Skip to content

Instantly share code, notes, and snippets.

@tnlogy
Created February 17, 2013 12:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tnlogy/4971294 to your computer and use it in GitHub Desktop.
Save tnlogy/4971294 to your computer and use it in GitHub Desktop.
Swarming behaviour in Codea
--# Main
-- Formation
function setup()
displayMode(FULLSCREEN)
physics.gravity(0,0)
touches = {}
items = {}
ships = {}
for i=0,10 do
local s = Ship {pos=vec2(0,50*i-400)}
table.insert(ships, 1, s)
end
font("Futura-CondensedExtraBold")
end
function draw()
background(83, 98, 125, 255)
pushMatrix()
translate(WIDTH/2,HEIGHT/2)
for i,s in ipairs(ships) do
s:draw()
if not isAlive(s) then table.remove(ships,i) end
end
for i,s in ipairs(items) do
s:draw()
if not isAlive(s) then table.remove(items,i) end
end
popMatrix()
fill(255, 255, 255, 255)
text("FIRE", 50,50)
end
function isAlive(s)
if s.ttl and ElapsedTime > s.ttl then
s:destroy()
else
return true
end
end
function touched(touch)
touches[touch.id] = touch
local i,ti, tv = 1, 1, {}
for id,v in pairs(touches) do
if id == touch.id then i=ti end
table.insert(tv, v)
ti = ti + 1
end
local step = #tv
-- check if button press
if touch.state == BEGAN and touch.y < 100 then
i,step=1,1
end
if #ships >= i then
ships[i]:touched(touch, function()
i = i + step
return ships[i]
end)
end
if touch.state == ENDED or touch.state == CANCELLED then
touches[touch.id] = nil
end
end
function collide(c)
if c.state ~= BEGAN then return end
local b = c.bodyA.info.bullet or c.bodyB.info.bullet
local s = c.bodyA.info.ship or c.bodyB.info.ship
if b then
b.ttl = ElapsedTime-1
if s then s.ttl = ElapsedTime+.2 end
end
Explosion(c.position, 15)
end
--# Item
Item = class()
function Item:getDir()
return vec2(0,1):rotate(math.rad(-self.body.angle))
end
function Item:setDir(dir)
self.body.angle = math.deg(dir:angleBetween(vec2(0,1)))
end
function Item:destroy()
self.body:destroy()
self.body = nil
end
--# Ship
Ship = class(Item)
function Ship:init(params)
self.id = params.id
self.m = mesh()
self.m.texture =("Tyrian Remastered:Ship B")
self.m:addRect(0,0,21,27)
self.body = physics.body(CIRCLE, 18)
self.body.position = params.pos
self.body.angularDamping = 4
self.body.linearDamping = 4
self.body.info = {ship=self}
self.tq = {}
end
function Ship:fire()
Bullet(self)
end
function Ship:draw()
pushMatrix()
translate(self.body.x, self.body.y)
rotate(-self.body.angle)
self.m:draw()
popMatrix()
if self.ttl then
local d = 10
local p = self.body.position +
vec2(math.random(-d,d),math.random(-d,d))
Explosion(p, math.random(10,50))
end
if self.child and #self.tq>0 then
local touch, time, childIter = unpack(self.tq[1])
if ElapsedTime > time+.05 then
table.remove(self.tq, 1)
self.child:touched(touch, childIter)
end
end
end
function Ship:touched(touch, childIter)
if not self.body then return end
if touch.state == BEGAN then
if touch.x < 100 and touch.y < 100 then self:fire() end
end
if touch.state == MOVING then
local dv = vec2(touch.deltaX, touch.deltaY)
local rv = math.random(1, 1.8)
self.body.linearVelocity = (dv*50*rv)
if dv:len() > 1 then
self:setDir((self:getDir() + dv:normalize()*2):normalize())
end
end
self.child = childIter()
if self.child then
table.insert(self.tq, {touch, ElapsedTime, childIter})
end
end
function Ship:moving()
return #self.tq>0
end
--# Bullet
Bullet = class(Item)
function Bullet:init(ship)
self.m = mesh()
self.m.texture =("Tyrian Remastered:Energy Orb 1")
self.m:addRect(0,0,20,20)
self.body = physics.body(CIRCLE, 8)
local dir = ship:getDir()
local p = vec2(ship.body.x, ship.body.y)+dir*28
self.body.x, self.body.y = p.x, p.y
self.body:applyForce(dir*400)
self.body.bullet = true
self.ttl = ElapsedTime+1
table.insert(items, self)
self.body.info = {bullet=self}
end
function Bullet:draw()
pushMatrix()
translate(self.body.x, self.body.y)
scale(self.ttl-ElapsedTime)
self.m:draw()
popMatrix()
end
--# Explosion
Explosion = class(Item)
function Explosion:init(pos, size, ttl)
size = size or 30
self.m = mesh()
self.m.texture = ("Tyrian Remastered:Explosion Huge")
self.m:addRect(pos.x,pos.y,size,size)
self.ttl = ElapsedTime+(ttl or .2)
table.insert(items, self)
end
function Explosion:draw()
pushMatrix()
local t = (self.ttl - ElapsedTime)*4
self.m:setColors(255,255,255,255*t)
self.m:draw()
popMatrix()
end
function Explosion:destroy() end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment