Java-Gaming.org Hi !
 Featured games (90) games approved by the League of Dukes Games in Showcase (789) Games in Android Showcase (234) games submitted by our members Games in WIP (864) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
Pages: [1]
 ignore  |  Print
 Phys2D Performing a Collision please need your help  (Read 11721 times) 0 Members and 1 Guest are viewing this topic.
kapocris

Senior Newbie

 « Posted 2009-12-06 17:26:05 »

Ok, Hi all. This is my first post.

Phys2d lib is wonderful but there's something that I couldnt manage yet. How to perform a collision ?

I know how to detect a collision when two bodies touch using  Arbiter, Contact classes.
I can list the bodies, the point of collision, but how do I apply movement to body2 when body1 touches it ?  I am making an "AirHockey" game.

This is my first attempt which of course does not work (I wouldnt be here asking for help, hehe)

I thought I could use static method collide but I think I am not invoking it the right way because nothing happens. Note that body1/body2 must be the pusher/puck (there are other bodies in the world, "the walls").

public void detectsColision(){
Body body1 = null;
Body body2 = null;
ArbiterList arbs = world.getArbiters();
Arbiter arb = null;
if(arbs.size() > 0){
for(int i=0;i<arbs.size();i++){
arb = arbs.get(i);
int numContacts = arb.getNumContacts();
if(numContacts > 0){
Contact[] Contacts = arb.getContacts();

Vector2f punto = (Vector2f)Contacts[0].getPosition();
body1 = arb.getBody1();
body2 = arb.getBody2();
System.out.println("BODY1: "+body1+" BODY2: "+body2);
if(body1.equals(this.puck) && body2.equals(this.pusher) ||
(body1.equals(this.pusher) && body2.equals(this.puck)))
Collide.collide(Contacts, this.puck, this.pusher,1000);
}
}
}

Also, the harder the collision, the higher the speed of the puck, I have no idea how to implement that.

h3ckboy

JGO Coder

Medals: 5

 « Reply #1 - Posted 2009-12-06 17:52:16 »

couldnt you just give the pusher force, and then that force will be transfered to the puck on contact?
Bonbon-Chan

JGO Coder

Medals: 12

 « Reply #2 - Posted 2009-12-07 08:23:21 »

I don't really get what you want to do. When two bodies collide, Phys2D calculates forces to bump them back. You can play with mass and coef to change how bodies react from collision.

Now in your case, when you detect a collision (like you do), calculate the forces to push back body and apply them with the Body.setForce(float x,float y) method.
kapocris

Senior Newbie

 « Reply #3 - Posted 2009-12-07 12:15:57 »

Thanks both of you for your responses. I'm going to explain myself better. I have two bodies in the world (besides the walls which represent the limits of the table).

The pusher: I set its position by invoking setPosition method every time a mouseEvent (mouseMoved) occurs. The method I posted above allows me to indentify when a collision between pusher-puck has occured and also the exact point of collision. When this happens, the pusher just drags the puck, it does not transmit a force at the point of collision so that the puck moves in the right direction.

Think of a pool game, when the stick hits a ball, the stick stays static after the impact while the ball is moved.

If I use the addForce method that you describe, when both bodies collide, the puck does not take the proper direction and  the pusher starts moving aswell.

It's obvious that I am missing something. Please if you just could give me a hand with this.
Bonbon-Chan

JGO Coder

Medals: 12

 « Reply #4 - Posted 2009-12-07 13:12:01 »

The Body.setPosition() method moves a body not like dragging it but like you teleport it : it doesn't get a speed.

I see 2 solutions :
- don't use Phys2D collision schem to init the move. Detect manualy the collision (circle against circle is not difficult) then convert the mouse/body speed to initial speed or a force for the puck.
- use Phys2D collision schem. Set pusher weight like 80000(g), the puck 250(g). Move the pusher with the Body.setForce() method. The problem of this method is the latency between the mouse move and the pusher move.

I would go solution 1 myself.
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #5 - Posted 2009-12-07 17:09:28 »

I don't know if that's the issue. If you use setPosition with Phys2D, Bonbon-Chan is right that you're sort of breaking the system, but this really only turns the collision system from continuous to discrete. Wherever the pusher is, collision should result (if it exists). By directly moving it, you only eliminate the steps in between each position. If your position is updating frequently enough, however, then this should unnoticeable.

Either way the pusher should be a static body, and the puck shouldn't.

Did you add both bodies to the world?

See my work:
OTC Software
Bonbon-Chan

JGO Coder

Medals: 12

 « Reply #6 - Posted 2009-12-08 08:12:11 »

I don't know if that's the issue. If you use setPosition with Phys2D, Bonbon-Chan is right that you're sort of breaking the system, but this really only turns the collision system from continuous to discrete. Wherever the pusher is, collision should result (if it exists). By directly moving it, you only eliminate the steps in between each position. If your position is updating frequently enough, however, then this should unnoticeable.

If I have understand his problem, the collision system works but the resulting speed after the collision is wrong since the pusher don't have the expected speed before the collision.
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #7 - Posted 2009-12-09 15:59:46 »

If I have understand his problem, the collision system works but the resulting speed after the collision is wrong since the pusher don't have the expected speed before the collision.

Oh, on that I think you're right. As I recall Phys2D just violently pushes things off each other if there is overlap.

In any case it's unwise to directly set position in a physics-based environment, so you would indeed be better off if you dampen the velocity of the pusher a lot (give it a lot of friction) and then just apply velocity. If you do this, you can simulate direct setting of position without breaking your physics system.

See my work:
OTC Software
kapocris

Senior Newbie

 « Reply #8 - Posted 2009-12-12 16:12:59 »

The Body.setPosition() method moves a body not like dragging it but like you teleport it : it doesn't get a speed.

I see 2 solutions :
- don't use Phys2D collision schem to init the move. Detect manualy the collision (circle against circle is not difficult) then convert the mouse/body speed to initial speed or a force for the puck.
- use Phys2D collision schem. Set pusher weight like 80000(g), the puck 250(g). Move the pusher with the Body.setForce() method. The problem of this method is the latency between the mouse move and the pusher move.

I would go solution 1 myself.

I need to ask you a couple more questions, I'm still confused.

- By manually detect the collision, this would be enough, right ?

Contact[] Contacts = arb.getContacts();
int x = (int) Contacts[0].getPosition().getX();
int y = (int) Contacts[0].getPosition().getY();

- About the mouse speed, you mean that I need to capture the pusher's center initial point/time (when mouse starts movement, the pusher's center final point/time (when the pusher hits the puck), then calculate distance between them an divide it by time...that would be the speed right?

-Once I have collected all this info, what am I supposed to do? You said I needed to convert the mouse speed to a force for the puck but how? Simply using puck.addForce() does not produce the desired effect.

I get that I am teleporting the pusher instead of actually moving it so it transmits its speed to the puck. All I'm doing is calling puck.addForce() when a collision occurs, and then passing as coordinates contact.x and contact.y but of course the puck moves too fast, or too slow, sometimes it moves in the wrong direction.

I'm so sorry to bother you, this little game is causing me much more trouble than I expected.

Thanks again both of you.
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #9 - Posted 2009-12-12 23:24:27 »

You shouldn't be doing the collision manually. Instead, you should just avoid moving the pusher instantly, and instead change its velocity.

To do that, give the pusher a lot of friction and change its velocity to match the change in mouse position. Then just hide the mouse so that instead of an exact 1:1 movement ratio, it will work more like in an fps (move the mouse left, the pusher moves left, move the mouse right, the pusher moves right). That should work much better.

See my work:
OTC Software
kapocris

Senior Newbie

 « Reply #10 - Posted 2009-12-13 11:41:35 »

You shouldn't be doing the collision manually. Instead, you should just avoid moving the pusher instantly, and instead change its velocity.

To do that, give the pusher a lot of friction and change its velocity to match the change in mouse position. Then just hide the mouse so that instead of an exact 1:1 movement ratio, it will work more like in an fps (move the mouse left, the pusher moves left, move the mouse right, the pusher moves right). That should work much better.

Ok, I understand your perspective and I also think it should work better. However, here's the problem.

I set a start position for the pusher. When mouse enters the board (which is a jPanel implementing a MouseMotionListener) mouseMoved event fires. So I capture new position for the mouse. Now that I've got it, How do I use it ? Directly passing it to pusher.adjustVelocity(e.getX(),e.getY()) method results in the pusher moving to the right. No matter the direction I move the mouse, the pusher will move to the right until it goes outside the board. So there's the problem. As you said, if I move the mouse to the left, pusher should go to left but it goes to the right no matter what.

I understand that friction must be really high since the pusher can only move in half of the board, I don't want it to cross the middle line or the goal, is that ok if I set it like setFriction(10000)  ?

I appreciate so much your responses, this is a final project for one subject, so it is really important for me.

h3ckboy

JGO Coder

Medals: 5

 « Reply #11 - Posted 2009-12-13 13:44:29 »

waht you need to do is check on what side the cursor is AFTER it has moved, and just move towards there.

I suppose you could use a 2d Vector
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #12 - Posted 2009-12-13 18:36:58 »

Ok, I understand your perspective and I also think it should work better. However, here's the problem.

I set a start position for the pusher. When mouse enters the board (which is a jPanel implementing a MouseMotionListener) mouseMoved event fires. So I capture new position for the mouse. Now that I've got it, How do I use it ? Directly passing it to pusher.adjustVelocity(e.getX(),e.getY()) method results in the pusher moving to the right. No matter the direction I move the mouse, the pusher will move to the right until it goes outside the board. So there's the problem. As you said, if I move the mouse to the left, pusher should go to left but it goes to the right no matter what.

I understand that friction must be really high since the pusher can only move in half of the board, I don't want it to cross the middle line or the goal, is that ok if I set it like setFriction(10000)  ?

I appreciate so much your responses, this is a final project for one subject, so it is really important for me.

Yeah, that's how you set the friction as I recall, but I also think I remember that using a value like 1000 for friction will be way too high. You might want to look into the docs or just experiment until you get a value that works, but start with like 0.5 and work your way up.

To get the change in mouse position, do this:

 1  2  3  4  5  6  7  8  9  10  11 `int lastMouseX, lastMouseY;public void mouseMoved(MouseEvent e){    int changeX = e.getX() - lastMouseX;    int changeY = e.getY() - lastMouseY;    //Note that I don't remember the exact method call for this.    pusher.adjustVelocity(changeX, changeY);}`

You're going to want to add to the velocity, not set it directly. That will look a little better.

See my work:
OTC Software
Bonbon-Chan

JGO Coder

Medals: 12

 « Reply #13 - Posted 2009-12-14 08:14:34 »

Ok back from a business trip

When I was speaking to do collision manually, it was to avoid all problem of latency between the pusher and the mouse (all depend if it is acceptable or not in your game). I was thinking of something like :
 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38 `int lastMouseX, lastMouseY;long lastTime;public void mouseMoved(MouseEvent e){    int px = e.getX();                  // px,py is the position of the pusher.    int py = e.getY();                  // the pusher is NOT in the Phys2D world and is NOT a body    long pt = e.getWhen();    double dx = this.puck.getPosition().getX()-e.getX();    double dy = this.puck.getPosition().getY()-e.geY();    double l  = Math.sqrt(dx*dx+dy*dy);    if(l < r_puck+r_pusher)   { // Collision      dx /= l;      dy /= l;      double mouse_speed_x = (double)(px-lastMouseX)/(double)(pt-lastTime);      double mouse_speed_y = (double)(py-lastMouseY)/(double)(pt-lastTime);         double speed = mouse_speed_x*dx+mouse_speed_y*dy; // mouse speed projection on direction      double induce_speed_x = dx*speed*COEF; // COEF has to be determinated      double induce_speed_y = dy*speed*COEF;      puck.setSpeed(induce_speed_x,induce_speed_y); // If you are sure that puck do not have any speed      puck.setForce(induce_speed_x,induce_speed_y); // Else   }   else  {     lastMouseX = px;     lastMouseY = py;     lastTime = pt;  }}`

You can make it better. It can be use or not depending of your game. If pusher can only collide with puck, it can be a good solution.
kapocris

Senior Newbie

 « Reply #14 - Posted 2009-12-14 19:10:55 »

Finally some progress !    I want to thank Demonpants,h3ckboy and of course Bonbon-Chan, I hope you had a great trip.

The puck now moves in the right direction. I literally copied your solution, just made a couple of changes (like not allowing the pusher run across the puck, stuff like that). I was playing with it and it feels very realistic.

I still have some doubts, I'd be glad if you can give me ideas...remember this is my first game ever.

Suppose I hit the puck once and now it is moving in one direction. If I hit it for a second time in the exact opposite direction it will simply get stuck in one of the static rectangles I use as barriers. I mean, it gets inside of them.

I did like you said, if puck is moving apply force instead of adjusting velocity (I tried both methods anyways)

The same happens if I push the puck very fast, in that case it doesn't matter if it is the first time the puck is being hit or not.

Some more data:

coef is set to 75
puck friction to 0
puck weight to 250

As I always say, any clue / information that you can give is very appreciated.
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #15 - Posted 2009-12-14 19:20:57 »

Finally some progress !    I want to thank Demonpants,h3ckboy and of course Bonbon-Chan, I hope you had a great trip.

The puck now moves in the right direction. I literally copied your solution, just made a couple of changes (like not allowing the pusher run across the puck, stuff like that). I was playing with it and it feels very realistic.

I still have some doubts, I'd be glad if you can give me ideas...remember this is my first game ever.

Suppose I hit the puck once and now it is moving in one direction. If I hit it for a second time in the exact opposite direction it will simply get stuck in one of the static rectangles I use as barriers. I mean, it gets inside of them.

I did like you said, if puck is moving apply force instead of adjusting velocity (I tried both methods anyways)

The same happens if I push the puck very fast, in that case it doesn't matter if it is the first time the puck is being hit or not.

Some more data:

coef is set to 75
puck friction to 0
puck weight to 250

As I always say, any clue / information that you can give is very appreciated.

Really if you're circumventing Phys2D in one place it's possibly going to cause problems in another place - that's just how it goes. You either have to use entirely Phys2D (in which case you don't want to manually set anything, you want adjust everything), or you're going to have to constantly write your own adjustments to Phys2D, until finally you've basically rewritten the whole engine.

