Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (601)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [LibGDX] Linking a Sprite (Or another image) to a Box2D Body  (Read 6342 times)
0 Members and 2 Guests are viewing this topic.
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Posted 2013-05-20 09:53:17 »

I have a body and a sprite which I want to link to that body.
My first idea was to set Sprite position to body position like this:
1  
2  
3  
4  
//(Inside my sprite's update method)
Vector2 bodyPos = new Vector2(body.getPosition().x - ship.getDimensions().x / 2, body.getPosition().y - ship.getDimensions().y / 2);
      ship.setPosition(bodyPos);
      ship.setRotation((float) Math.toRadians(body.getAngle()));


Because I am just drawing one or two bodies and sprites to see how things work, so far there are no problems with that method.

But then I accidentally found out about body.setUserData(Object) method. Wondering if this has any advantages or deals with something I have not encountered or thought about, I went to libgdx documentation and found this (at https://code.google.com/p/libgdx/wiki/PhysicsBox2D):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
Iterator<Body> bi = world.getBodies();
                   
while (bi.hasNext()){
    Body b = bi.next();

    // Get the bodies user data - in this example, our user
    // data is an instance of the Entity class
    Entity e = (Entity) b.getUserData();

    if (e != null) {
        // Update the entities/sprites position and angle
        e.setPosition(b.getPosition().x, b.getPosition().y);
        // We need to convert our angle from radians to degrees
        e.setRotation(MathUtils.radiansToDegrees * b.getAngle());
    }
}


So if I have only one body and not an array of bodies and sprites, it will be like this:
1  
2  
3  
4  
body.setUserData(mySprite);

(when rendering)
(Sprite)body.getUserData().setPosition(values);

Right? Because I don't have many bodies and certainly I don't need an iterator.

So, is this method only useful with many bodies? Or is it my method wrong or inefficient?

The other question is, I have my sprite in one class and body in another class (Actually I have a static method which creates a body wherever I want etc). These two do not know about each other. That is to say, no references, no parameters about each other.
Should I write them like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
//Sprite constructor
public MySprite(parameters, no body parameters){
}

//Body constructor
public MyBody(other parameters, Object userData){
//other code
body.setUserData(userData);
}


I hope you can enlighten me with your ideas and knowledge Smiley

EDIT: Dammit, I just realized there is a MathUtils class Cheesy
Offline Kerai

Junior Devvie


Medals: 4



« Reply #1 - Posted 2013-05-20 11:57:01 »

I think the proper way should be this:

You have an Entity class, which holds reference to a Body and a reference to Sprite

your game loop should go in this order

1  
2  
3  
4  
5  
6  
7  
box2d.update(whatever)

for(Entity ent :entities) {
   ent.update(); // entity logic like AI, inputs, etc. At the end it updates Sprite position to match a Body position
}

//render sprites


Sprites should be held in different structure, optimal for rendering.

Body's UserData should hold reference to its Entity - not to loop through bodies. It's useful for collision detection. Box2D lets you add listeners and filters to your world... so you can detect when your bullet collides with a player, etc. your listeners would receive to Bodies. you can identify them by their UserData
Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #2 - Posted 2013-05-20 18:58:27 »

I am sorry, I can't understand. What should the entity class look like?
You say Entity class should hold reference to body and sprite. And you say Body's userdata should hold reference to its entity. That sounded confusing to me. It might be because English is not my native language, but I just didn't understand.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Jimmt
« League of Dukes »

JGO Kernel


Medals: 139
Projects: 4
Exp: 3 years



« Reply #3 - Posted 2013-05-20 21:46:47 »

Correct me if I'm wrong, but I thought the userData was mostly for collision info with contactlisteners. I think your original method was fine.
Online pitbuller
« Reply #4 - Posted 2013-05-20 22:45:33 »

Correct me if I'm wrong, but I thought the userData was mostly for collision info with contactlisteners. I think your original method was fine.

User data is just pointer to any data that you want. Also its only sane way to do mapping from body to entity.
Offline heisenbergman

JGO Coder


Medals: 14


L___ o_ G___ a__ P___


« Reply #5 - Posted 2013-05-21 01:18:02 »

I think your original method was fine.
+1

The original method on the OP is the same way I do it and I think it's fine as well.

Also its only sane way to do mapping from body to entity.

What do you mean by "do mapping from body to entity"? What are you referring to with "entity"? I'm asking because I'm interested in how to utilize userData...

Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #6 - Posted 2013-05-21 09:49:15 »

I'm asking because I'm interested in how to utilize userData...

Usually it's used for storing the java side object representing the Entity. When a collision happens, the Entity should be notified. But upon collision, you only get the Box2D Body, so you have to save user data (the entity to call the #collide(Entity) method) Smiley

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline heisenbergman

JGO Coder


Medals: 14


L___ o_ G___ a__ P___


« Reply #7 - Posted 2013-05-21 10:09:28 »

I'm asking because I'm interested in how to utilize userData...

Usually it's used for storing the java side object representing the Entity. When a collision happens, the Entity should be notified. But upon collision, you only get the Box2D Body, so you have to save user data (the entity to call the #collide(Entity) method) Smiley
Hm... I don't quite understand.

Sorry if I'm sounding a bit slow, but... why should the Entity be notified? (I'm still not sure I also understand what is being referred to as the Entity... is it synonymous to Object?)

