Peggle Trajectory Aim

What: I’m trying to make a Peggle style aiming system, for anyone not familiar here’s a youtube of Peggle (note the aiming system at the top of the screen): http://www.youtube.com/watch?feature=player_detailpage&v=ZMo2Vegh8hA#t=195s

It’s essentially a downward trajectory shot, taking gravity into account.

Background: I did a lot of searches on trajectory examples in Unity and here’s the issue I ran into. They all seem to assume you are firing along the horizontal or X axis (Angry Birds or Worms for example). Indeed most math I looked up to explain trajectories seems to assume you want to shoot to the left or right on the horizontal axis (whereas I want to always shoot down on the Y or vertical axis).

This results in shooting the ball UP before it falls, producing some awkward shots. I want it to shoot down but with some force and taking into account gravity (ala Peggle).

To help you help me, here’s what I’m working off of.

  1. I can grab the X,Y coordinate of the mouse using essentially this which is called during Update():
function GetXY()
{
	ray = cannonCamera.ScreenPointToRay(Input.mousePosition); // create a ray from the mousePosition
	
	if (plane.Raycast(ray, dist)) //dist is a float from the ray start to the hit point
	{
		aimPoint = ray.GetPoint(dist); //aimPoint is a Vector3 describing where the mouse is hovering
		desiredShot = aimPoint - transform.position; //desiredShot is a Vector3 between our mouse cursor and the cannon making the shot
		desiredShot.z = 0; //leaves us with just X,Y
	}
}
  1. I can return the theta or angle of the mouse cursor using the trig circle, which means when aiming down that I return an angle somewhere between 180 and 360 (which looks like this):

  2. Just to give you a visual example of #1 and #2 in action, here is the game returning the X,Y position and Angle of the mouse position on screen:

Help: Can someone give me guidance on how I can accomplish this downward trajectory shot, what would be the appropriate equation? Am I thinking/approaching this wrong?

I originally tried trajectory solutions I found searching Unity Answers but they have the issue my above webplayer has (for example, Calculating ball trajectory in full 3d world - Questions & Answers - Unity Discussions). I tried using the math here, but to no avail: Non-Horizontally Launched Projectile Problems.

Any help would be deeply appreciated, I’ve tried for days here with no luck! Code samples are useful but even just pointing me towards the right formula would be extremely useful, it’s been 15 years since I’ve done any trig! Thanks!

Skeptika

Edit: I’m thinking about trying this: Trajectory of a projectile formula. Does anyone know maths? - Questions & Answers - Unity Discussions which is using this: Projectile motion - Wikipedia (go down to Angle to hit coordinate X,Y)… is this the approach I should be taking? If so, once I calculate the Theta required, how do I actually convert this into a fired shot (rotate object to appropriate Theta and fire transform.forward with assumed force)?

I came up with an elegant solution for this. I place two empty transforms in the barrel of the gun and child them to that gun. The transforms, I call nozzle1 and nozzle2. I place nozzle1 at the base of the gun barrel, and nozzle2 at its tip. what this does, is allows me to always know, the trajectory if the gun barrel.

you see?

Then, at fire() I just get the rise and run (nozzle2.y -nozzle1.y) and (nozzle2.x-nozzle1.x) and voila. I have a trajectory vector.

I know how to get a straight like trajectory, but per Peggle, I’m trying to get an arc trajectory. If I understand you properly, that’s just returning a straight line (which I already return anyway per the picture up above between the cannon and the mouse cursor).

The idea is to return the lowest angle to achieve an X,Y position, so the ball looks like it’s shooting downwards with an arc.

Why would gravity not work?

Gravity works fine, I think you’re misunderstanding (or I’m misunderstanding you). The goal in it’s simplest form is to: have the ball go where the mouse cursor is, including gravity. This cannot be accomplished with a straight line trajectory unless you disregard gravity.

Since I’m not disregarding gravity, and gravity is key in a Peggle style game, you have to predict either the Angle or the Velocity you must launch the projectile at to hit your target position (which is a parabola or arc). As I understood what you were suggesting, that’s not an arc, that’s a straight line and not at all what I’m trying to accomplish. Unless I’m really, really misunderstanding you :wink:

