Mommy's Best Games, Inc. is an independent game developer founded in 2007. This is a view behind the scenes of our game development and marketing!

Nathan

Saturday, September 18, 2010

Grenade Throw Equation

So the player has your cool soldier dude is hunkered down behind a barricade. Your soldier can't get a shot off at the player, but he can lob a grenade. He throws the grenade, it flies through the air... oh .. umm.. wow. The grenade just flew way over the player's head. Probably because the player was in a slight depression, lower than the soldier's Y position, and you just estimated the grenade's velocity, cobbling something together.

Time to fix that!
Explosionade is our next game, and it features lots of grenades and plenty of explosions. We'll have the official announcement shortly, but I wanted to pull some physics-y code from it for your use!

Here's my game-ready grenade velocity function. It's simple parabolic motion, straight out of wikipedia, but for some reason, sometimes, I'm too lazy too even look that up and rework the equation! So I reworked it for you (and my lazy future-self, when I need it again).



Here's some C# code for the equation.

// targetPos is what you want to hit
// throwPos is where the grenade starts
// Tweak flyTime to make the grenade take longer or shorter to get there
// This simple returns the velocity at which to throw the grenade, and your target is toast!
static float flyTime= 2.0f;
protected Vector2 ThrowGrenadeVel(Vector2 targetPos, Vector2 throwPos)
{
 Vector2 diff = (targetPos - throwPos);
 Vector2 grenadeVel;
 startVel.X = (diff.X) / travelTime; // we don't factor in gravity for X

 // Handles different heights nicely
 startVel.Y = (diff.Y - 0.5f * Grenade.gravityY * flyTime* flyTime) / flyTime;
            return startVel;     }
The player mech on the left anticipates a grenade hit from the enemy Horronyms on the right. Horronyms conveniently have three arms, two for holding their gun, one for throwing grenades, natch.


Simple enough, it uses s = s0 + v0t + 1/2at^2 but reworks it for the initial velocity (v0) here. You just need to have your Grenade.gravityY specified as static public float in your Grenadeclass (or whatever you're using there). I used a gravityY of about 500.0f. Two seconds felt pretty good, giving the player some time to dodge it or shoot it in Explosionade. But you can tweak the flyTime to take longer or shorter. Be aware this does no checking for ceilings, or walls. You'll have to do line of sight tests for those.
 If you use the equation and have any problems just leave a comment. Good luck throwing!

9 comments:

CJ Currie said...

Are you using physics and ForeceMode.VelocityChange? If so, what do you use for the starting angle?

CJ Currie said...

Never mind... for a moment it looked like you were using the Unity3D engine, but I may be wrong. The basis of my question still stands... more extrapolation, please.

Daniel said...

Hmmmm...
I'm currently learning C++ during breaks in my University courses, seeing all this C# makes me wonder who hard will it be to switch between the two...

On the other hand I can't wait to see your new game! Are the screens from it? Or is it just Grapple Buggy?

Nathan Fouts said...

CJ Currie,
This equation gets you the starting velocity (a vector). From this you can calculate the starting angle (if you need it to rotate a gun to face the vector for instance). You can get the angle with arc tangent as such:
newAng = Math.Atan2(dir.Y, dir.X);

Daniel,
C# is pretty fast in terms of development.
This game is called Explosionade (the image with the grenade shot is a close up of the game.)
Good luck with school!

Daniel said...

Ohhh

Looks like I should have read the whole post before commenting X(

addmore games said...

We did a very simple and fast raycasting algorithm for polygon objects for our game ToyBorgs: http://www.youtube.com/watch?v=O2Tbx0BTrnQ (watch the bots)

May be we could share this too.

btw: An ingame video of our game:
http://www.youtube.com/watch?v=l2ZAMQlNIYU

I am very interested in seeing more infos like that from you. Thanks for sharing :)

jeffery said...

how do you do this in 3d and find out the ending position though?

jeffery said...
This comment has been removed by the author.
Nathan Fouts said...

===3D VERSION===

@jeffrey
It's almost the same, but you have to account for the Z component. That means treat it just like the X.
(Assuming that Y is your up/down direction).
In that case, X and Z are just moving around on the ground (not up/down).

So use a Vector3 instead.
Vector3 diff = (targetPos - throwPos);
Vector3 grenadeVel;

startVel.X = (diff.X) / travelTime;

startVel.Y = (diff.Y - 0.5f * Grenade.gravityY * flyTime* flyTime) / flyTime;

startVel.Z = (diff.Z) / travelTime;

Make sense?