# Asteroids-like collision detection/physics & rounding speed

• 07-28-2009
Brafil
Asteroids-like collision detection/physics & rounding speed
Basically there are two problems. The first one is easy (in a 2D world):

The entities in the project have positions stored as float points. But a screen has only ints as pixels. So, is rounding floats to ints appropriate? Since if I just take the floor, the objects move sloppy (stays the same, then jumps, stays the same etc). What would you do?

The second one not so easy:

So, let's say the players (spaceships) have position, rotation, scale and a center. If a player touches the screen borders, it should bounce realistically. For example:

assume the player looks like a giant 'U'.

Code:

```|  | |  | |___|```
if it's rotated 45 degrees to the right and collides with the top, like

Code:

```__________     X   /   /  / C /  \  /   \/```
(Where X is the point of collision and C the mass center of the object)

In this case, the point X is a bit to the right of C, so the object should rotate a bit to the right and be pushed down.

There is a force acting directly down from point X (ignore friction for now). How should I implement this?

So, the basic idea is implementing forces with a position and direction. But how to calculate the resulting rotation/translation of the object? I think this needs some trig. Don't matter.

My ideas are:
If the force's direction vector points to the center of an object (beginning at the force point), the translation is equal to the direction and the rotation is none. But if the vector points 90 degrees to the left/right, the translation is none and there is only rotation.
• 07-28-2009
MK27
Quote:

Originally Posted by Brafil
Basically there are two problems. The first one is easy (in a 2D world):

The entities in the project have positions stored as float points. But a screen has only ints as pixels. So, is rounding floats to ints appropriate? Since if I just take the floor, the objects move sloppy (stays the same, then jumps, stays the same etc). What would you do?

Apparently, openGL uses floats internally (for everything) and your variable will be converted if you use ints, which is inefficient -- so in other words, always use floats and use >=, <= never == with collision stuff.

Which I have only done a bit of 2D collision so I can't add much more. Although I am sure there must be 90000 pages online to do with your second question(s). I guess it depends on how "realistic" you want the physics; I always like collision stuff that involves the appearance of a little bit too much reciprocating energy, eg. so head-on they actually bounce away faster than the speed they started at, which looks neat and adds to the viewing excitement, but probably is not very realistic, physics wise. My other fav technique there is incorporating a significant random potential, eg, so they may speed up, or slow down, or the trajectory may be too oblique. That ain't real at all, it's almost better than real! Unless your goal is emulating something specific these are subjective questions of style.
• 07-28-2009
VirtualAce
Asteroids is simple and you don't need tons of physics in it if you don't have to have it.
• 07-29-2009
Brafil
I didn't mean asteroids. I only thought of the game containing asteroids-style elements.

And I don't want tons of physics, but still a bit better collision response. The game shall be fun, not realistic, and I think just a floating spaceship which can't go out of bounds is not enough.

But it shouldn't be like a physics simulation. I'm just adding some toys (like friction in empty space. It is not fun to play if you gotta stop it manually).

EDIT @MK27: Nice idea. I'll add some randomness, too. Like the engines breaking if you try to go too fast (maybe they won't) ;-p
• 07-29-2009
dwks
Quote:

The entities in the project have positions stored as float points. But a screen has only ints as pixels. So, is rounding floats to ints appropriate? Since if I just take the floor, the objects move sloppy (stays the same, then jumps, stays the same etc). What would you do?
I'd definitely store positions as floating-point numbers (probably doubles, but floats work as well), and then round to ints for display purposes. One nice thing about this is that if you want to support different screen resolutions, or in-game zooming, then you just use a different factor for the conversion to integers. The internal floating-point representation can remain the same. If you decide to do this you could say, for example, that the screen is 1.0 by 1.0 (or 100.0 or 100.0, but I'd recommend 1.0 by 1.0) units in size, and then keep track of everything (position, velocity, acceleration, etc) in this coordinate system. Then you can map the coordinate system to any view you like (a different size window, a mini-map in the corner, whatever).

Quote:

