2
\$\begingroup\$

I am trying to port a game I made using Flash/AS3, to the Windows Phone using C#/XNA 4.0. You can see it here: http://goo.gl/gzFiE

In the flash version I used a pixel-perfect collision between meteors (it's a rectangle, and usually rotated) that spawn outside the screen, and move towards the center, and a shield in the center of the screen(which is half of a semi-circle, also rotated by the player), which made the meteor bounce back in the opposite direction it came from, when they collided.

My goal now is to make the meteors bounce in different angles, depending on the position it collides with the shield (much like Pong, hitting the borders causes a change in the ball's angle).

So, these are the 3 options I thought of:

  1. Pixel-perfect collision (Microsoft has a sample) , but then I wouldn't know how to change the meteor angle after the collision

  2. 3 BoundingCircle's to represent the half semi-circle shield, but then I would have to somehow move them as I rotate the shield.

  3. Farseer Physics. I could make a shape composed of 3 lines, and use that as the collision object for the shield.

Is there any other way besides those? Which would be the best way to do it(it's aimed towards mobile devices, so pixel-perfect is probably not a good choice)? Most of the time there's always a easier/better way than what we think of...

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Are you able to detect the collision between arc and body? Can your body be approximated by a circle (kinematically speaking)? \$\endgroup\$
    – FxIII
    Nov 25, 2011 at 17:06
  • 1
    \$\begingroup\$ Title: is that half of a semicircle, or just a semicircle? \$\endgroup\$
    – 3Dave
    Nov 25, 2011 at 17:28

1 Answer 1

1
\$\begingroup\$

Your approach is way to complicated. You don't need pixel perfect collision detection or a physics-engine. Actually you just need the radius of your shield, the direction normal of your shield (a vector pointing from the world center to the middle of your arc) and the delta of the incoming vector to your world center.

Let's declare some stuff:

  • Rs is the radius of your shield
  • thickness thickness of the shield
  • Re is the radius of the earth
  • Vs is the normal of your shield (eg. where the shield is pointing at, viewing from the center of "earth")
  • Vm is the vector from the earth center to the meteor.

You'll need just some dot-products to solve your problem. In pseudo code:

// get distance from meteor to earth and normalize Vm
distance = normalize(Vm)

if(distance < Re){
    // meteor hit the earth :(
    return;
}

// check if meteor is in the range of the shield
if(distance < Rs + thickness && distance > Rs - thickness){
    // the dot product will give an indication whether the shield
    // faces the meteor or not
    facing = dotProduct(Vs, Vm)

    // angle will be the angle of impact (usually in radians)
    angle = acos(facing)

    // facing will be greater than zero when the shield faces the meteor
    if(facing > 0 && angle < PI / 4){
        // deflect the meteor here
        deflectMeteor()
    }
}

Update:

To actually perform the deflection of the meteor, you can simply "reflect" the meteor normal with the shield normal (using the variables used above, make sure Vm is normalized):

newDirection = (2 * facing * Vm) - Vs;
\$\endgroup\$
6
  • \$\begingroup\$ thanks for replying @bummzack. I've been struggling to get this to work... The shield seems to be rotated 90 degrees in a counter-clockwise direction. The variable angle keeps returning something between 1.2 and 1.6 when the shield is correctly placed. Also, I don't think it's correct to normalize Vm then compare it to the shield/earth radius :). \$\endgroup\$ Nov 28, 2011 at 17:38
  • \$\begingroup\$ Yes, this is assuming that the shield points to the right with rotation = 0. As mentioned, the angle is in radians and where do I compare Vm to the shield/earth radius? In the above example, I'm assuming normalize returns the magnitude of Vm before normalization. That's a common functionality, as you can save yourself a sqrt operation. \$\endgroup\$
    – bummzack
    Nov 28, 2011 at 17:43
  • \$\begingroup\$ @heitortsergent Btw. here's a small flash test-example that uses the exact procedure as described above: swfcabin.com/open/1322498516 (sorry for the red lines in there :)) \$\endgroup\$
    – bummzack
    Nov 28, 2011 at 17:45
  • \$\begingroup\$ Oh, I see. I thought normalize would turn Vm into a unit vector :). And rotation = 0 on my shield points it up, so that makes sense... Thanks a lot for the flash example too, it's working perfectly now :D. \$\endgroup\$ Nov 28, 2011 at 19:06
  • \$\begingroup\$ @heitortsergent You are correct, normalize turns Vm into a unit-vector. But since the process of normalization needs to calculate the magnitude, a "good" normalize would return the magnitude of the vector that it had before normalization. I don't know if that's the case with the XNA implementation though \$\endgroup\$
    – bummzack
    Nov 28, 2011 at 19:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .