Snake

Hey guys! I have finally finished the first working prototype of Snake! :slight_smile: Here is the code:

Main

function setup()
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    alive = true
    Grid = {}
    for x = 1, 32 do
        for y = 1, 24 do
            table.insert(Grid, Cell(x * 32, y * 32))
        end
    end
        
    QUEUE = 1
    LEVEL = 1
    Walls = {}
    levelUp(LEVEL)
    initializeSnake()
    Basket = { Food() }
    FRAME = 1
    SPEED = 10
    SCORE = 0
end


function draw()
    background(255, 255, 255, 255)
    if alive == true then
        if #Snake > 10 then
            LEVEL = LEVEL + 1
            levelUp()
        end
        if FRAME < SPEED then
            FRAME = FRAME + 1
        else
            FRAME = 0
        end
          
        for k, cell in ipairs(Grid) do
            cell:clear()
        end
            
        for k, brick in ipairs(Walls) do
            brick:draw(k)
        end
        
        Snake[#Snake]:last()
        
        Snake[ 1 ]:check()
        
        for k, snake in pairs(Snake) do
            snake:draw()
        end
        
        Snake[ 1 ]:check()
        
        for k, fruit in ipairs(Basket) do
            fruit:draw()
        end
    else
        for k, cell in ipairs(Grid) do
            cell:clear()
        end
        if SCORE < 10 then
        	for k,n in ipairs(Numbers[SCORE + 1]) do
            	Grid[ gridValue(n) ].state = BODY
        	end
        else
        	for k,n in ipairs(Numbers[math.floor(SCORE / 10) + 1]) do
        		Grid[ gridValue(n - vec2(3,0)) ].state = BODY
        	end
        	for k,n in ipairs(Numbers[SCORE - math.floor(SCORE / 10) * 10 + 1]) do
        		Grid[ gridValue(n + vec2(3,0)) ].state = BODY
        	end
        end
    end
    for k, cell in ipairs(Grid) do
        cell:draw()
    end    
end

function touched(t)
    Snake[1]:touched(t)
end

function gridValue(v)
    return (v.x - 1) * 24 + v.y
end

function initializeSnake()
    Snake = { Head(), Body(16, 13, 2) }
    QUEUE = 1
end

Cell.lua

Cell = class()

EMPTY = 1
FOOD = 2
HEAD = 3
BODY = 4
WALL = 5

colors = 
{
    color(0, 0, 0, 255),
    color(0, 255, 0, 255),
    color(255, 0, 0, 255),
    color(255, 255, 255, 255),
    color(127, 127, 127, 255),
    color(127, 127, 127, 255),
    color(255, 0, 255, 255),
    color(0, 255, 255, 255),
    color(0, 0, 0, 255),
    color(50, 50, 50, 255)
}

------------------------------------------------------------

function Cell:init(x, y)
    self.pos = vec2(-16 + x, -16 + y)
    self.state = EMPTY
end

------------------------------------------------------------

function Cell:draw()
    stroke(colors[ self.state + 5])
    strokeWidth(4)
    fill(colors[ self.state ])
    rectMode(CENTER)
    rect(self.pos.x, self.pos.y, 32, 32)
end

function Cell:clear()
    self.state = EMPTY
end

function Cell:isFull() 
    if self.state > HEAD then
        return true
    else
        return false
    end    
end

Brick.lua

Brick = class()

function Brick:init(pos)
    self.pos = pos
end

function Brick:draw()
    Grid[ gridValue(self.pos) ].state = WALL
end

Body.lua

Body = class()

function Body:init(x,y,i)
    self.pos = vec2(x, y)
    self.prevPos = self.pos
    self.index = i
end

function Body:draw()
    if FRAME == 0 then
        print()
        self.prevPos = self.pos
        self.pos = Snake[self.index - 1].prevPos
    end
    Grid[ gridValue(self.pos) ].state = BODY 
end

function Body:last()
    if QUEUE > 0 and FRAME == 0 then
        table.insert(Snake, Body(self.prevPos.x, self.prevPos.y, self.index + 1))
        QUEUE = QUEUE - 1
    end
end

Head.lua

Head = class()

RIGHT = vec2(1, 0)
LEFT = vec2(-1, 0)
UP = vec2(0, 1)
DOWN = vec2(0, -1)

------------------------------------------------------------

function Head:init()
    self.pos = vec2(17,13)
    self.speed = RIGHT
    self.changeTo = RIGHT
    self.prevPos = self.pos
end

function Head:draw(i)
    if FRAME == 0 then
        self.prevPos = self.pos
            self.speed = self.changeTo
            self.pos = self.pos + self.speed
        if self.pos.x < 1 then
            self.pos.x = 32
        elseif self.pos.x > 32 then
            self.pos.x = 1
        elseif self.pos.y < 1 then
            self.pos.y = 24
        elseif self.pos.y > 24 then
            self.pos.y = 1
        end
    end
    Grid[ gridValue( self.pos ) ].state = HEAD
end

function Head:touched(t)
    d = vec2(t.x - self.pos.x * 32, t.y - self.pos.y * 32)
    primeAxis = math.max( math.abs(d.x), math.abs(d.y))
    if primeAxis == math.abs(d.x) and (self.speed == UP or self.speed == DOWN) then
        if d.x > 0 then
            self.changeTo = RIGHT
        end
        if d.x < 0 then
            self.changeTo = LEFT
        end
    elseif primeAxis == math.abs(d.y) and (self.speed == LEFT or self.speed == RIGHT) then
        if d.y > 0 then
            self.changeTo = UP
        end
        if d.y < 0 then
            self.changeTo = DOWN
        end
    end
end

function Head:check()
    if Grid[ gridValue(self.pos) ]:isFull() then 
    	endGame()
    end
end

Food.lua

Food = class()

function Food:init()
    self.pos = vec2(math.random(1,32),math.random(1,24))
    while Grid[ gridValue(self.pos)]:isFull() do
        self.pos = vec2(math.random(1,32),math.random(1,24))
    end
end

function Food:draw()
    if Snake[1].pos == self.pos then
        QUEUE = QUEUE + 1
        SCORE = SCORE + 1
        self:init()
    end
    Grid[gridValue(self.pos)].state = FOOD
end

And Here is more…

Levels.lua

Levels = {
    {
        vec2(8, 5), vec2(8, 6), vec2(8, 7), vec2(8, 8), 
        vec2(8, 9), vec2(8, 10), vec2(8, 11), vec2(8, 12), 
        vec2(8, 13), vec2(8, 14), vec2(8, 15), vec2(8, 16), 
        vec2(8, 17), vec2(8, 18), vec2(8, 19), vec2(8, 20), 
        
        vec2(24, 5), vec2(24, 6), vec2(24, 7), vec2(24, 8), 
        vec2(24, 9), vec2(24, 10), vec2(24, 11), vec2(24, 12), 
        vec2(24, 13), vec2(24, 14), vec2(24, 15), vec2(24, 16), 
        vec2(24, 17), vec2(24, 18), vec2(24, 19), vec2(24, 20)
    }, 
    {
        vec2(1, 16), vec2(2, 16), vec2(3, 16), vec2(4, 16), 
        vec2(5, 16), vec2(6, 16), vec2(7, 16), vec2(8, 16), 
        vec2(8, 15), vec2(8, 14), vec2(8, 13), vec2(8, 12), 
        vec2(8, 11), vec2(8, 10), vec2(8, 9), vec2(8, 8), 
        vec2(8, 7), vec2(8, 6), vec2(8, 5), vec2(8, 4), 
        vec2(8, 3), vec2(8, 2), vec2(8, 1), 
        
        vec2(24, 24), vec2(24, 23), vec2(24, 22), vec2(24, 21), 
        vec2(24, 20), vec2(24, 19), vec2(24, 18), vec2(24, 17), 
        vec2(24, 9), vec2(24, 10), vec2(24, 11), vec2(24, 12), 
        vec2(24, 13), vec2(24, 14), vec2(24, 15), vec2(24, 16), 
        vec2(25, 9), vec2(26, 9), vec2(27, 9), vec2(28, 9), 
        vec2(29, 9), vec2(30, 9), vec2(31, 9),  vec2(32, 9)
    }
}

function levelUp()
    if LEVEL > #Levels then 
        endGame()
    else
        Walls = {}
        initializeSnake()
        for k,  v in ipairs( Levels[LEVEL] ) do
            table.insert(Walls,  Brick(v))
        end
    end
end

Numbers.lua

function endGame()
    alive = false
end

Numbers = {
	{
		vec2(15,17),vec2(16,17),vec2(17,17),vec2(18,17),
		vec2(19,17),vec2(15,9),vec2(16,9),vec2(17,9),
		vec2(18,9),vec2(19,9),vec2(15,16),vec2(15,15),
		vec2(15,14),vec2(15,13),vec2(15,12),vec2(15,11),
		vec2(15,10),vec2(19,16),vec2(19,15),vec2(19,14),
		vec2(19,13),vec2(19,12),vec2(19,11),vec2(19,10)
	},
    {
        vec2(15,14),vec2(16,15),vec2(17,16),vec2(17,15),
        vec2(17,14),vec2(17,13),vec2(17,12),vec2(17,11),
        vec2(17,10),vec2(15,9),vec2(16,9),vec2(17,9),
        vec2(18,9),vec2(19,9)
    },
    {
		vec2(15,15),vec2(16,16),vec2(17,16),vec2(18,16),
		vec2(19,15),vec2(19,14),vec2(18,13),vec2(17,12),
		vec2(16,11),vec2(15,10),vec2(15,9),vec2(16,9),
		vec2(17,9),vec2(18,9),vec2(19,9)
    },
    {
    	vec2(15,15),vec2(16,16),vec2(17,16),vec2(18,16),
    	vec2(19,15),vec2(19,14),vec2(18,13),vec2(17,13),
    	vec2(19,12),vec2(19,11),vec2(19,10),vec2(18,9),
    	vec2(17,9),vec2(16,9),vec2(15,10)
    },
    {
    	vec2(15,16),vec2(15,15),vec2(15,14),vec2(15,13),
    	vec2(15,12),vec2(15,11),vec2(16,11),vec2(17,11),
    	vec2(18,13),vec2(18,12),vec2(18,11),vec2(18,10),
    	vec2(18,9),vec2(19,11)
    },
    {
    	vec2(15,16),vec2(16,16),vec2(17,16),vec2(18,16),
    	vec2(19,16),vec2(15,15),vec2(15,14),vec2(16,14),
    	vec2(17,14),vec2(18,14),vec2(19,13),vec2(19,12),
    	vec2(19,11),vec2(19,10),vec2(18,9),vec2(17,9),
    	vec2(16,9),vec2(15,10)
   	},
   	{
   		vec2(15,16),vec2(16,16),vec2(17,16),vec2(18,16),
   		vec2(19,16),vec2(15,15),vec2(15,14),vec2(16,13),
   		vec2(17,13),vec2(18,13),vec2(19,13),vec2(15,13),
   		vec2(15,12),vec2(15,11),vec2(15,10),vec2(19,12),
   		vec2(19,11),vec2(19,10),vec2(15,9),vec2(16,9),
   		vec2(17,9),vec2(18,9),vec2(19,9)
   	},
   	{
   		vec2(15,16),vec2(16,16),vec2(17,16),vec2(18,16),
   		vec2(19,16),vec2(19,15),vec2(19,14),vec2(19,13),
   		vec2(19,12),vec2(19,11),vec2(19,10),vec2(19,9)
   	},
   	{
		vec2(15,17),vec2(16,17),vec2(17,17),vec2(18,17),
		vec2(19,17),vec2(15,9),vec2(16,9),vec2(17,9),
		vec2(18,9),vec2(19,9),vec2(15,16),vec2(15,15),
		vec2(15,14),vec2(15,13),vec2(15,12),vec2(15,11),
		vec2(15,10),vec2(19,16),vec2(19,15),vec2(19,14),
		vec2(19,13),vec2(19,12),vec2(19,11),vec2(19,10),
		vec2(16,14),vec2(17,14),vec2(18,14)
	},
	{
		vec2(15,16),vec2(16,16),vec2(17,16),vec2(18,16),
		vec2(19,16),vec2(15,15),vec2(15,14),vec2(15,13),
		vec2(15,12),vec2(16,12),vec2(17,12),vec2(18,12),
		vec2(19,12),vec2(15,9),
		vec2(16,9),vec2(17,9),vec2(18,9),vec2(19,9),
		vec2(19,15),vec2(19,14),vec2(19,13),vec2(19,11),
		vec2(19,10)
	}
}

@Jordan
Nice game. Played it a few rounds and noticed that the snake slows down with each new cell it adds to it’s body. Also, is the game supposed to restart after the snake gets about 10 cells to it’s body. If the speed can be increased and not slow down and the snake can get longer, it would be a challenge to play. Nice job. Looking forward for the next version.

The trick to optimizing snake games is not to redraw the snake in every frame. Just extend the body and erase the tail. Then the length doesn’t matter.

Thanks for the advice, one question though… @Memebag , what do you mean “extend the body and erase the tail”, for this program I used a table to keep track of the snake, do you mean I should use a RETAINED background?

The reason its slowing down is because you aren’t using a variable timestep. Try using DeltaTime for game calculations that could vary based on rendering time, such as timers instead of just frame counts.

If I comment out the print() statement in Body:draw(), the snake doesn’t appear to slow down.

@Jordan
I made the following modifications to your program. I commented out the print() statement in Body:draw(). That stopped the slow down of the snake as it got longer. I changed SPEED = 5 in function setup. That increased the speed of the snake. I changed if #Snake > 75 then in function draw. That made the snake longer an harder to avoid. With those changes, the game has a lot more of a challenge before going to the next level. Thanks for an interesting game.

Thanks for the help guys, I have taken your advice and made a new version of the game. I have put in more levels, a nicer look, made it so that it draws to a retained background only when it updates, a few modifications to finer details of the game (e.g. when you eat food, it doesn’t appear immediately, there is a one turn delay). I am just finishing the level plans and then I will post my final source!
:smiley:

HERE IT IS!!! Please give me some pointers as to how I can improve this. Thank you! :smiley:

Main.lua =

function setup()
    saveProjectInfo("Author", "Jordan Arenstein")
    saveProjectInfo("Description", "The classic retro game.")
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    backingMode(RETAINED)
    alive = true
    FRAME = 0
    SPEED = 30
    LEVEL = 0
    SCORE = -22
    
    Grid = {}
    for x = 1, 32 do
        for y = 1, 24 do
            table.insert(Grid, Cell(x,y))
        end
    end
    
    Walls = {}
    Snake = {}
    levelUp()
    food = Food()
end

function draw()
   
    if FRAME == 0 then
        background(255, 255, 255, 255)
        if alive == true then
            for i = 1, #Walls do
                Walls[i]:draw()
            end
            
            for i = 1, #Snake do
                Snake[i]:draw()
            end
            
            Snake[#Snake]:last()
            
            if Grid[ gridValue(Snake[1].pos) ]:safe() == false then
                sound(SOUND_EXPLODE)
                endGame()
            end
            
            food:draw()
            if #Snake - 4 + QUEUE > 15 then
                 levelUp()
            end
        else
            if SCORE < 10 then
                for k,n in ipairs(Numbers[SCORE + 1]) do
                    Grid[ gridValue(n) ]:wall()
                end
            else
                for k,n in ipairs(Numbers[math.floor(SCORE / 10) + 1]) do
                    Grid[ gridValue(n - vec2(3,0)) ]:wall()
                end
                for k,n in ipairs(Numbers[SCORE - math.floor(SCORE / 10) * 10 + 1]) do
                    Grid[ gridValue(n + vec2(3,0)) ]:wall()
                end
            end
        end
        for i = 1, #Grid do
            Grid[i]:draw()
            Grid[i]:empty()
        end
        
        FRAME = FRAME + 1
    else
        
        FRAME = FRAME + 1
        if FRAME >= SPEED then           
            FRAME = 0
        end
    end
end

function touched(t)
    Snake[1]:touched(t)
end

function endGame()
    alive = false
end
function gridValue(v)
    return (v.x - 1) * 24 + v.y
end

function levelUp()
    LEVEL = LEVEL + 1
    if LEVEL <= #Levels then
    Walls = {}
    for k, pos in ipairs(Levels[LEVEL]) do
        table.insert(Walls, Wall(pos))
    end
    SPEED = 32
    SCORE = SCORE + 20
    initializeSnake()
    else
        endGame()
    end
end

function initializeSnake()
    Snake = { Head(), Body(16,13, 2) }
    QUEUE = 1
end

Cell.lua =

Cell = class()

colors = {
    color(255, 255, 255, 255), color(0, 255, 0, 255), color(255, 0, 0, 255),
    color(127, 127, 127, 255), color(0, 0, 0, 255)
}
function Cell:init(x,y)
    self.pos = vec2(x * 32 - 16, y * 32 - 16)
    self.state = 1
end

function Cell:draw()
    noStroke()
    fill(colors[self.state])
    rectMode(CENTER)
    rect(self.pos.x,self.pos.y,33,33)
end

function Cell:empty()
    self.state = 1
end

function Cell:food()
    self.state = 2
end

function Cell:head()
    self.state = 3
end

function Cell:body()
    self.state = 4
end

function Cell:wall()
    self.state = 5
end

function Cell:safe()
    if self.state < 4 then 
        return true
    else
        return false
    end
end

Head.lua =

Head = class()

UP = vec2(0, 1)
DOWN = vec2(0, -1)
RIGHT = vec2(1, 0)
LEFT = vec2(-1, 0)

function Head:init()
    self.pos = vec2(17,13)
    self.prevPos = vec2(16,13)
    self.speed = RIGHT
    self.changeTo = RIGHT
end

function Head:draw()
    self.speed = self.changeTo
    self.prevPos = self.pos
    self.pos = self.pos + self.speed
    if self.pos.x < 1 then self.pos.x = 32 end
    if self.pos.y < 1 then self.pos.y = 24 end
    if self.pos.x > 32 then self.pos.x = 1 end
    if self.pos.y > 24 then self.pos.y = 1 end
    if Grid[ gridValue(Snake[1].pos) ]:safe() == false then
        sound(SOUND_EXPLODE) 
        endGame() 
    end
    Grid[ gridValue(self.pos) ]:head()
end

function Head:touched(t)
    d = vec2(math.floor(t.x / 32), math.floor(t.y / 32)) - self.pos
    axis = math.max(math.abs(d.x), math.abs(d.y))
    if axis == math.abs(d.x) and math.abs(self.speed.y) == 1 then
        if d.x > 0 then self.changeTo = RIGHT end
        if d.x < 0 then self.changeTo = LEFT end
    end
    if axis == math.abs(d.y) and math.abs(self.speed.x) == 1 then
        if d.y > 0 then self.changeTo = UP end
        if d.y < 0 then self.changeTo = DOWN end
    end
end

Body.lua =


Body = class()

function Body:init(x, y, i)
    self.pos = vec2(x, y)
    self.prevPos = self.pos
    self.index = i    
end

function Body:draw()
    self.prevPos = self.pos
    self.pos = Snake[self.index - 1].prevPos
    Grid[ gridValue(self.pos) ]:body()
end

function Body:last()
    if QUEUE > 0 then
        table.insert(Snake, Body(self.pos.x, self.pos.y, self.index + 1))
        QUEUE = QUEUE - 1
        SPEED = SPEED - 1.5
        SCORE = SCORE + 1
    end
end

Food.lua =

Food = class()

function Food:init()
    self.pos = vec2(math.random(1,32),math.random(1,24))
    QUEUE = QUEUE + 1
end

function Food:draw()
    if self.pos == Snake[1].pos then 
        sound(SOUND_PICKUP)
        self:init()
    else
        Grid[ gridValue(self.pos) ]:food()
    end
    while Grid[ gridValue(self.pos)].state > 2 do
        self.pos = vec2(math.random(1,32),math.random(1,24))
    end
end

Wall.lua =

Wall = class()

function Wall:init(pos)
    self.pos = pos
end

function Wall:draw()
    Grid[ gridValue(self.pos) ]:wall()
end

Numbers.lua =

Numbers = {
	{
		vec2(15, 17), vec2(16, 17), vec2(17, 17), vec2(18, 17), 
    	vec2(19, 17), vec2(15, 9), vec2(16, 9), vec2(17, 9), 
    	vec2(18, 9), vec2(19, 9), vec2(15, 16), vec2(15, 15), 
   		vec2(15, 14), vec2(15, 13), vec2(15, 12), vec2(15, 11), 
    	vec2(15, 10), vec2(19, 16), vec2(19, 15), vec2(19, 14), 
    	vec2(19, 13), vec2(19, 12), vec2(19, 11), vec2(19, 10)
    }, 
    
    {
        vec2(15, 14), vec2(16, 15), vec2(17, 16), vec2(17, 15), 
        vec2(17, 14), vec2(17, 13), vec2(17, 12), vec2(17, 11), 
        vec2(17, 10), vec2(15, 9), vec2(16, 9), vec2(17, 9), 
        vec2(18, 9), vec2(19, 9)
    }, 
    
    {
		vec2(15, 15), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 15), vec2(19, 14), vec2(18, 13), vec2(17, 12), 
        vec2(16, 11), vec2(15, 10), vec2(15, 9), vec2(16, 9), 
        vec2(17, 9), vec2(18, 9), vec2(19, 9)
    }, 
    
    {
        vec2(15, 15), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 15), vec2(19, 14), vec2(18, 13), vec2(17, 13), 
        vec2(19, 12), vec2(19, 11), vec2(19, 10), vec2(18, 9), 
        vec2(17, 9), vec2(16, 9), vec2(15, 10)
    }, 
    
    {
        vec2(15, 16), vec2(15, 15), vec2(15, 14), vec2(15, 13), 
        vec2(15, 12), vec2(15, 11), vec2(16, 11), vec2(17, 11), 
        vec2(18, 13), vec2(18, 12), vec2(18, 11), vec2(18, 10), 
        vec2(18, 9), vec2(19, 11)
    }, 
    
    {
        vec2(15, 16), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 16), vec2(15, 15), vec2(15, 14), vec2(16, 14), 
        vec2(17, 14), vec2(18, 14), vec2(19, 13), vec2(19, 12), 
        vec2(19, 11), vec2(19, 10), vec2(18, 9), vec2(17, 9), 
        vec2(16, 9), vec2(15, 10)
    }, 
    
    {
        vec2(15, 16), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 16), vec2(15, 15), vec2(15, 14), vec2(16, 13), 
        vec2(17, 13), vec2(18, 13), vec2(19, 13), vec2(15, 13), 
        vec2(15, 12), vec2(15, 11), vec2(15, 10), vec2(19, 12), 
        vec2(19, 11), vec2(19, 10), vec2(15, 9), vec2(16, 9), 
        vec2(17, 9), vec2(18, 9), vec2(19, 9)
    }, 
    
    {
        vec2(15, 16), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 16), vec2(19, 15), vec2(19, 14), vec2(19, 13), 
        vec2(19, 12), vec2(19, 11), vec2(19, 10), vec2(19, 9)
    }, 
    
    {
		vec2(15, 16), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 16), vec2(15, 9), vec2(16, 9), vec2(17, 9), 
        vec2(18, 9), vec2(19, 9), vec2(15, 15), vec2(15, 14), 
        vec2(15, 13), vec2(15, 12), vec2(15, 11), vec2(15, 10), 
        vec2(19, 15), vec2(19, 14), vec2(19, 13), vec2(19, 12), 
        vec2(19, 11), vec2(19, 10), vec2(16, 14), vec2(17, 14), 
        vec2(18, 14)
    }, 
    
    {
        vec2(15, 16), vec2(16, 16), vec2(17, 16), vec2(18, 16), 
        vec2(19, 16), vec2(15, 15), vec2(15, 14), vec2(15, 13), 
        vec2(15, 12), vec2(16, 12), vec2(17, 12), vec2(18, 12), 
        vec2(19, 12), vec2(15, 9), 
        vec2(16, 9), vec2(17, 9), vec2(18, 9), vec2(19, 9), 
        vec2(19, 15), vec2(19, 14), vec2(19, 13), vec2(19, 11), 
        vec2(19, 10)
    }
}

Levels.lua =

Levels = {
    {
    }, 
    
    {
        vec2(9, 20), vec2(9, 19), vec2(9, 18), vec2(9, 17),
        vec2(9, 16), vec2(9, 15), vec2(9, 14), vec2(9, 13),
        vec2(9, 12),vec2(9, 11), vec2(9, 10), vec2(9, 9),
        vec2(9, 8), vec2(9, 7), vec2(9, 6), vec2(9, 5),
        vec2(24, 20), vec2(24, 19), vec2(24, 18), vec2(24, 17),
        vec2(24, 16), vec2(24, 15), vec2(24, 14), vec2(24, 13),
        vec2(24, 12), vec2(24, 11), vec2(24, 10), vec2(24, 9), 
        vec2(24, 8), vec2(24, 7), vec2(24, 6), vec2(24, 5), 
    },
    
    {
        vec2(9, 20), vec2(9, 19), vec2(9, 18), vec2(9, 17),
        vec2(9, 16), vec2(9, 15), vec2(9, 14), vec2(9, 13), 
        vec2(9, 12), vec2(9, 11), vec2(9, 10), vec2(9, 9), 
        vec2(9, 8), vec2(9, 7), vec2(9, 6), vec2(9, 5),
        vec2(10, 20), vec2(10, 5), vec2(11, 20), vec2(11, 5), 
        vec2(12, 20),vec2(12, 5), vec2(13, 20), vec2(13, 5), 
        vec2(14, 20), vec2(14, 5), vec2(19, 20), vec2(19, 5), 
        vec2(20, 20), vec2(20, 5), vec2(21, 20), vec2(21, 5), 
        vec2(22, 20), vec2(22, 5), vec2(23, 20), vec2(23, 5), 
        vec2(24,20), vec2(24, 19), vec2(24, 18), vec2(24, 17), 
        vec2(24, 16), vec2(24, 15), vec2(24, 14), vec2(24, 13), 
        vec2(24, 12), vec2(24, 11), vec2(24, 10), vec2(24, 9),
        vec2(24, 8), vec2(24, 7), vec2(24, 6), vec2(24, 5) 
    },
    
    {
        vec2(1, 16), vec2(2, 16), vec2(3, 16), vec2(4, 16),
        vec2(5, 16), vec2(6, 16), vec2(7, 16), vec2(8, 16),
        vec2(8, 15), vec2(8, 14), vec2(8, 13), vec2(8, 12),
        vec2(8, 11), vec2(8, 10), vec2(8, 9), vec2(8,8), 
        vec2(8, 7), vec2(8, 6), vec2(8, 5), vec2(8, 4),
        vec2(8, 3), vec2(8, 2), vec2(8, 1), vec2(25, 24),
        vec2(25, 23), vec2(25, 22), vec2(25, 21), vec2(25, 20),
        vec2(25, 19), vec2(25, 18), vec2(25, 17), vec2(25, 16),
        vec2(25, 15), vec2(25, 14), vec2(25, 13), vec2(25, 12),
        vec2(25, 11), vec2(25, 10), vec2(25, 9), vec2(26, 9),
        vec2(27, 9), vec2(28, 9), vec2(29, 9), vec2(30, 9),
        vec2(31, 9), vec2(32, 9),   
    },
    {
    	vec2(1, 1), vec2(2, 1), vec2(3, 1), vec2(4, 1), 
    	vec2(5, 1), vec2(6, 1), vec2(7, 1), vec2(8, 1), 
    	vec2(9, 1), vec2(10, 1), vec2(11, 1), vec2(12, 1), 
    	vec2(13, 1), vec2(14, 1), vec2(15, 1), vec2(16, 1), 
    	vec2(17, 1), vec2(18, 1), vec2(19, 1), vec2(20, 1), 
    	vec2(21, 1), vec2(22, 1), vec2(23, 1), vec2(24, 1), 
    	vec2(25, 1), vec2(26, 1), vec2(27, 1), vec2(28, 1), 
    	vec2(29, 1), vec2(30, 1), vec2(31, 1), vec2(32, 1),
    	
    	vec2(1, 24), vec2(2, 24), vec2(3, 24), vec2(4, 24), 
    	vec2(5, 24), vec2(6, 24), vec2(7, 24), vec2(8, 24), 
    	vec2(9, 24), vec2(10, 24), vec2(11, 24), vec2(12, 24), 
    	vec2(13, 24), vec2(14, 24), vec2(15, 24), vec2(16, 24), 
    	vec2(17, 24), vec2(18, 24), vec2(19, 24), vec2(20, 24), 
    	vec2(21, 24), vec2(22, 24), vec2(23, 24), vec2(24, 24), 
    	vec2(25, 24), vec2(26, 24), vec2(27, 24), vec2(28, 24), 
    	vec2(29, 24), vec2(30, 24), vec2(31, 24), vec2(32, 24),
    	
    	vec2(1, 2), vec2(1, 3), vec2(1, 4), vec2(1, 5),
    	vec2(1, 6), vec2(1, 7), vec2(1, 8), vec2(1, 9),
    	vec2(1, 10), vec2(1, 11), vec2(1, 12), vec2(1, 13), 
    	vec2(1, 14), vec2(1, 15), vec2(1, 16), vec2(1, 17), 
    	vec2(1, 18), vec2(1, 19), vec2(1, 20), vec2(1, 21),
    	vec2(1, 22), vec2(1, 23),
    	
    	vec2(32, 2), vec2(32, 3), vec2(32, 4), vec2(32, 5),
    	vec2(32, 6), vec2(32, 7), vec2(32, 8), vec2(32, 9),
    	vec2(32, 10), vec2(32, 11), vec2(32, 12), vec2(32, 13), 
    	vec2(32, 14), vec2(32, 15), vec2(32, 16), vec2(32, 17), 
    	vec2(32, 18), vec2(32, 19), vec2(32, 20), vec2(32, 21),
    	vec2(32, 22), vec2(32, 23),  
    }
}

video from game?

How would you modify this game to use sprites? I tried making a few images up, but it’s not obvious to me how you would replace the Grid[ ]:draw with sprites. I also seem to only get the program to crash when try to initialize my sprites.

@Berentis, this would be VERY simple to implement ;). Use cell:draw, in that function it gets the color of the cell from its current state, you could change that to use sprites.

Here is the code for the Cell class that does it, (I just chose the most suitable sprites)

Cell = class()

sprites = {
    "Small World:Grass Patch", "Small World:Heart Glow", "Small World:Bunny Skull", 
    "Small World:Treasure", "Small World:Tree Icon"
}
function Cell:init(x,y)
    self.pos = vec2(x * 32 - 16, y * 32 - 16)
    self.state = 1
end

function Cell:draw()
    noStroke()
    sprite(sprites[self.state], self.pos.x, self.pos.y, 32, 32)
end

function Cell:empty()
    self.state = 1
end

function Cell:food()
    self.state = 2
end

function Cell:head()
    self.state = 3
end

function Cell:body()
    self.state = 4
end

function Cell:wall()
    self.state = 5
end

function Cell:safe()
    if self.state < 4 then 
        return true
    else
        return false
    end
end