Wiki

Clone wiki

Core / LimgCode1.3

--living images
function setup()
    parameter("zoom",1,5)
    parameter("left",left,1)
    parameter("up",up,1)
    iparameter("run",0,1,1)
    --displayMode(FULLSCREEN)
    w = World()
    w:random()
end

function draw()
    scale(zoom)
    translate((-left*w.w)*(zoom-1)/zoom,-up*w.h*(zoom-1)/zoom)
    w:draw()
    if run == 1 then w:move() end
end

function touched(touch)
    if touch.tapCount == 3 then w:random() end
end

World = class()

function World:init(s,nl,lw,lh,nf,gd,vis,ww,wh)
    --(scale, num Lims, Lim width, Lim height, num Foods, genetic drift, viscosity)
    --scale - the amount the world is zoomed in, high number small world zoomed in
    if s == nil then self.s = 2 else self.s = s end 
    --number of Lims
    if nl == nil then self.nl = 10 else self.nl = nl end 
    --width of each Lim
    if lw == nil then self.lw = 16 else self.lw = lw end
    --height of each Lim
    if lh == nil then self.lh = 16 else self.lh = lh end
    --number of Foods available at any moment that Lims eat
    if nf == nil then self.nf = 20 else self.nf = nf end
    --genetic drift - the amount each r, g, b, a can change when dividing
    if gd == nil then self.gd = 1 else self.gd = gd end 
    --viscocity - the higher the number the slower Lims move
    if vis == nil then self.vis = 50 else self.vis = vis end
    --world width
    if ww == nil then self.w = WIDTH else self.w = ww end
    --world height
    if wh == nil then self.h = HEIGHT else self.h = wh end
    self:reset()   
end

function World:reset()
    self.l = Lims(self.nl,self.lw,self.lh,self.s,self.w,self.h)
    self.f = Foods(self.nf,self.s,self.w,self.h)  
end

function World:random()
    self.lw = math.random(13) + 3
    self.lh = math.random(13) + 3
    self.s = 10 - ((self.lw+self.lh)/4)
    self.nf = 20 - math.floor(self.s)
    self:reset()   
end

function World:draw()
    background(0, 0, 0)
    scale(self.s)
    noSmooth()
    self.l:draw(self.s)
    self.f:draw()
end

function World:move()
    --self.l:move(self.f,self.s)
    --function Lims:move(f,s)
    --(foods,scale)
    local i
    for i = 1, self.l.n do
        --self.l.t[i]:move(self.f,self.s,self.l)
        self:moveLim(self.l.t[i])
    end
--end
end

function World:moveLim(l)
--function Lim:move(f,s,l)
    --(foods, scale, lims)
    l.a = l.a + 1
    local i, j, k, fv, lv, cf, cl, r, g, b, a, v
    cf = math.huge
    for k = 1, self.f.n do
        fv = vec2(self.f.t[k].x,self.f.t[k].y)
        if fv:dist(vec2(l.x,l.y)) < cf then
            cf = l:wdist(self.w/self.s,self.h/self.s,vec2(l.x,l.y),fv).d
        end
    end
    cl = math.huge
    for k = 1, self.l.n do
        lv = vec2(self.l.t[k].x,self.l.t[k].y)
        if lv:dist(vec2(l.x,l.y)) < cl 
            and lv:dist(vec2(l.x,l.y)) ~= 0 then
            cl = l:wdist(self.w/self.s,self.h/self.s,vec2(l.x,l.y),lv).d
        end
    end
    for i = 1, l.w do
        for j = 1, l.h do
            r, g, b, a = l.im:get(i,j)
            if (g == 0 or g == 255 
                or (g > 127 and (g/10) > cf) 
                or (g < 128 and (g/10) < cf)) 
                and
                (r == 0 or r == 255 
                or (r > 127 and (r/10) > cl) 
                or (r < 128 and (r/10) < cl))
                then
                if b > 127 then          
                    --local vis = 50 --viscosity 
                    v = vec2(a/self.vis,0)
                    v = v:rotate(math.rad((l.r/255)*360))
                    l.x = l.x + (v.x/self.vis)
                    l.y = l.y + (v.y/self.vis)
                else
                    l.r = l.r + (a-127)/128
                    if l.r > 255 then l.r = l.r - 255 end
                end
            end
        end
    end   
    for k = 1, self.f.n do
        fv = vec2(self.f.t[k].x,self.f.t[k].y)
        if fv:dist(vec2(l.x,l.y)) < l.w + 1 then
            --self:eat(self.f.t[k],self.l,self.s)
            --function Lim:eat(f,l,s)
    --(food, lims, scale)
            self.f.t[k]:rand(self.s,self.w,self.h)
            local d = self.l:oldest()
            l:divide(d,self.gd)