Anyway, if you really want to try another hotfix, maybe you should just manually check for collision with the walls, and if it ever exists manually move the puck off the wall onto the correct side.

See my work:
OTC Software
Bonbon-Chan

JGO Coder

Medals: 12

 « Reply #16 - Posted 2009-12-15 08:14:25 »

Quote
The same happens if I push the puck very fast, in that case it doesn't matter if it is the first time the puck is being hit or not.

When I use Phys2D, I have to pass a long trial&error course. First, I play with the frictions and weight to try to have the speeds that I want. Then I play with coef used in collision. And last, I play with the number of steps used by frame to avoid object to pass through another.

It can be a good idea to do several World.step() in one frame (you will have to decrease the speed of all objects). It lets Phys2D to do more accurate collision detections.

For friction, if you set 0 it is like "perfect ice" : your puck will never stop moving. As I remember, I allways use friction near 1 and very little change can do a big difference.
kapocris

Senior Newbie

 « Reply #17 - Posted 2009-12-15 12:05:24 »

Ok guys, It's done. It took me some time to find out the problem: "pt" and "lastTime" sometimes were equal, that means "mouse_speed_x" and "mouse_speed_y" were Infinity and that's why the puck simply disappeared from the board when it was hit too fast.

The only problem is that if pusher is not moving collision will simply not be detected and the puck will go through it.
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #18 - Posted 2009-12-15 14:59:40 »

