For the moment they dont do much, and you cant interract. But they are fun to watch.
http://www.youtube.com/watch?v=VJ9PR34-Jxw
Here the code
--# Main
-- 0 fourmi
-- copyright JMV38 2013 - all rights reserved
displayMode(FULLSCREEN)
function setup()
physics.gravity(0,0)
smooth()
world = World()
local brown = color(120, 65, 30, 255)
ants = Ants(200, brown )
if FPS then fps=FPS() end
end
function draw()
background(255, 255, 255, 255)
world:draw()
ants:draw()
if fps then fps:draw() end
end
--# Ant
Ant = class()
-- copyright JMV38 2013 - all rights reserved
function Ant:init(ms,v0,r0,nbrStates,caller)
-- utilities
local rnd = math.random
local deg = math.deg
local rad = math.rad
local cos = math.cos
local sin = math.sin
self.rnd = math.random
self.deg = math.deg
self.rad = math.rad
self.cos = math.cos
self.sin = math.sin
-- object creation and links
self.body = physics.body(CIRCLE,5)
local body = self.body
body.info = self
body.type = DYNAMIC
body.angle = rad(rnd(360))
body.fixedRotation = true
local v = vec2((rnd()-0.5)*2*r0,(rnd()-0.5)*2*r0)
body.position = v + v0
self.imgState = 1
self.caller = caller
self.coords = caller.coords
self.ms = caller.ms
self.pausePeriod = 3
self.pauseDuration = 1
self.pausing = true
self.speed = 75
self.changeDirPeriod = 0.5
self:pause()
self:changeDir()
-- init mesh information
local sizeFactor = 0.9
self.w = 26 *sizeFactor
self.h = 21 *sizeFactor
self.rect = self.ms:addRect(v.x,v.y,self.w,self.h,body.angle)
self.ms:setRectColor(self.rect,caller.color)
self.ms:setRectTex(self.rect,0,0,1/nbrStates,1)
end
function Ant:changeImgState(di,ms,coords)
if self.pausing then return end
local i = self.imgState
i = (i -1+ di)%6 +1
self.imgState = i
ms:setRectTex(self.rect, unpack(coords[i]))
end
function Ant:changeDir()
local v,speed
local body = self.body
body.angle = body.angle + self.rad(self.rnd()*180-90)
if self.pausing then speed=0 else speed=self.speed end
v = vec2(self.cos(body.angle),self.sin(body.angle)) * speed
body.linearVelocity = v
self.changeDirT0 = ElapsedTime + (self.rnd()+1)/2*self.changeDirPeriod
if self.rect then self:changeImgState(3,self.ms,self.coords) end
end
function Ant:pause()
local body = self.body
self.pausing = not self.pausing
if self.pausing then
body.linearVelocity = vec2(0,0)
self.pauseT0 = ElapsedTime + (self.rnd()+1)/2*self.pauseDuration
else
self:changeDir()
self.pauseT0 = ElapsedTime + (self.rnd()+1)/2*self.pausePeriod
end
end
function Ant:changeSpeed(n)
local rnd = math.random
if rnd()<=DeltaTime*60/n then self.speed = 0 else self.speed = 50 end
end
function Ant:touched(touch)
-- Codea does not automatically call this method
end
--# Ants
Ants = class()
-- copyright JMV38 2013 - all rights reserved
function Ants:init(n,c)
self.ms = mesh()
self.color = c
local img,coords = self:textureGet()
self.texture = img
self.coords = coords
self.ms.texture = self.texture
local list = {}
local v0 = vec2(WIDTH/2,HEIGHT/2)
local nbrStates = #self.coords
for i=1,n do list[i] = Ant(self.ms,v0,100,nbrStates,self) end
self.list = list
end
function Ants:draw()
self:redraw()
self.ms:draw()
end
function Ants:redraw(debug)
local rnd = math.random
local deg = math.deg
local rad = math.rad
local cos = math.cos
local sin = math.sin
local ms = self.ms
local coords = self.coords
local body,v,i,pos,angle
if not debug then
-- actions to do every frame for all ants
for _,ant in pairs(self.list) do
body = ant.body
pos = body.position
ms:setRect(ant.rect,pos.x,pos.y,ant.w,ant.h,body.angle)
ant:changeImgState(1,ms,coords)
end
-- actions that can be skipped sometimes
self:makeThemAlive()
else -- special to built images
local ant = self.list[1]
local s = 10
ms:setRect(ant.rect, WIDTH/2, HEIGHT/2, ant.w*s, ant.h*s, 0)
ant.body.linearVelocity = vec2(0)
ant:setImgState("stop",ms,self.coords)
return
end
end
function Ants:makeThemAlive()
local ant
local list = self.list
for i=1,#list do
ant = list[i]
if ant.changeDirT0 < ElapsedTime then ant:changeDir() end
if ant.pauseT0 < ElapsedTime then ant:pause() end
end
end
function Ants:textureGet()
local img = {}
local coords = {}
local N = 6
for i=1,N do img[i] = self:loadImg(i) end
local w0 = img[1].width
local h0 = img[1].height
local w = w0 * #img
local h = h0
local tex = image(w,h)
setContext(tex)
background(255, 255, 255, 255)
setContext()
for i =1,#img do
local im = img[i]
local x1 = (w0)*(i-1)
coords[i] = {(x1)/w, 0,w0/w, 1}
for x=1,im.width do for y=1,im.height do
tex:set(x+x1,y,color(im:get(x,y)))
end end
end
return tex,coords
end
function Ants:loadImg(phase)
local w,h = 31,25
self.img = image(31,25)
local img = self.img
setContext(img)
pushMatrix() pushStyle()
background(0, 0, 0, 0)
fill(255, 255, 255, 255)
stroke(255, 255, 255, 255)
self:bodyImg()
self:frontLeg(phase,"left")
self:frontLeg(phase+3,"right")
self:midLeg(phase+1,"left")
self:midLeg(phase+4,"right")
self:backLeg(phase+2,"left")
self:backLeg(phase+5,"right")
popMatrix() popStyle()
setContext()
return img
end
function Ants:stopImg()
local w,h = 31,25
self.img = image(w,h)
local img = self.img
setContext(img)
pushMatrix() pushStyle()
background(0, 0, 0, 0)
fill(0, 0, 0, 255)
stroke(0, 0, 0, 255)
self:bodyImg()
self:frontLeg(0,"left")
self:frontLeg(0,"right")
self:midLeg(3,"left")
self:midLeg(3,"right")
self:backLeg(5.99,"left")
self:backLeg(5.99,"right")
popMatrix() popStyle()
setContext()
return img
end
function Ants:moveLeg(phase,side,ref,front,back)
-- phase: 0 to 5.99, 0 = front and 5.99 = back
local q = (phase - math.floor(phase/6)*6)/6
local p = 1-q
local sgn
if side =="left" then sgn=1 else sgn=-1 end
local x0,y0 = unpack(ref)
local x1a,y1a,x2a,y2a = unpack(front) -- front position
local x1b,y1b,x2b,y2b = unpack(back ) -- back position
local x1,y1 = x1a*p + x1b*q , y1a*p + y1b*q
local x2,y2 = x2a*p + x2b*q , y2a*p + y2b*q
self:leg(x0,y0,x1,y1*sgn,x2,y2*sgn)
end
function Ants:frontLeg(phase,side)
local x0,y0 = 17,(self.img.height + 0)/2
self:moveLeg(phase,side,{x0,y0},{0,0,5,7},{0,0,3,7})
self:moveLeg(phase,side,{x0,y0},{4,6,11,12},{3,6,0,12})
end
function Ants:midLeg(phase,side)
local x0,y0 = 14,(self.img.height + 0)/2
self:moveLeg(phase,side,{x0,y0},{0,0,3,6},{0,0,1,6})
self:moveLeg(phase,side,{x0,y0},{3,5,3,9},{1,5,-1,9})
self:moveLeg(phase,side,{x0,y0},{3,8,3,14},{-1,8,-3,12})
end
function Ants:backLeg(phase,side)
local x0,y0 = 13,(self.img.height + 0)/2
self:moveLeg(phase,side,{x0,y0},{0,0,0,6},{0,0,-3,6})
self:moveLeg(phase,side,{x0,y0},{1,6,-4,6},{-2,6,-9,6})
self:moveLeg(phase,side,{x0,y0},{-3,6,-4,13},{-7,6,-13,9})
end
function Ants:bodyImg()
local y0 = (self.img.height + 1)/2
strokeWidth(0)
ellipse(6,y0,10,8) -- abdomen
ellipse(14,y0,12,4) -- centre
ellipse(21,y0,6,6) -- tete
self:legs(22,y0,0,0,3,5) -- antenne
self:legs(22,y0,3,5,9,4)
end
function Ants:leg(x0,y0,x1,y1,x2,y2)
strokeWidth(3)
lineCapMode(SQUARE)
line(x0+x1,y0+y1,x0+x2,y0+y2)
end
function Ants:legs(x0,y0,x1,y1,x2,y2)
self:leg(x0,y0,x1,y1,x2,y2)
self:leg(x0,y0,x1,-y1,x2,-y2)
end
function Ants:touched(touch)
-- Codea does not automatically call this method
end
--# World
World = class()
-- copyright JMV38 2013 - all rights reserved
function World:init()
-- visibility
local ms = mesh()
local i = ms:addRect(75,HEIGHT-15,150,30)
local c = color(127, 127, 127, 255)
ms:setRectColor(i,c)
self.ms = ms
-- edges
edge = {}
edge[1] = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
edge[2] = physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
edge[3] = physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
edge[4] = physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
end
function World:draw()
-- Codea does not automatically call this method
self.ms:draw()
end
function World:touched(touch)
-- Codea does not automatically call this method
end