--end
        end
    end
    
    local bdr = 3
    if l.x < -(bdr) then l.x = (self.w/self.s) + (bdr) end
    if l.x > (self.w/self.s) + (bdr) then l.x = 0 - (bdr) end 
    if l.y < -(bdr) then l.y = (self.h/self.s) + (bdr) end
    if l.y > (self.h/self.s) + (bdr) then l.y = 0 - (bdr) end
--end
end

Lims = class()

function Lims:init(n,w,h,s,ww,wh)
    --(num Lims, Lim width, Lim height, scale, world width, world height)
    self.t = {} -- image table
    self.n = n -- number images
    -- you can accept and set parameters here
    local i
    for i = 1, self.n do
        local x = (math.random(ww - (ww/10)) + ww/20) / s
        local y = (math.random(wh - (wh/10)) + wh/20) / s
        --local h = 5
        --local w = 5
        local r = math.random(256)-1
        self.t[i] = Lim(x,y,w,h,r,i)
        self.t[i]:rand()  
    end
end

function Lims:draw(s)
    --(scale)
    local i
    for i = 1, self.n do
        self.t[i]:draw(s)
    end
end

function Lims:oldest()
    local i
    local o = 0 --oldest
    local h = 0 --highest
    for i = 1, self.n do
        if self.t[i].a > h then
            h = self.t[i].a
            o = i
        end
    end
    return self.t[o] 
end

Lim = class()

function Lim:init(x,y,w,h,r,a)
    self.x = x
    self.y = y
    self.w = w
    self.h = h
    self.r = r -- rotation
    self.a = a -- age
    self.im = image(w,h)
end

function Lim:rand()
    local i, j
    for i = 1, self.w do
        for j = 1, self.h do
            local r = math.random(256)-1
            local g = math.random(256)-1
            local b = math.random(256)-1
            local a = math.random(256)-1
            self.im:set(i,j,r,g,b,a)
        end
    end   
end

function Lim:draw(s)
    --(scale)
    pushMatrix()
    translate(self.x,self.y)
    rotate((self.r/255)*360)
    translate(-self.x,-self.y)
    spriteMode(CORNER)
    sprite(self.im,self.x,self.y)
    strokeWidth(1)
    stroke(127, 127, 127, 255)
    noFill()
    rectMode(CORNER)
    --rect(self.x-1,self.y-1,self.w+2-(1/s),self.h+2)
    --rect(self.x-1,self.y-1,self.w+2,self.h+2)
    popMatrix()
end

function Lim:divide(d,gd)
    --local gd = 1 --genentic drift
    self.a = 0
    d.a = 0
    d.x = self.x
    d.y = self.y
    d.r = self.r
    local i, j, r, g, b, a
    for i = 1, self.w do
        for j = 1, self.h do
            r,g,b,a = self.im:get(i,j)
            r = math.fmod(r+(math.random((gd*2)+1) - gd -1),256)
            g = math.fmod(g+(math.random((gd*2)+1) - gd -1),256)
            b = math.fmod(b+(math.random((gd*2)+1) - gd -1),256)
            a = math.fmod(a+(math.random((gd*2)+1) - gd -1),256)
            d.im:set(i,j,r,g,b,a)
            r,g,b,a = self.im:get(i,j)
            r = math.fmod(r+(math.random((gd*2)+1) - gd -1),256)
            g = math.fmod(g+(math.random((gd*2)+1) - gd -1),256)
            b = math.fmod(b+(math.random((gd*2)+1) - gd -1),256)
            a = math.fmod(a+(math.random((gd*2)+1) - gd -1),256)
            self.im:set(i,j,r,g,b,a)
        end
    end   