Ok guys, It's done. It took me some time to find out the problem: "pt" and "lastTime" sometimes were equal, that means "mouse_speed_x" and "mouse_speed_y" were Infinity and that's why the puck simply disappeared from the board when it was hit too fast.

The only problem is that if pusher is not moving collision will simply not be detected and the puck will go through it.
You could force it to always be moving by a very very tiny amount.

See my work:
OTC Software
Bonbon-Chan

JGO Coder

Medals: 12

 « Reply #19 - Posted 2009-12-15 15:12:16 »

I think you problem is a more general problem on your game design. For dynamic games, I avoid using anything that deal with event.

For example when dealing with awt/swing, MouseEvent / KeyboardEvent only store mouse/keyboard state in a Mouse/Keyboard object. Then I deal with the input in the logic/rendering loop.

So in your case, I would test collision every frame and not only when an event occured.
h3ckboy

JGO Coder

Medals: 5

 « Reply #20 - Posted 2009-12-15 16:02:39 »

do you have the world.step() in your updating method or do you only do it whent he mouse is moved?

cause that would kinda make a difference
kapocris

Senior Newbie

 « Reply #21 - Posted 2009-12-17 18:25:28 »

What I did is to add a temporary static body in the exact position the pointer is resting so that the puck crashes against it instead of going through it, also  I adjusted puck's dumping and the achieved effect is pretty realistic to me. When mouse moves again I delete the temporary body from the world. I know this solution is trash but hey...it works.