Ok,
I am sorry, I misunderstood you.

After thinking bout it, and looking it up, as this is something I have thought about after playing Angry Birds I believe you need to look at Inverse Trigometric Functions. The way I see it is, you have a vector, the direction of gun fire. This could be consider a tangent to the curve you desire.

You also have a distance. The distance between the end of the gun barrel and the input pos.

I am betting, that with these two pieces of information, + gravity, you can calculate a curve.

I think inverse sin or inverse tan. Geometry is not really my thing tho. Algebra is. But, I bet, this would be the route.

No worries, I’ve seem similar questions a lot within Unity and no terribly good answers. I might have bitten off more than I can chew here, my math is rusty.

To maybe reframe the question for anyone brave enough to jump in after I’ve tried a few more things:

  • Given X,Y coordinates which will always be at the bottom of the Trigonometry Circle (from 180-360 degrees) and
  • Given a firing speed (I just assume it)
  • I want to return the Angle necessary to make the shot (including gravity).
  • I want to then rotate my cannon towards that Angle.

In theory then, if the Angle calculation is correct, simply firing forward with the assumed speed should always hit the X,Y coordinates. I tried using this unsuccessfully: Trajectory of a projectile formula. Does anyone know maths? - Questions & Answers - Unity Discussions.

Next up I’ll try this:

Hi,
I looked into this a bit more. And while it is not much, yes you do want the arctangent. Further, minus calculating the arc and displaying the proper gun rotation, what you can gather very easily is, the rise and run of the triangle that makes up the space between the end of the gun and the input position. I am guessing, as it might not be 100% right, but it is the arc of this tangent that you want.

I would suggest you have a length, or distance limit for the arc display. Meaning, if you nose pos is x 0 y - 32 that the display nodes showing the arc, only reach 10 units. So, your tangent can only be ten in length.

I don’t know if that helps at all. I am sure the answer is very simple and elegant… To a professor. This is some very tricky math. I would be interested in finding out if you find the solution.

Got it working with some slight hackery. I’ve essentially increased the speed by reducing the time to get the low angle of launch rather than solve it out elegantly, but it works and behaves just like a Peggle shot. Buried deep in a UnityAnswer, works for me!

private Vector3 calculateBestThrowSpeed(Vector3 origin, Vector3 target, float timeToTarget) {
    // calculate vectors
    Vector3 toTarget = target - origin;
    Vector3 toTargetXZ = toTarget;
    toTargetXZ.y = 0;
 
    // calculate xz and y
    float y = toTarget.y;
    float xz = toTargetXZ.magnitude;
 
    // calculate starting speeds for xz and y. Physics forumulase deltaX = v0 * t + 1/2 * a * t * t
    // where a is "-gravity" but only on the y plane, and a is 0 in xz plane.
    // so xz = v0xz * t => v0xz = xz / t
    // and y = v0y * t - 1/2 * gravity * t * t => v0y * t = y + 1/2 * gravity * t * t => v0y = y / t + 1/2 * gravity * t
    float t = timeToTarget;
    float v0y = y / t + 0.5f * Physics.gravity.magnitude * t;
    float v0xz = xz / t;
 
    // create result vector for calculated starting speeds
    Vector3 result = toTargetXZ.normalized;   // get direction of xz but with magnitude 1
    result *= v0xz;                    // set magnitude of xz to v0xz (starting speed in xz plane)
    result.y = v0y;                    // set y to v0y (starting speed of y plane)
 
    return result;
}

I receive the target through the mouseaim code I gave in the first post, and then just: rigidbody.AddForce(throwSpeed, ForceMode.VelocityChange).

1 Like

You looked at the wrong formula.

You needed to use Angle Of Reach (http://en.wikipedia.org/wiki/Trajectory_of_a_projectile)

Im failing to see the elegance.

That’s when I thought he was just asking how to get the angle of a projectile. Not the angle plus gravity, curve, plot line etc. so your failure is worthy.

actually the best response ever! :slight_smile:

LoL

For now, I’ll work on the art before heading back into to coding to do the mouse-aim previewing (drawing the arc). Cheers guys.