Skip to content

128. Physics ballistics

October 21, 2013

This post is about creating a shower of arrows that are shot into the air and fall back to the earth. Useful for your next elves vs orcs game.

I’ve created a new physics class to handle this, because it needs a couple of special features.

In the setup, I’ve set gravity to the same value as in Codea, ie 133 pixels per second.

The arrows have a number of properties, as you can see below. I’ve separated direction from speed just to make it easier for a user to set them, and I’ll need to multiply them together to get velocity.

The damping factor just adds a little drag to the arrows, although with gravity as well, it may not be necessary. I have read that it’s a good idea to include damping because computers aren’t perfectly accurate, and if you set a constant speed, it may not stay that way because of rounding errors. Damping just makes sure the speed never spins out on control.


Ballistics = class()

--constants which apply to all physics objects
Ballistics.gravityStrength=vec2(0,-133) --not accurate

function Ballistics:init(position,direction,speed,mass,
                         colour,diameter,length)
self.position=position
self.velocity=direction*speed
self.mass=mass
self.color=colour or color(0)
self.width,self.length=diameter,length
--initialise
self.damping= 0.99
self.acceleration = vec2(0,0) --w.accel
Ballistics.gravityOn=true
end

The AdjustPosition function is exactly the same as for previous posts, but the draw function has some changes.

Arrows need to rotate as they shot up, then fall to earth, so they are always facing in the direction they are going. How do we do this?

arrow

(So I got sick of trying to draw simple diagrams in iPad drawing apps. It’s just quicker to draw them and photograph them!)

Above is our arrow, heading upwards to the right. Its velocity is (x,y), so for every x pixels it moves to the right, it moves y pixels upwards.

We want to rotate the arrow so it sits on the dotted line I’ve drawn from the bottom line. That means rotating the arrow by a degrees to the right.

We know that tan(a) = x / y, so a = atan(x/y)

The code below calculates this and turns the result into degrees. Then it translates to the position of the arrow (remember, you always translate before you rotate), and rotates by -a. (Why negative a? – read here).

function Ballistics:draw()
self:AdjustPosition(DeltaTime)
pushMatrix()
fill(self.color)
pushMatrix()
local a=math.deg(math.atan(self.velocity.x/self.velocity.y))
translate(self.position.x, self.position.y)
rotate(-a)
ellipse( 0,0, self.width ,self.length)
popMatrix()
popMatrix()
end

function Ballistics:AdjustPosition(t)
--update speed
if Ballistics.gravityOn then
self.acceleration = self.acceleration + Ballistics.gravityStrength
end
self.velocity = self.velocity + self.acceleration * t
--set (x,y) position
self.position = self.position + self.velocity * t
--reset acceleration to 0
self.acceleration=vec2(0,0)
end

Then all that’s left is to create some arrows. I have a function that creates a single arrow, using random numbers to vary things slightly. THe arrows get put into a table called arrows.

The draw function adds a new arrow each time, draws the arrows, and if they go off the edge of the screen, it deletes them from the arrows table.

function setup()
arrows={}
end

function AddArrow()
table.insert(arrows,Ballistics(vec2(50,10+math.random(30,100)),
vec2(.95+.1*math.random(),.95+.1*math.random()),
math.random(225,275),
.01,color(255,255,0),2,30))
end

function draw()
background(0)
AddArrow()
for i,p in pairs(arrows) do
p:draw()
if p.position.x>WIDTH or p.position.y<0 then
           table.remove(arrows,i)
        end
end
end

The code is here

Advertisements

From → Physics

Leave a Comment

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

%d bloggers like this: