Snake game

Here is the first game I’ve made in Codea. Just a simple snake game, you collect the yellow pellet, avoid the red pellets, walls, and yourself, etc. Swipe to move. The snake gets faster as the score increases.

I am getting a bug where the snake stays at the same speed for a while, then suddenly gets a lot faster. Can anyone help me with this?

--# Main
-- Snake

function collision()
    if snake.positions[1].x == -1 or snake.positions[1].x == STAGESIZE.x + 1 or
       snake.positions[1].y == -1 or snake.positions[1].y == STAGESIZE.y + 1 then
        return true
    end
    for _, v in ipairs(bombs) do
        if v.pos == snake.positions[1] then
            return true
        end
    end
    for i = 2, table.maxn(snake.positions) do
        if snake.positions[i] == snake.positions[1] then
            return true
        end
    end
    return false
end

-- Use this function to perform your initial setup
function setup()
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    stage = Stage()
    stage.backgroundcolor = color(0, 0, 0, 255)
    recordTouch = true
    -- Time is time since last update, speed is the FPS
    time = 0
    
    snake = Snake({vec2(20, 20), vec2(21, 20)}, sLEFT)
    pellet = Pellet(vec2(math.random(STAGESIZE.x),
                         math.random(STAGESIZE.y)))
    bombs = {}
    
    alive = true
    score = 0
    speed = STARTSPEED
    wait = 1/speed
end

-- This function gets called once every frame
function draw()
    noStroke()
    -- Draw evrything
    stage:draw()
    pellet:draw()
    for _, v in pairs(bombs) do
        v:draw()
    end
    snake:draw()
    
    fill(255, 255, 255, 255)
    textMode(CENTER)
    font("Futura-Medium")
    fontSize(24)
    text("Score: " .. score, WIDTH/2, HEIGHT-25)
    
    if alive then
        -- Wait until enough time has passed
        if ElapsedTime - time > wait then
            time = ElapsedTime
            snake:move()
            if snake.positions[1] == pellet.pos then
                -- update the score and speed
                pellet.pos = vec2(math.random(STAGESIZE.x), math.random(STAGESIZE.y))
                table.insert(snake.positions, snake.positions[table.maxn(snake.positions)])
                sound(DATA, "ZgBAQgBAQEBAQEBAAAAAAEsMiT2zWuw+YQBAf0BAQEBAQGlh")
                score = score + 1
                speed = speed * SPEEDMULTIPLIER
                wait = 1/speed
                table.insert(bombs, Bomb(vec2(math.random(STAGESIZE.x), math.random(STAGESIZE.y))))
            end
            if collision() then
                alive = false
                time = ElapsedTime
                sound(SOUND_EXPLODE, 29798)
            end
        end
    else
        -- If dead, wait 1.5 seconds and restart
        if ElapsedTime - time > 1.5 then
            setup()
        end
    end
end

function touched(touch)
    if CurrentTouch.state == BEGAN or touchStart then
        firstTouch = vec2(CurrentTouch.x, CurrentTouch.y)
        recordTouch = true
    elseif CurrentTouch.state == MOVING and recordTouch then
        local currentTouch, angle
        currentTouch = vec2(CurrentTouch.x, CurrentTouch.y)
        if firstTouch:distSqr(currentTouch) > SQRSWIPELENGTH then
            angle = math.atan2(currentTouch.y - firstTouch.y,
                               currentTouch.x - firstTouch.x)
            angle = math.floor(2*angle/math.pi + 0.5)
            if (angle == -2 or angle == 2) and not (snake.direction == sRIGHT) then
                snake.direction = sLEFT
            elseif angle == 1 and not (snake.direction == sDOWN) then
                snake.direction = sUP
            elseif angle == 0 and not (snake.direction == sLEFT) then
                snake.direction = sRIGHT
            elseif angle == -1 and not (snake.direction == sUP) then
                snake.direction = sDOWN
            end
            recordTouch = False
        end
    end
end
--# Bomb
Bomb = class()

function Bomb:init(pos)
    -- you can accept and set parameters here
    self.pos = pos
end

function Bomb:draw()
    pushStyle()
    fill(213, 12, 12, 255)
    drawgridsquare(self.pos.x, self.pos.y)
    popStyle()
end

--# Constants
STAGESIZE = vec2(50, 35)
CELLSIZE = 20
SPACESIZE = 1

-- The length of the swipe needed to turn the snake, squared
SQRSWIPELENGTH = 400

sLEFT = 1
sRIGHT = 2
sUP = 3
sDOWN = 4

STARTSPEED = 6
SPEEDMULTIPLIER = 1.05
--# GlobalFunctions
function drawgridsquare(row, col)
    rect((row*CELLSIZE)+SPACESIZE, (col*CELLSIZE)+SPACESIZE, CELLSIZE-SPACESIZE, CELLSIZE-SPACESIZE)
end
--# Pellet
Pellet = class()

function Pellet:init(pos)
    -- you can accept and set parameters here
    self.pos = pos
end

function Pellet:draw()
    pushStyle()
    fill(255, 220, 0, 255)
    drawgridsquare(self.pos.x, self.pos.y)
    popStyle()
end
--# Snake
Snake = class()

function Snake:init(positions, direction)
    -- self.positions = {vec2(20, 20), vec2(21, 20)}
    -- self.direction = sLEFT
    self.positions = positions
    self.direction = direction
end

function Snake:draw()
    -- Draw the squares
    pushStyle()
    fill(10, 10, 10, 255)
    for i, v in pairs(self.positions) do
        drawgridsquare(v.x, v.y)
    end
    popStyle()
end

function Snake:move()
    table.remove(self.positions)
    if self.direction == sLEFT then
        table.insert(self.positions, 1, vec2(self.positions[1].x-1, self.positions[1].y))
    elseif self.direction == sRIGHT then
        table.insert(self.positions, 1, vec2(self.positions[1].x+1, self.positions[1].y))
    elseif self.direction == sUP then
        table.insert(self.positions, 1, vec2(self.positions[1].x, self.positions[1].y+1))
    elseif self.direction == sDOWN then
        table.insert(self.positions, 1, vec2(self.positions[1].x, self.positions[1].y-1))
    end
end
--# Stage
Stage = class()

function Stage:init()
    -- you can accept and set parameters here
    self.backgroundcolor = color(0, 0, 0, 255)
end

function Stage:draw()
    pushStyle()
    fill(self.backgroundcolor)
    
    background(0, 0, 0, 255)
    for x = 0, STAGESIZE[1] do
        for y = 0, STAGESIZE[2] do
            fill(193, 193, 193, 255)
            drawgridsquare(x, y)
        end
    end
    popStyle()
end

Hi @floppy_gunk, try leave a line between your
~~.~
Code
~~.~

Yes, the tildes have to be on their own lines. I’ve edited the first post to correct that.

With the speed change, try displaying your frame rate on the screen and see if there’s a change at some point.