Online Jimmt
« League of Dukes »

JGO Kernel


Medals: 139
Projects: 4
Exp: 3 years



« Reply #8 - Posted 2013-05-21 16:13:02 »

Usually in games the Entity class represents anything in the game world, be it a weapon or enemy. The Entity should be connected to the box2D body because otherwise it's hard to process what body hit what other body.
Offline heisenbergman

JGO Coder


Medals: 14


L___ o_ G___ a__ P___


« Reply #9 - Posted 2013-05-21 21:45:38 »

But what I do is that the body is a part of the Entity class...

...am I doing it wrong?

Huh

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Jimmt
« League of Dukes »

JGO Kernel


Medals: 139
Projects: 4
Exp: 3 years



« Reply #10 - Posted 2013-05-21 21:48:07 »

Yes, but when you use contactlistener it can only give you the fixtures/bodies that collide.
Offline heisenbergman

JGO Coder


Medals: 14


L___ o_ G___ a__ P___


« Reply #11 - Posted 2013-05-22 00:38:23 »

Sorry, I'm probably not explaining myself right... I'm coming from the perspective of "But wait... I'm handling collisions without the use of userData... does that mean I'm doing it wrong?"

How I do it is for example I have a class called MyCoin that represents a coin in the game, and it contains a Box2D Body. Now, during gameplay, I want the coin to disappear when the player comes into contact/collides with it (meaning the player has picked it up). What I do now is that I have all the coins stored in a Vector called coins; and upon collision, I loop through that Vector to check:

(1) Is one of the fixtures the player body?
AND
(2) Is the other fixture a coin?

At which point, if both are true, I do all the stuff that should happen (e.g. money increases) and then queue the coin for destruction after the world step. So, like this:

1  
2  
3  
4  
5  
6  
for (int i = 0; i < coins.size(); i++) {
    if ((fixtureA.getBody().equals(coins.elementAt(i).getBody()) && fixtureB.getBody().equals(myPlayer.getBody()))
     || (fixtureB.getBody().equals(coins.elementAt(i).getBody()) && fixtureA.getBody().equals(myPlayer.getBody()))) {
        // do everything related to the coin getting picked up
    }
}

It occurred to me as I was implementing this that having to loop through collections of certain objects repeatedly upon collision is probably not the best way to do things from a performance standpoint. Also, I wanted specific objects of the same class to have significantly different behavior, it would probably be a pain to handle.

But I couldn't think of another way to do it. Now, if userData will help me achieve this, I'm all ears Smiley Please help. TIA!

Offline kutucuk

Senior Devvie


Medals: 5
Exp: 3 years



« Reply #12 - Posted 2013-05-22 03:14:10 »

Great conversation took place here while my connection was broken Smiley Thanks guys.

