collision reaction not working properly for simple objects

Topics: Developer Forum, User Forum
Oct 22, 2008 at 1:48 PM
Edited Oct 22, 2008 at 1:51 PM
hello,

I am trying to implement farseer in my 2D top down RPG engine.

Currently I'm just toying around with the collision system. All I have right now is a player walking around a tiled map. The player is size 64x64 and the tiles are 32x32.

So when I load the map, all the 'solid' tiles I create geom / bodies for, making them static, and setting their width/height to 32/32, and their position to the world position of the tile minus 16 on both x & y (to make up for it being center based rather then top left).

Then when I load the player, I create a geom/body for him, and set the width/height to the sprite width/height minus 32/32 (again, to make up for it being center based).

So I load up the game - and like magic, my player is now colliding with walls!! Awesome I think. So now I need to determine when a collision happens so I can take action (set the players velocity to 0, so they stop moving when they collide with a wall).

So I handle the players Geomoetry.Collision event...

Now here's my problem - after a collision, the players position is not being re-set properly to be along the edge of the wall. So once the player hits a wall, and I don't touch the keypad any longer to move him... the Collision event fires *constantly* over and over.... and when I check the players position, he is not fully adjusted to be along the edge of the wall. So If I have a 1 tile thick wall on the left side of the map, and the player runs into it... his new X position should be 32... however, it is not after collision... isntead it is something like 31.95555, or 27.333, or something like this...

Visually, it appears to work fine. But obviously it is not actually working fine because the player is not adjusting properly and instead he is moving not past the collision boundary, causing constant collisions unless I manually walk away from the wall..

All the geoms / bodies are simple rectangles created using the factories. There is no gravity at all in the game (its set to 0,0) because this is a top down / 3/4ths view RPG. Also, my character is moving by manully adjusting the bodies position when the key is pressed (something like physicsBody.Position += velocity * timePasssed). I am not using forces or anything fancy - my requirements are very simple - I just need very simple AABB collision against walls and other moving objects!!!

Any idea what the problem is? I can begin posting code, however perhaps there is something obvious I'm missing. Thanks again!!!
Coordinator
Oct 22, 2008 at 2:18 PM
Edited Oct 22, 2008 at 2:20 PM
Try using the PhysicsSimulatorView from the Farseer samples to see what's going on. I'll give a short description in a moment.

When 2 geometries collide, a collision response is calculated so that a "normal" physics reaction is applied to the geometry. Instead of setting velocity to 0, you could set RestitutionCoefficient to 0. This means that the object will not bounce at all away from the wall.

Anyways, about the penetration problem. Farseer was not designed to be used with setting position of a object manually. This can cause penetration into other geometries and a proper collision response can't be calculated since the velocity of the body is 0. (it's standing still while you are moving it manually)

I've never tried something like this myself, so I don't have any good solution for you right now.
 
I'm always using force to move characters and other objects. If you want to simulate him walking and then suddenly stop (when key is released), set a high linear drag on him.

You can test it out in our samples. Open up Demo2.cs in the samples project and set LinearDragCoefficient to 15 on the rectangleGeom object.

Later down in the code, increase the force amount from 50 to 5000.
Just 2 numbers I quickly though off, you might want to tweak them to your preferences.

Edit: Use w,a,s and d buttons to move the geom.
Oct 22, 2008 at 5:27 PM
Thanks a lot for the reply genbox.

I did what you suggested - first altering the tutorial 2 the way you describe. The box now moves the way I want my game character to move like you said it would.

So I changed my game code, and instead of manipulating position directly, I use .ApplyForce(velocity*3000)

I also set the same LinearDragCoefficient (15) and set RestitutionCoefficient to 0 as well.

Well, my character is now moving again and colliding with walls... however, I still have the same issue! in the same case, after colliding with a wall along the left edge of the world, my characters x position stays at 31.95, which means I'm stick colliding over and over again, and my Colliding event never stops firing until I manually move the character away.

Any idea what the problem could be, and what variables I should try tweaking? So you are saying there's no way to manipulate velocity or position directly, and I should always use ApplyForce()?

EDIT: I just tried playing with all the variables, and it seems if i increase RestitutionCoefficient enough, it will bounce off the wall enough to prevent a constant collision. However then I have the 'bounce' affect, which really I don't want.. I just want the character to hug against the wall.

I should note, that I need only very simple AABB vs AABB collision for my game. Perhaps using farseer is overkill? I have to keep the physics VERY simple, because I am actually creating a 2D MMORPG engine... so I need only simple box-hits-another-box-then-moves-to-edge-and-stops type 'physics', and that's all. I was able to get player-> tile collision working myself, however getting 2 moving AABB's to collide with each other was starting to get complicated, which is when I found your library. Maybe you can suggest an alternative? Maybe there's lower level function I can use to solve my problem? OR should I just go back to the drawing board and write the moving aabb -> moving aabb collision myself?

Thanks again for any suggestions!
Coordinator
Oct 22, 2008 at 5:29 PM
@sensorium7: If you apply torque on each update, the torque of the body wil get greater all the time. When the body spins so fast that it syncs up with your monitor update rate, it will seem like it's spinning backwards. It's called the wagon wheel effect (http://en.wikipedia.org/wiki/Wagon-wheel_effect)

You can set the body rotation manually. Farseer will work with it correctly. In your case, you could use a slider joint and "boost" the orbiting object into orbit. to make this work correctly, you should have no drag and gravity. On collision with anything, you could dispose the joint.

This is just an idea. I just tested it and it seems to work okay. Not sure if it's what you want.



Coordinator
Oct 22, 2008 at 5:40 PM
Edited Oct 22, 2008 at 5:40 PM
@gfilla - About the physics, it all depends on your game. But if collisions is all you really need, Farseer might not be your solution. Simple AABB's would be the way to go, since you only have rectangles.

XNA provides a BoundingBox class. I can't remember if it supports rotation or not, but in your case, it might not even matter.

Back to the physics: Yes, increasing the RestitutionCoefficient would make the character bounce off the wall. RestitutionCoefficient of 0 means no bounce and 1 means perfect bounce, but again, you will be back to square one ;)

You character simply collides with the wall and does not get enough impulse to "blow" back from the collision. This is why your collision event is firing all the time. Up until now, you have been trying to omit the rules of physics in your game. Newton would be shamed of you. hehe.
You best bet might be to control everything by your self.

I do hope you will return with questions about another physics based game in the future. ;)