end

function Lim:eat(f,l,s)
    --(food, lims, scale)
    f:rand(s)
    local d = l:oldest()
    self:divide(d)
end

function Lim:wdist(w,h,v1,v2)
    --wrap distance
    --find the distance between v1 and v2 assuming the boundaries wrap
    --w = map width, h = map height
    local dt = {} -- distance table 
    dt[1] = {d=v1:dist(v2),v=v2} --visible distance on screen
    dt[2] = {d=v1:dist(vec2(v2.x,v2.y+h)),v=vec2(v2.x,v2.y+h)} --distance up off map
    dt[3] = {d=v1:dist(vec2(v2.x,v2.y-h)),v=vec2(v2.x,v2.y-h)} --distance down off map
    dt[4] = {d=v1:dist(vec2(v2.x-w,v2.y)),v=vec2(v2.x-w,v2.y)} --distance left off map
    dt[5] = {d=v1:dist(vec2(v2.x+w,v2.y)),v=vec2(v2.x+w,v2.y)} --distance right off map
    dt[6] = {d=v1:dist(vec2(v2.x+w,v2.y+h)),v=vec2(v2.x+w,v2.y+h)} --distance up right off map
    dt[7] = {d=v1:dist(vec2(v2.x-w,v2.y-h)),v=vec2(v2.x-w,v2.y-h)} --distance down left off map
    dt[8] = {d=v1:dist(vec2(v2.x-w,v2.y+h)),v=vec2(v2.x-w,v2.y+h)} --distance up left off map
    dt[9] = {d=v1:dist(vec2(v2.x+w,v2.y-h)),v=vec2(v2.x+w,v2.y-h)} --distance down right off map
    local i
    local sdi = 1 --shortest distance, 1 is visible distance on screen
    local sd = dt[sdi].d --shortest distance
    for i = 2, 9 do
        if dt[i].d < sd then
            sd = dt[i].d
            sdi = i
        end
    end
    return dt[sdi]
end

Foods = class()

function Foods:init(n,s,ww,wh)
    --num foods, scale
    self.n = n
    self.t = {}
    local i
    for i = 1, self.n do
        self.t[i] = Food(nil,nil,s,ww,wh)
    end
end

function Foods:draw()
    for i = 1, self.n do
        self.t[i]:draw()
    end
end

Food = class()

function Food:init(x,y,s,ww,wh)
    self.x = x
    self.y = y
    if self.x == nil or self.y == nil then
        self:rand(s,ww,wh)
    end
end

function Food:draw()
    pushMatrix()
    strokeWidth(1)
    stroke(0, 255, 0, 255)
    noFill()
    ellipse(self.x,self.y,3,3)
    popMatrix()
end

function Food:rand(s,ww,wh)
    --self.x = (math.random(WIDTH - (WIDTH/10)) + WIDTH/20) / s
    --self.y = (math.random(HEIGHT - (HEIGHT/10)) + HEIGHT/20) / s
    self.x = (math.random(ww - (ww/10)) + ww/20) / s
    self.y = (math.random(wh - (wh/10)) + wh/20) / s
end

Food = class()

function Food:init(x,y,s,ww,wh)
    self.x = x
    self.y = y
    if self.x == nil or self.y == nil then
        self:rand(s,ww,wh)
    end
end

function Food:draw()
    pushMatrix()
    strokeWidth(1)
    stroke(0, 255, 0, 255)
    noFill()
    ellipse(self.x,self.y,3,3)
    popMatrix()
end

function Food:rand(s,ww,wh)
    --self.x = (math.random(WIDTH - (WIDTH/10)) + WIDTH/20) / s
    --self.y = (math.random(HEIGHT - (HEIGHT/10)) + HEIGHT/20) / s
    self.x = (math.random(ww - (ww/10)) + ww/20) / s
    self.y = (math.random(wh - (wh/10)) + wh/20) / s
end

Updated