So, let me wrap things up and see if there is something wrong in what I understood;
- I should do the logic part with box2d (obviously, it is the physics part), and rendering part with an entity class (So, MyShip class is an entity class?) assuming that I want to separate logic and render (which is the efficient thing to do).
- UserData is there to make collision detection easier? If I link my entity to a body using user data, I can determine which entity hit which one easier (like if(body.getUserData == myEntity) {//do stuff}
Quote from: matheus23
Usually it's used for storing the java side object representing the Entity. When a collision happens, the Entity should be notified. But upon collision, you only get the Box2D Body, so you have to save user data (the entity to call the #collide(Entity) method)
- A Body userdata could (or should?) be an entity.
- What we call entity is nothing more than our objects in the game. Like, the character, the enemy, the bullets, and weapons?

- Basicly, there is nothing wrong with my method, but I still can (or should?) link the body and entity using UserData, and updating the entities using my method or the method in the libgdx page is up to me. And if I use UserData, I also have an advantage like this:
1  
2  
3  
4  
5  
6  
if(body1.getUserData() == ship){
// do not explode the ship, check health first
}
if(body2.getUserData()  == bullet){
//just make the bullet disappear
}

Offline heisenbergman

JGO Coder


Medals: 14


L___ o_ G___ a__ P___


« Reply #13 - Posted 2013-05-22 03:41:51 »

Sorry, I'm probably not explaining myself right... I'm coming from the perspective of "But wait... I'm handling collisions without the use of userData... does that mean I'm doing it wrong?"

How I do it is for example I have a class called MyCoin that represents a coin in the game, and it contains a Box2D Body. Now, during gameplay, I want the coin to disappear when the player comes into contact/collides with it (meaning the player has picked it up). What I do now is that I have all the coins stored in a Vector called coins; and upon collision, I loop through that Vector to check:

(1) Is one of the fixtures the player body?
AND
(2) Is the other fixture a coin?

At which point, if both are true, I do all the stuff that should happen (e.g. money increases) and then queue the coin for destruction after the world step. So, like this:

1  
2  
3  
4  
5  
6  
for (int i = 0; i < coins.size(); i++) {
    if ((fixtureA.getBody().equals(coins.elementAt(i).getBody()) && fixtureB.getBody().getUserData().equals(myPlayer.getBody()))
     || (fixtureB.getBody().equals(coins.elementAt(i).getBody()) && fixtureA.getBody().getUserData().equals(myPlayer.getBody()))) {
        // do everything related to the coin getting picked up
    }
}

It occurred to me as I was implementing this that having to loop through collections of certain objects repeatedly upon collision is probably not the best way to do things from a performance standpoint. Also, I wanted specific objects of the same class to have significantly different behavior, it would probably be a pain to handle.

But I couldn't think of another way to do it. Now, if userData will help me achieve this, I'm all ears Smiley Please help. TIA!
Adding to this... if I do the following inside the MyCoin class:

1  
body.setUserData(this); // to store this MyCoin instance inside the body

How can I use getUserData() inside the collision listener to determine that the body is linked to a MyCoin instance? Meaning... how do I complete this if-statement?
1  
2  
3  
4  
if ((fixtureA.getBody().getUserData.equals(/*what can I put here to determine that this is MyCoin?*/) && fixtureB.getBody().equals(/*what can I put here to determine that this is MyPlayer?*/)) 
 || (fixtureB.getBody().getUserData.equals(/*what can I put here to determine that this is MyCoin?*/) && fixtureA.getBody().equals(/*what can I put here to determine that this is MyPlayer?*/))) {
    // do everything related to the coin getting picked up
}

Offline 65K
« Reply #14 - Posted 2013-05-22 05:57:01 »

Looking out for certain collisions and handling them with user data. Pushing user data into type specific working variables.
This approach works for all entities of a certain class.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
// disable droid-bullet collisions if between shooter and own bullet because bullets are fired from the center of the body
world.setContactFilter(new ContactFilter() {

         @Override
         public boolean shouldCollide(Fixture fixtureA, Fixture fixtureB) {
            Object userDataA = fixtureA.getBody().getUserData();
            Object userDataB = fixtureB.getBody().getUserData();

            Droid droid = cast(userDataA, userDataB, Droid.class);
            Bullet bullet = cast(userDataA, userDataB, Bullet.class);
            if (droid != null && bullet != null) {
               if (bullet.getShooter().equals(droid)) {
                  return false;
               }
            }

            return true;
         }
      });


1  
2  
3  
4  
5  
6  
7  
8  
9  
private <O> O cast(Object object1, Object object2, Class<O> expectedClass) {
      if (expectedClass.isAssignableFrom(object1.getClass())) {
         return (O)object1;
      }
      if (expectedClass.isAssignableFrom(object2.getClass())) {
         return (O)object2;
      }
      return null;
   }

Offline heisenbergman

JGO Coder


Medals: 14


L___ o_ G___ a__ P___


« Reply #15 - Posted 2013-05-22 06:10:16 »

^ whoa...



I like it.

I may implement something similar in my code if I could also get around everything else that my current implementation requires Smiley  Thanks!

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

rwatson462 (30 views)
2014-12-15 09:26:44

Mr.CodeIt (20 views)
2014-12-14 19:50:38

BurntPizza (42 views)
2014-12-09 22:41:13

BurntPizza (76 views)
2014-12-08 04:46:31

JscottyBieshaar (37 views)
2014-12-05 12:39:02

SHC (51 views)
2014-12-03 16:27:13

CopyableCougar4 (48 views)
2014-11-29 21:32:03

toopeicgaming1999 (115 views)
2014-11-26 15:22:04

toopeicgaming1999 (103 views)
2014-11-26 15:20:36

toopeicgaming1999 (31 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!