(like friction in empty space. It is not fun to play if you gotta stop it manually.
You can also map a key like down or backspace to "brake"; it accelerates you in the opposite direction that you're moving, so that if you hold it down long enough you'll come to a complete stop.
• 07-29-2009
Brafil
I have this brake key, but the game is kinda difficult only with it.

BTW: I have managed to rotate the sprite if it touches the upper screen. But how can I make it rotate smoothly? Not just like flipping?
• 07-29-2009
VirtualAce
Code:

```... ... void Object::Update(float timeDelta) {   m_vecVel += m_vecAcceleration * timeDelta;   m_vecPos += m_vecVel * timeDelta;   //Bounce off sides of screen   if (m_vecPos.x <= Screen.left || m_vecPos.x >= Screen.right)   {       m_vecVel.x = -m_vecVel.x;   }   if (m_vecPos.y <= Screen.top || m_vecPos.y >= Screen.bottom)   {       m_vecVel.y = -m_vecVel.y;   } } void Object::Thrust(float units) {     m_vecAcceleration.x += cosf(m_vecRotation.z) * units;     m_vecAcceleration.y += sinf(m_vecRotation.z) * units; } void Object::RotateLeft(float units,float timeDelta) {     m_vecRotation.z += units * timeDelta; } void Object::RotateRight(float units,float timeDelta) {     m_vecRotation.z -= units * timeDelta; } ... ...```
This should do what you want. Note that mass is not taken into effect nor have I computed any mass moment of inertia's, etc.
• 07-30-2009
Brafil
Nice. Only that the acceleration is zero if the user doesn't press up or down (in my case).

When bouncing off, should I apply a torque and force to the object? They will be a bit random.

And how can I decrease the x and y-velocity at the same amount? For simulating friction?
• 07-30-2009
VirtualAce
Do you want me to write the game for you? I gave you a place to start and you come back and ask other questions that are obviously only pertinent to your system. I don't know how your system works but surely you can integrate my suggestions into your code.
• 07-31-2009
Brafil
No. I've been implementing nearly exactly what you said. The only thing was if I should round or not, performance-wise. I know that I can profile, but I wanted to know what others do (learn by example, :-), not how they do it.

Basically I know what to do know. I'll apply a small force in the right direction (I can calculate that) and a torque. I'll look at some other games for seeing how they do it.
• 07-31-2009
MK27
Quote:

Originally Posted by dwks
I'd definitely store positions as floating-point numbers (probably doubles, but floats work as well), and then round to ints for display purposes.

I know dwks does this way more than I, but I still believe that in the end openGL converts all non-floats to floats, so that is sort of silly. Maybe you should round to an integer value instead (or is that what was meant)?
• 07-31-2009
brewbuck
Quote:

Originally Posted by Brafil
And how can I decrease the x and y-velocity at the same amount? For simulating friction?

Normal sliding friction is a force directed opposite to the direction of travel and proportional to the velocity. Therefore, to apply friction:

Code:

```velocity = sqrt( vx * vx + vy * vy ); frictionForce = k * velocity; vx -= sign(vx) * frictionForce * timeStep; vy -= sign(vy) * frictionForce * timeStep;```
Where sign(foo) gives -1 if foo is negative, and 1 if foo is positive.

This is the PHYSICALLY CORRECT way to apply friction. However, for game purposes, you can simulate friction without performing that expensive sqrt() operation by simply decreasing the velocity proportionally:

Code:

```vx *= drag; vy *= drag;```
Where drag is some number between 0 and 1.

There is also a fast, approximate method for computing sqrt( vx * vx + vy * vy ) without actually taking a square root, and this might be accurate enough for your purposes. But I'd start with the "drag" method and see how good it feels.

There are other things to consider. Friction force can never REVERSE the direction of the velocity, but this finite timestep approximation can cause that to occur. So you would need some more complicated checks -- if the velocity changes sign, set it to zero instead. Again, the drag method does not have this problem.
• 07-31-2009
MK27
Quote:

Originally Posted by brewbuck
Friction force can never REVERSE the direction of the velocity

If the ship were covered in chewing gum it could :p
• 07-31-2009
VirtualAce
Round to ints is pointless. Most graphics hardware works natively with floats anyways. The days of ints being faster and floats being slower have long since passed.