Displaying Angry Birds Style Trajectory Points

In some games, it is really helpful to show the trajectory of objects before they are launched. In this tutorial, we will learn how to do this with the help of mathematics and physics.

If you look below, you can see what we will achieve at the end of this tutorial. I used corona sdk as always but you can easily convert the code into your programming language, there is nothing specific to corona sdk or lua.

trajectory sample

Adding ball and defining variables

Ok, let’s start with adding our blue circle to the scene and defining some variables.

local ball = display.newCircle(100,200,10)
ball:setFillColor(0,0.7,1,0.2) 
ball.strokeWidth = 1 
ball:setStrokeColor(0,0.7,1)
local xStart = ball.x
local yStart = ball.y
local myLine
local trajectoryCircles = {}
local ballDirectionX
local ballDirectionY
local gravity = 0.1

Lines 1-4: Add your ball to the scene and give it color and stroke.
Lines  5-6: Define two variable to hold ball’s initial positions.
Line 7: We will draw a line between ball’s initial position and latest position and this variable will hold this lines.
Line 8: Define a table to hold the trajectory circles.
Lines 9-10: Define these to hold the myBall’s speed in each direction when it is launched.
Line 11: And of course we need gravity if we want our ball to reach the ground.

Adding touch event

Now we will add a touch event to our ball.

function ball : touch(e)
	if e.phase == "began" then
		display.getCurrentStage():setFocus( self )
	end

	if e.phase == "moved" then
		if myLine ~= nil then
			myLine : removeSelf()
			myLine = nil
		end
		
		ball.x = e.x
		ball.y = e.y
		myLine = display.newLine( xStart, yStart, ball.x, ball.y )
		ballDirectionX = (xStart - e.x) /15
		ballDirectionY = (yStart - e.y) / 15
	end

	if e.phase == "ended" then
		display.getCurrentStage():setFocus( nil )
	end
end

ball : addEventListener( "touch", ball )

Line 15: In the “began” phase of touch event set focus to the ball

Lines 19-22: In the “moved” phase we will draw a line between initial position of ball and the latest position but at first remove the line which is drawn at previous move

Lines 24-28: Set ball position to the touch event’s position to drag the ball. Draw a line between the initial position and the latest position. Find the direction vector from the latest position to initial position.This vector will be our ball’s velocity. I divided it by fifteen to make it a little bit smaller. If you want more information about vectors you may look at my tutorial about simulating radial gravity without using physics engine. I mentioned about 2d vectors in that tutorial.

Now if you run your code you will see this.

trajectory unfinished

Adding enterFrame event

Ok, it is time to move our ball after it is launched.
Add an enterFrame event to the runtime when touch event is ended.

Update the “ended” phase of touch event as below.

if e.phase == "ended" then
   Runtime : addEventListener("enterFrame", ball)
   display.getCurrentStage():setFocus( nil )
end

As you can see we added an enterFrame event to the runtime and made ball as listener of this event. So we should add a method to our ball with the name of enterFrame.

Add this between the local variable gravity and touch method of ball

function ball : enterFrame(e)
	ballDirectionY = ballDirectionY + gravity
	self.x = self.x + ballDirectionX
	self.y = self.y + ballDirectionY
end

Adding trajectory circles

And finally we will draw our trajectory. To do this, we will add little circles to the future positions of our ball.The only problem is, how we can know the coordinates of future positions?

If you look enterFrame method which is added to our ball above, you will see we are moving our ball with a certain calculation at each frame. We are adding ballDirectionX to the x coordinate of the ball and ballDirectionY to the y coordinate of it. And also we are updating ballDirectionY by adding gravity to it at each frame.

Then let’s use these calculations to find first four positions of our ball and try to find a formula for iteration.

For the x coordinate:

X position iteration

For the y coordinate:

Y position iteration

Now we can put this formulas into our code.

I’ve written the full code below. Lines 22-26 and 41-44 are the new ones. In the “began” phase of touch we are adding our circles to the scene and in the “moved” phase we are updating the position of our circles by using our formulas.

local ball = display.newCircle(100,200,10)
ball:setFillColor(0,0.7,1,0.2) 
ball.strokeWidth = 1 
ball:setStrokeColor(0,0.7,1)
local xStart = ball.x
local yStart = ball.y
local myLine
local trajectoryCircles = {}
local ballDirectionX
local ballDirectionY
local gravity = 0.1

function ball : enterFrame(e)
	ballDirectionY = ballDirectionY + gravity
	self.x = self.x + ballDirectionX
	self.y = self.y + ballDirectionY
end

function ball : touch(e)
	if e.phase == "began" then
		display.getCurrentStage():setFocus( self )
		for i = 1, 70, 1 do
			local trajectoryCircle = display.newCircle(ball.x,ball.y,2)
			trajectoryCircle.alpha = 0.5
			trajectoryCircles[#trajectoryCircles + 1] = trajectoryCircle
		end			
	end

	if e.phase == "moved" then
		if myLine ~= nil then
			myLine : removeSelf()
			myLine = nil
		end
		
		ball.x = e.x
		ball.y = e.y
		myLine = display.newLine( xStart, yStart, ball.x, ball.y )
		
		ballDirectionX = (xStart - e.x) /15
		ballDirectionY = (yStart - e.y) / 15
		for i = 1, #trajectoryCircles,1 do
			trajectoryCircles[i].x = ball.x + i*ballDirectionX 
			trajectoryCircles[i].y = ball.y + i*ballDirectionY + gravity*i*(i+1)/2
		end
	end

	if e.phase == "ended" then
		Runtime : addEventListener("enterFrame", ball)
		display.getCurrentStage():setFocus( nil )
	end
end

ball : addEventListener( "touch", ball )

To see If I draw the right trajectory, I don’t now remove the trajectory circles after the ball is launched but if you want to remove them you can add below lines in the “ended” phase of touch.

for i = #trajectoryCircles, 1, -1 do
   trajectoryCircles[i] : removeSelf()
   trajectoryCircles[i]  = nil
end

I wish you find this tutorial useful. Please don’t hesitate to ask questions in your comments.

3 thoughts on “Displaying Angry Birds Style Trajectory Points

  1. Great post! You definitely deserve more recognition for posting stuff like this.

    I’ve been messing around with this code for the past few days and I’m wondering if you know of anyway to shorten the delay between letting the ball go and it actually starting its trajectory?

    If not, thanks anyway man!

    Like

    1. Hi. Sorry for the late reply and thank you very much for your nice words. I started for this blog to help people and share my knowledge. You know it is not so easy to find this kind of tutorials. Honestly i hoped much more visitors but my blog is not recognized as you mentioned. So i lost my desire to write this blog. Thats why i did not post anything for moths. I think i will not add any more post.

      Finally for your question i am sorry i dont have any answer. May be you can descrease iteration number and you should remove trajectory circles from screen and memory before your ball move

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s