Created
February 17, 2013 12:26
-
-
Save tnlogy/4971294 to your computer and use it in GitHub Desktop.
Swarming behaviour in Codea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# 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