Skip to content

Instantly share code, notes, and snippets.

@phred
Last active June 27, 2024 13:46
Show Gist options
  • Save phred/1346624 to your computer and use it in GitHub Desktop.
Save phred/1346624 to your computer and use it in GitHub Desktop.
Conway's Game of life for Codea
-- Size of the board, 40 is nice and fast 
-- 100 is doable but only runs at 3 fps with current board algorithm
-- 10 is fun and good for making sure everything works
-- 40 is ideal
Size=40
Generation=0
World = { cols=Size, rows=HEIGHT/(WIDTH/Size), last=0.0 }
Cell = { size = WIDTH/World.cols, color=color(0, 62, 255, 255) }
Directions = {
    {-1, -1 }, {-1, 0 }, {-1,  1 },
    { 0, -1 },           { 0,  1 },
    { 1,  1 }, { 1, 0 }, { 1, -1  }
function newBoard()
    local b = {}
    for i = 1, World.cols do
        b[i] = {}  
        for j = 1, World.rows do
            b[i][j] = 0
        end
    end
    return b
end
function neighbors(col, row)
    count = 0
    for ndx, dir in ipairs(Directions) do
        neighbor_col = (col + dir[2])
        neighbor_row  = (row + dir[1])
        
        if neighbor_col < 1 or neighbor_col > World.cols or
            neighbor_row < 1 or neighbor_row > World.rows then
            -- edge of the board is always empty
        else
            count = count + Board[neighbor_col][neighbor_row]
        end
    end
    return count
end
function iterate_board()
    local Board_new = newBoard()
    for i, col in ipairs(Board) do
        for j, cell in ipairs(col) do
            n = neighbors(i, j)
            --if n > 0 then print(j, i, n, cell) end
            if cell == 1 then
                if n > 3 or n < 2 then -- over- or under-population
                    Board_new[i][j] = 0
                else
                    Board_new[i][j] = 1  -- stable
                end
            else
                if n == 3 then
                    Board_new[i][j] = 1 -- birth
                end
            end
        end
    end
    
    for i, col in ipairs(Board_new) do
        for j, cell in ipairs(col) do
            Board[i][j] = cell
        end
    end
end
frames = 0
fps = 0.0
fps_start = 0
-- Use this function to perform your initial setup
function setup()
    Board = newBoard()
    
    parameter("Delay", 0, 5)
    Delay = 0.1
    iparameter("Hold", 0, 1)
    Hold = 1
    iparameter("Ghosting", 0, 255)
    Ghosting = 100
    touches = {}
    cleared = false
    last_tap_count = 0
    watch("Generation")
    watch("fps")
end
function touched(touch)
    if touch.state == ENDED then
        touches[touch.id] = nil
        last_tap_count = 0
   else
        touches[touch.id] = touch
    end
end
-- This function gets called once every frame
function draw()
    if not cleared then
        background(0, 0, 0, 255)
        cleared = true
    end
    fill(0, 0, 0, 255-Ghosting-(25*Delay - 12.5))
    rect(0,0,WIDTH,HEIGHT)
    pushMatrix()
    for i, col in ipairs(Board) do     
        pushMatrix()
        for j, cell in ipairs(col) do
            drawCell(cell)
            translate(0.0, Cell.size)
        end
        popMatrix()
        translate(Cell.size, 0.0)
    end
    popMatrix()
    frames = frames + 1
    if ElapsedTime - fps_start >= 3.0 then
        fps = frames / (ElapsedTime - fps_start)
        frames = 0
        fps_start = ElapsedTime
    end
    if (ElapsedTime - World.last > Delay and Hold == 0) then
        iterate_board()
        World.last = ElapsedTime
        Generation = Generation + 1
        IterateOne = false
    end
    fingers_tapped = {}
    for k, touch in pairs(touches) do
        col = math.max(0, math.floor((touch.x / Cell.size) % World.cols))
        row = math.max(0, math.floor((touch.y / Cell.size) % World.rows))
        if touch.tapCount >= 2 then
            table.insert(fingers_tapped, k)
            if Hold == 1 and touch.tapCount > last_tap_count then
                last_tap_count = touch.tapCount
                iterate_board()
            end
        else
            Board[1 + col][1 + row] = 1
        end
    end
    
    if #fingers_tapped == 2 then
        Hold = 1 - Hold
        for k, id in pairs(fingers_tapped) do
            touches[id] = nil
        end
    end
end
function drawCell(cell)
    if cell == 1 then
        fill(Cell.color)
        stroke(0, 0, 0, 255)
        strokeWidth(2)
        rect(0, 0, Cell.size, Cell.size)
    end
end
--
 
@phred
Copy link
Author

phred commented Nov 8, 2011

Added tap-to-advance, two finger double tap to toggle pause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment