Adding vector from another moving object...

Started by
38 comments, last by mwkenna 12 years, 7 months ago
Aw crud, it's me again. [grin] Here's an easy one...

              ------    .
             |      |  .
             |Moving| .
   ----->    | Box  |.  <-- Circle collides here
Box's travel |      | .
direction    |      |  o
              ------
Let's say in the above example that the 'Moving Box' is moving along vector (1, 0) at a speed of 300. Let's also say that the 'Circle' is moving along the vector (-0.707, 0.707) at a speed of 400. If I perform a standard reflection against the Moving Box, the Circle's new vector will be (0.707, 0.707) which would make its X speed roughly 282... The problem with that is the Moving Box will overtake the circle, since it's traveling along the X at 300. I want to keep the Circle's speed at 400... How do I change the vector of the Circle so that it just outruns the Moving Box? Thanks in advance for the help!
"The crows seemed to be calling his name, thought Caw"
Advertisement
Find a vector for the circle whose X component is greater than or equal to the X component of the box's movement vector. (Note that I find it a tad easier to treat the vectors as full velocity vectors rather than unit vectors multiplied by velocity).

So if vx2 + vy2 = v2, vx = 300, and v = 400, solve for vy and get sqrt(70000), or ~265. So the velocity vector for the circle should be <300,-265>, which you can convert to a unit vector if you like.

Hope that helps,
Twilight Dragon
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
You could try looking for the equations needed to implement a more physically accurate collision.

In this particular case, the velocity of the object the ball is bouncing off of should be considered. If the reflection is done relative to the moving box's frame of reference, it should have the proper effect. The x velocity relative to the box is -0.707 - 1 = -1.707. Reflecting this gives a velocity of 1.707.

The equations for collisions provide a more general solution than this that works for any collision direction and with objects that both have mass. I think when one object has infinite mass, the equations reduce to something like a reflection.
Note to the AP: You're right, but also keep in mind that the OP was using unit vectors for the direction and specifying the velocity separately, so the numbers you gave weren't entirely accurate.
{[JohnE, Chief Architect and Senior Programmer, Twilight Dragon Media{[+++{GCC/MinGW}+++{Code::Blocks IDE}+++{wxWidgets Cross-Platform Native UI Framework}+++
let have two objects A and B, with velocity vector 'va' and mass 'ma', and B with velocity vector 'vb' and mass 'mb'.

Also have the collision normal 'nab', the collision normal of A impacting on B.

also, have a coefficient of restitution 'cor', or how hard the collision will be (very hard collision, cor = 1.0f, very soft, cor = 0.0f).

from the conservation of momentum, you can derive the collision impulse

let vab = (va - vb), or the relative velocity of object A from object B's point of view.

if(vab . nab > 0.0f), the objects are moving away from each other, so return;

the collision impulse will be
j = -(1 + cor) * (vab . nab) / (1/ma + 1/mb);

then

va += (j * nab) / ma;
vb -= (j * nab) / mb;


in short

bool Bounce(Vector va, float ma, Vector vb, float mb, Vector nab, float cor){    Vector vab = (va - vb);    float  vn  = vab.DotProduct(nab);    if (vn > 0.0f) return false;    float j = -((1.0f + cor) * vn) / (1/ma + 1/mb);    va += (j * nab) / ma;    vb -= (j * nab) / mb;    return true;}

Everything is better with Metal.

Oh oops...well the x velocity of the ball relative to the box is -282.8 - 400 = -682.8, so reflecting that gives a velocity of 682.8. Also it is easier to just use a velocity vector than a direction vector and a speed.
Cool, thanks again!

So if I change the code a bit to work for my own application, it should be as follows:

bool Bounce(float* va, float ma, float* vb, float mb, float* nab, float cor){    float vab[2], vn, j;    vab[0] = (va[0] - vb[0]);    vab[1] = (va[1] - vb[1]);    vn = vab[0]*nab[0] + vab[1]*nab[1];    if (vn > 0.0f) return false;    j = -((1.0f + cor) * vn) / (1/ma + 1/mb);    va[0] += (j * nab[0]) / ma;    va[1] += (j * nab[1]) / ma;    vb[0] -= (j * nab[0]) / mb;    vb[1] -= (j * nab[1]) / mb;    return true;}


I'd send the function the objects' vectors stored in the floats 'va[2]' and 'vb[2], and the collision normal 'nab[2]'. I'd also send it the floats 'ma' (mass of A) and 'mb' (mass of B), as well as the float 'cor' (hardness of collision). Would you proof-read the above and make sure I have it correct? Thanks! [smile]

I'm presuming vectors 'va' and 'vb' are scaled to include the speed of the objects, which means their velocities are going to change after the collision takes place. I'll have to experiment with this to see if I can get it to work with my Breakout-style game, where I want the ball's velocity to remain constant even after colliding with a moving block (only the ball's travel vector should change to avoid being overrun by the block, not its velocity), and I don't want the block's velocity or trajectory to change at all.

Thanks again for the info, oliii! If I can't get this to work with my breakout game, I'll definitely be able to use this for a platform game I have planned in the near future.
"The crows seemed to be calling his name, thought Caw"
that system should work as it is.

To keep the ball speed relatively unchanged, you'll need a high value for cor (0.99), and a high mass for the paddle (100.0), and a low mass (1.0) for the ball, so most of the energy from the collision is transfered from the paddle towards the ball.

I'd also advocate an artificial system to keep the ball velocity constant, like add a little bit of velocity to the ball every frame if it's too low, because there is always some FP innacuracies over time, and making inifnite or 0 mass will cause you problems, and the system, as it is, will still loose energy (mass not infinite, but you can't and should not do that anyway).

Also, be careful with the ball moving too fast, as well as the paddle, and make sure you nudge the ball away from the paddle in case of an intersection (using the MTD), and then apply the collision response like above (using the normalised MTD).

Everything is better with Metal.

Sorry it took a while to respond, I was trying to get oliii's idea along with my rather finite knowledge of vector math to work together in my game. [wink]

And ya know what? It works Great! Thanks oliii, for helping me to get that collision detection to work in my game! I was using two separate routines (one for right-oriented blocks and one for angled blocks), and that wasn't working well because sometimes a collsion would be prematurely detected for a block that was buried behind another block. Heh, you'd probably cringe if you saw the code for my game.

I only have one question about that collision detection scheme... If the ball is moving along and it clips the corner of a block, sometimes it will detect the collision and then process the 'bounce' routine but the ball's vector won't change.

 ------       .| Block|     .  <== Ball's Trajectory before collision|      |    .|    --|---|   |  |   | ------    |    | Ball |     ------    .   .  <== Ball's Trajectory after collision  .


This only happens very occasionally, and it doesn't seem to matter how fast the ball is travelling or whether or not the block is a moving block. It only seems to happen if the very tip of the corner of the ball quad and the tip of the corner of a block quad collide (very small collision; "glancing blow"), not when there's a 'major' collision (ball smacks into the side of the block). Hard to explain, so I'm hoping you've seen this issue in action. If you have seen this in action, do you know how to make this work every time? Like I said, it happens very rarely but it's distracting when you're playing a fast and furious game and the ball doesn't ricochet like you'd expect.

Thanks again for all the help, I really appreciate it!
"The crows seemed to be calling his name, thought Caw"
I have a theory...

Are you calculating the amount of intersection and multiplying that to the final vector? then maybe the intersection is to low in the above case...?

You could cheat, and do a simple "if collision is detected, and resulting vector is lower than a certain reflective angle, set it to that angle"...
In this type of game, I think most people would think it's ok. :D
"Game Maker For Life, probably never professional thou." =)

This topic is closed to new replies.

Advertisement