Need help: Launching an object with a trajectory

I’m attempting to make my first real physics-based game, and I’m having a bit of trouble.

 

I have a ball which I am throwing from the lower right of the screen (off the screen).   Then, I want it to be thrown in an arc upwards, then come down at the lower left of the screen.    

 

The problem is, the ball is too slow, and the trajectory is way off that I can’t even get it to arc properly… it ends up arcing at the top left of the screen rather than the middle.   I’ve tried linearImpulse and also setLinearVelocity and the same problem happens.  I’m hard-coding the numbers for the parameters and going by trial-and-error, so I don’t know if this is the right approach and whether I should use a mathematical formula for this.

 

Here’s my code… hoping someone knowledgeable can help me out with this:

  local group = scene.view   local pos\_x = g.max\_x()\*1.5    local pos\_y = g.max\_y()   ball\_info[id].obj = display.newCircle(pos\_x, pos\_y, ball\_info.radius)   physics.addBody(ball\_info[id].obj, "dynamic", {friction = 0, density = 1.3})   group:insert(ball\_info[id].obj)   ball\_info[id].obj:setLinearVelocity( -1000, -700 )   --ball\_info[id].obj:applyLinearImpulse( -700, -400, pos\_x, pos\_y )

The arc will depend on several factors:

  • size of the ball

  • density of the ball

  • strength and direction of the impulse

  • gravity

So to get the desired result, you need to tweak all those factors (except gravity, you can just leave that at default).

Here’s a code snippet that launches a ball in an arc from the bottom right of the screen.

local physics = require("physics") physics.start() local ball = display.newCircle(display.contentWidth, display.contentHeight, 10, 10) physics.addBody(ball, {density = 1}) ball:applyLinearImpulse(-2, -10)

You can also Google David McClusky’s github and use his trajectory library. I don’t remember if its physics-based, but it is pretty useful.

Hi @dislam,

This tutorial about “predicting trajectory” might give you some guidance to move forward:

http://coronalabs.com/blog/2013/04/09/physics-radial-gravity-and-predicting-trajectory/

Take care,

Brent

 

Success!  This helped, thank you Brent!

 

All I had to do was reverse this function:

function getTrajectoryPoint( startingPosition, startingVelocity, n ) --velocity and gravity are given per second but we want time step values here local t = 1/display.fps --seconds per time step at 60fps local stepVelocity = { x=t\*startingVelocity.x, y=t\*startingVelocity.y } local stepGravity = { x=t\*0, y=t\*9.8 } return { x = startingPosition.x + n \* stepVelocity.x + 0.25 \* (n\*n+n) \* stepGravity.x, y = startingPosition.y + n \* stepVelocity.y + 0.25 \* (n\*n+n) \* stepGravity.y } end

Since I already know my final x and y (it’s going to end up at the bottom left corner of screen), I just reversed the function to return the startVelocity.x and startingVelocity.y instead.   

 

I also am using n=180, to get the position at the 180th frame (60 fps x 3 seconds).

 

So this is how I got the velocity:

local sample = {} sample.t = 1 / display.fps sample.gravity\_x = 0 sample.gravity\_y = sample.t \* 9.8 local start\_x = g.max\_x() local start\_y = g.max\_y()\*0.8 local final\_x = 0 local final\_y = g.max\_y() local throw\_time = 3 local n = display.fps \* throw\_time sample.velocity\_x = (final\_x - start\_x - 0.25\*(n\*n+n)\*sample.gravity\_x) / n sample.velocity\_y = (final\_y - start\_y - 0.25\*(n\*n+n)\*sample.gravity\_y) / n local velocity\_x = sample.velocity\_x / sample.t local velocity\_y = sample.velocity\_y / sample.t

Then I used the physics properties listed in the fireProj function, and applied the velocity I got from above:

physics.addBody(ball\_info[id].obj, "dynamic", {bounce=0.2, density = 1.0, radius=14}) ball\_info[id].obj:setLinearVelocity( velocity\_x, velocity\_y )

Cheers!

The arc will depend on several factors:

  • size of the ball

  • density of the ball

  • strength and direction of the impulse

  • gravity

So to get the desired result, you need to tweak all those factors (except gravity, you can just leave that at default).

Here’s a code snippet that launches a ball in an arc from the bottom right of the screen.

local physics = require("physics") physics.start() local ball = display.newCircle(display.contentWidth, display.contentHeight, 10, 10) physics.addBody(ball, {density = 1}) ball:applyLinearImpulse(-2, -10)

You can also Google David McClusky’s github and use his trajectory library. I don’t remember if its physics-based, but it is pretty useful.

Hi @dislam,

This tutorial about “predicting trajectory” might give you some guidance to move forward:

http://coronalabs.com/blog/2013/04/09/physics-radial-gravity-and-predicting-trajectory/

Take care,

Brent

 

Success!  This helped, thank you Brent!

 

All I had to do was reverse this function:

function getTrajectoryPoint( startingPosition, startingVelocity, n ) --velocity and gravity are given per second but we want time step values here local t = 1/display.fps --seconds per time step at 60fps local stepVelocity = { x=t\*startingVelocity.x, y=t\*startingVelocity.y } local stepGravity = { x=t\*0, y=t\*9.8 } return { x = startingPosition.x + n \* stepVelocity.x + 0.25 \* (n\*n+n) \* stepGravity.x, y = startingPosition.y + n \* stepVelocity.y + 0.25 \* (n\*n+n) \* stepGravity.y } end

Since I already know my final x and y (it’s going to end up at the bottom left corner of screen), I just reversed the function to return the startVelocity.x and startingVelocity.y instead.   

 

I also am using n=180, to get the position at the 180th frame (60 fps x 3 seconds).

 

So this is how I got the velocity:

local sample = {} sample.t = 1 / display.fps sample.gravity\_x = 0 sample.gravity\_y = sample.t \* 9.8 local start\_x = g.max\_x() local start\_y = g.max\_y()\*0.8 local final\_x = 0 local final\_y = g.max\_y() local throw\_time = 3 local n = display.fps \* throw\_time sample.velocity\_x = (final\_x - start\_x - 0.25\*(n\*n+n)\*sample.gravity\_x) / n sample.velocity\_y = (final\_y - start\_y - 0.25\*(n\*n+n)\*sample.gravity\_y) / n local velocity\_x = sample.velocity\_x / sample.t local velocity\_y = sample.velocity\_y / sample.t

Then I used the physics properties listed in the fireProj function, and applied the velocity I got from above:

physics.addBody(ball\_info[id].obj, "dynamic", {bounce=0.2, density = 1.0, radius=14}) ball\_info[id].obj:setLinearVelocity( velocity\_x, velocity\_y )

Cheers!