-- title: Snake -- author: Bob Grant -- script: lua gameStateInit = 5 gameStateStart = 10 gameStatePlay = 20 gameStateDead = 30 gameStateEnd = 40 gameState = gameStateStart snakeSpawnPosition = { x = 5, y = 5 } snakeStartLength = 5 snakeDirectionUp = 0 snakeDirectionDown = 1 snakeDirectionLeft = 2 snakeDirectionRight = 3 snakeStartSpeed = 10 snakeMaxHunger = 99 snake = { body = {}, direction = snakeDirectionRight, speed = snakeStartSpeed, growCounter = 0, hunger = 0 } food = {} maxFood = 10 foodMaxTimer = 600 foodMinTimer = 180 foodMaxGrowth = 10 foodNumSprites = 5 foodBaseSprite = 16 score = 0 boardXMin = 1 boardXMax = 58 boardYMin = 3 boardYMax = 32 function TIC() if gameState == gameStateStart then startGame() elseif gameState == gameStateInit then initGame() elseif gameState == gameStatePlay then playGame() elseif gameState == gameStateEnd then endGame() end -- if end -- TIC function startGame() if btnp(4) then gameState = gameStateInit end --if end -- startGame function initGame() score = 0 -- generate snake snake.body = {} -- head table.insert(snake.body, { x = snakeSpawnPosition.x + 1, y = snakeSpawnPosition.y } ) -- body for bodyPart = 1,snakeStartLength - 1 do table.insert(snake.body, { x = snakeSpawnPosition.x, y = snakeSpawnPosition.y } ) end -- for snake.direction = snakeDirectionRight snake.speed = snakeStartSpeed snake.moveCounter = snakeStartSpeed snake.growCounter = 0 snake.hunger = 0 food = {} -- reset food gameState = gameStatePlay end -- initGame function endGame() cls() drawOutline() drawScore() drawHungerBar() drawSnake() drawFood() print("Game Over - Press Z to play SNAKE", 30, 50) if btnp(4) then gameState = gameStateInit end --if end -- endGame function playGame() cls() drawOutline() drawScore() checkKeys() moveSnake() drawHungerBar() checkCollision() drawSnake() handleFood() drawFood() end -- gameStatePlay function drawOutline() line(3,11,236,11,14) line(236,11,236,132,14) line(236,132,3,132,14) line(3,132,3,11,14) end -- drawOutline function drawScore() print("Score : "..score,0,0) end -- drawScore function checkKeys() if btnp(0) and snake.direction ~= snakeDirectionDown then snake.direction = snakeDirectionUp elseif btnp(1) and snake.direction ~= snakeDirectionUp then snake.direction = snakeDirectionDown elseif btnp(2) and snake.direction ~= snakeDirectionRight then snake.direction = snakeDirectionLeft elseif btnp(3) and snake.direction ~= snakeDirectionLeft then snake.direction = snakeDirectionRight end -- if end -- checkKeys function moveSnake() snake.moveCounter = snake.moveCounter - 1 if snake.moveCounter <= 0 then snake.moveCounter = snake.speed -- move body parts for bodyPart = #snake.body, 2, -1 do snake.body[bodyPart].x = snake.body[bodyPart - 1].x snake.body[bodyPart].y = snake.body[bodyPart - 1].y end -- for -- move head if snake.direction == snakeDirectionUp then snake.body[1].y = snake.body[1].y - 1 elseif snake.direction == snakeDirectionDown then snake.body[1].y = snake.body[1].y + 1 elseif snake.direction == snakeDirectionLeft then snake.body[1].x = snake.body[1].x - 1 elseif snake.direction == snakeDirectionRight then snake.body[1].x = snake.body[1].x + 1 end -- if -- snake health timer snake.hunger = snake.hunger + 1 if snake.hunger > 75 then sfx(0,snake.hunger-40,5,0,10,0) end -- if if snake.hunger > snakeMaxHunger then gameState = gameStateEnd end -- if end -- if moveCounter -- check growing if snake.growCounter > 0 then table.insert(snake.body, { x = snake.body[#snake.body].x, y = snake.body[#snake.body].y } ) snake.growCounter = snake.growCounter - 1 if snake.growCounter < 0 then snake.growCounter = 0 end end -- if snake.speed = snakeStartSpeed - math.floor(#snake.body / 20) if snake.speed < 0 then snake.speed = 0 end -- if end -- moveSnake function drawHungerBar() rect(135,3,102,4,15) if snake.hunger > 50 then rect(136,4,50,2,5) else rect(136,4,snake.hunger,2,5) end -- if if snake.hunger > 75 then rect(186,4,25,2,9) else rect(186,4,snake.hunger-50,2,9) end -- if if snake.hunger > 75 then rect(211,4,snake.hunger-75,2,6) end -- if end -- drawHungerBar() function checkCollision() -- walls --boardXMin = 2 --boardXMax = 59 --boardYMin = 3 --boardYMax = 33 if snake.body[1].x < boardXMin or snake.body[1].x > boardXMax or snake.body[1].y < boardYMin or snake.body[1].y > boardYMax then gameState = gameStateEnd elseif checkBodyCollision( snake.body[1].x, snake.body[1].y) then gameState = gameStateEnd end local foodPiece = checkFoodCollision( snake.body[1].x, snake.body[1].y) if foodPiece ~= 0 then snake.growCounter = snake.growCounter + food[foodPiece].growth score = score + food[foodPiece].growth sfx(1,20 + (food[foodPiece].growth * 2),20,1,15,0) table.remove(food, foodPiece) snake.hunger = 0 end -- if end -- checkCollision function checkFoodCollision(x, y) for index, foodPiece in ipairs(food) do if foodPiece.x == x and foodPiece.y == y then return index end -- if end -- for return 0 -- no food end -- if function checkBodyCollision(x, y) for bodyPart = #snake.body, 2, -1 do if snake.body[bodyPart].x == x and snake.body[bodyPart].y == y then return true end -- if end -- for return false end -- checkBodyCollision function drawSnake() --body for bodyPart = #snake.body, 2, -1 do spr(0,snake.body[bodyPart].x * 4, snake.body[bodyPart].y * 4, 0) end -- for -- head local headSprite = 1 + snake.direction spr(headSprite,snake.body[1].x * 4, snake.body[1].y * 4, 0) end -- drawSnake function handleFood() -- time food for index, foodObject in ipairs(food) do foodObject.timer = foodObject.timer - 1 if foodObject.timer < 0 then table.remove(food, index) end -- if end -- for -- check for food spawn if (#food < maxFood) and (math.random(180) <= 4) then local foodX = math.random(boardXMin, boardXMax) local foodY = math.random(boardYMin, boardYMax) local foodTime = math.random(foodMinTimer, foodMaxTimer) local foodGrowth = math.random(1,foodMaxGrowth) local foodSprite = math.random(0,foodNumSprites) table.insert(food, { x = foodX, y = foodY, timer = foodTime, growth = foodGrowth, sprite = foodSprite } ) end -- if end -- spawnFood function drawFood() for index, foodObject in ipairs(food) do spr(foodBaseSprite + foodObject.sprite, foodObject.x * 4, foodObject.y * 4, 0 ) end -- for end -- drawFood