There's something that I still need to know : How do you know when a body is moving or not ?

Finally, I see some light at the end of the tunnel...
h3ckboy

JGO Coder

Medals: 5

 « Reply #22 - Posted 2009-12-17 18:49:13 »

chekc the api....

there is probably a getVelocity() somewhere in the body class.
Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #23 - Posted 2009-12-18 16:51:43 »

What I did is to add a temporary static body in the exact position the pointer is resting so that the puck crashes against it instead of going through it, also  I adjusted puck's dumping and the achieved effect is pretty realistic to me. When mouse moves again I delete the temporary body from the world. I know this solution is trash but hey...it works.

There's something that I still need to know : How do you know when a body is moving or not ?

Finally, I see some light at the end of the tunnel...
Instead of deleting and recreating a body every time the mouse moves, why not directly change the position of the same body?

See my work:
OTC Software
kapocris

Senior Newbie

 « Reply #24 - Posted 2009-12-29 19:51:54 »

Instead of deleting and recreating a body every time the mouse moves, why not directly change the position of the same body?

Because It's like I'm teleporting the pusher around the world instead of actually moving it so it has a velocity....I figured it out...can't waste any more time on the physics...it works...that's what matters right? this is my first proyect, my professor is pushing me, deadline is pusing me...you know.

Pages: [1]
 ignore  |  Print

 hadezbladez (2618 views) 2018-11-16 13:46:03 hadezbladez (946 views) 2018-11-16 13:41:33 hadezbladez (2573 views) 2018-11-16 13:35:35 hadezbladez (510 views) 2018-11-16 13:32:03 EgonOlsen (3739 views) 2018-06-10 19:43:48 EgonOlsen (4137 views) 2018-06-10 19:43:44 EgonOlsen (2496 views) 2018-06-10 19:43:20 DesertCoockie (3303 views) 2018-05-13 18:23:11 nelsongames (3399 views) 2018-04-24 18:15:36 nelsongames (4377 views) 2018-04-24 18:14:32
 cygnus 15x Spasi 12x SkyAphid 12x orange451 12x FabulousFellini 9x VaTTeRGeR 8x KaiHH 8x philfrei 7x SHC 5x NuclearPixels 5x BitBotz 5x Speiger 4x elect 3x orangepascal 3x Ecumene 2x yboya 2x
 Java Gaming Resourcesby philfrei2019-05-14 16:15:13Deployment and Packagingby philfrei2019-05-08 15:15:36Deployment and Packagingby philfrei2019-05-08 15:13:34Deployment and Packagingby philfrei2019-02-17 20:25:53Deployment and Packagingby mudlee2018-08-22 18:09:50Java Gaming Resourcesby gouessej2018-08-22 08:19:41Deployment and Packagingby gouessej2018-08-22 08:04:08Deployment and Packagingby gouessej2018-08-22 08:03:45
 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