Wiki

Clone wiki

Core / LimgCode1.1

--living images
function setup()
    --World(scale, num Lims, Lim width, Lim height, num Foods)
    w = World(4, 20, 6, 6, 10)
end

function draw()
    w:draw()
    w:move()
end

World = class()

function World:init(s,nl,lw,lh,nf)
    --(scale, num Lims, Lim width, Lim height, num Foods
    self.s = s --scale
    self.l = Lims(nl,lw,lh,s)
    self.f = Foods(nf,s)
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)
end

Lims = class()

function Lims:init(n,w,h,s)
    --(num Lims, Lim width, Lim height, scale)
    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(WIDTH - (WIDTH/10)) + WIDTH/20) / s
        local y = (math.random(HEIGHT - (HEIGHT/10)) + HEIGHT/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:move(f,s)
    --(foods,scale)
    local i
    for i = 1, self.n do
        self.t[i]:move(f,s,self)
    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:move(f,s,l)
    --(foods, scale, lims)
    self.a = self.a + 1
    local i, j, k, fv, lv, cf, cl, r, g, b, a, v
    cf = math.huge
    for k = 1, f.n do
        fv = vec2(f.t[k].x,f.t[k].y)
        if fv:dist(vec2(self.x,self.y)) < cf then
            cf = self:wdist(WIDTH/s,HEIGHT/s,vec2(self.x,self.y),fv).d
        end
    end
    cl = math.huge
    for k = 1, l.n do
        lv = vec2(l.t[k].x,l.t[k].y)
        if lv:dist(vec2(self.x,self.y)) < cl 
            and lv:dist(vec2(self.x,self.y)) ~= 0 then
            cl = self:wdist(WIDTH/s,HEIGHT/s,vec2(self.x,self.y),lv).d
        end
    end
    for i = 1, self.w do
        for j = 1, self.h do
            r, g, b, a = self.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          
                    v = vec2(a/25,0)
                    v = v:rotate(math.rad((self.r/255)*360))
                    self.x = self.x + (v.x/100)
                    self.y = self.y + (v.y/100)
                else
                    self.r = self.r + (a-127)/128
                    if self.r > 255 then self.r = self.r - 255 end
                end
            end
        end
    end   
    for k = 1, f.n do
        fv = vec2(f.t[k].x,f.t[k].y)
        if fv:dist(vec2(self.x,self.y)) < self.w + 1 then
            self:eat(f.t[k],l,s)
        end
    end
    
    local bdr = 3
    if self.x < -(bdr) then self.x = (WIDTH/s) + (bdr) end
    if self.x > (WIDTH/s) + (bdr) then self.x = 0 - (bdr) end 
    if self.y < -(bdr) then self.y = (HEIGHT/s) + (bdr)end
    if self.y > (HEIGHT/s) + (bdr) then self.y = 0 - (bdr) end
end

function Lim:divide(d)
    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)
    --num foods, scale
    self.n = n
    self.t = {}
    local i
    for i = 1, self.n do
        self.t[i] = Food(nil,nil,s)
    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)
    self.x = x
    self.y = y
    if self.x == nil or self.y == nil then
        self:rand(s)
    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)
    self.x = (math.random(WIDTH - (WIDTH/10)) + WIDTH/20) / s
    self.y = (math.random(HEIGHT - (HEIGHT/10)) + HEIGHT/20) / s
end

Updated