286 lines
7.2 KiB
Lua
286 lines
7.2 KiB
Lua
-- SPDX-FileCopyrightText: 2017 Daniel Ratcliffe
|
|
--
|
|
-- SPDX-License-Identifier: LicenseRef-CCPL
|
|
|
|
-- Display the start screen
|
|
local w, h = term.getSize()
|
|
|
|
local headingColour, textColour, wormColour, fruitColour
|
|
if term.isColour() then
|
|
headingColour = colours.yellow
|
|
textColour = colours.white
|
|
wormColour = colours.green
|
|
fruitColour = colours.red
|
|
else
|
|
headingColour = colours.white
|
|
textColour = colours.white
|
|
wormColour = colours.white
|
|
fruitColour = colours.white
|
|
end
|
|
|
|
local function printCentred(y, s)
|
|
local x = math.floor((w - #s) / 2)
|
|
term.setCursorPos(x, y)
|
|
--term.clearLine()
|
|
term.write(s)
|
|
end
|
|
|
|
local xVel, yVel = 1, 0
|
|
local xPos, yPos = math.floor(w / 2), math.floor(h / 2)
|
|
local pxVel, pyVel = nil, nil
|
|
local nExtraLength = 6
|
|
local bRunning = true
|
|
|
|
local tailX, tailY = xPos, yPos
|
|
local nScore = 0
|
|
local nDifficulty = 2
|
|
local nSpeed, nInterval
|
|
|
|
-- Setup the screen
|
|
local screen = {}
|
|
for x = 1, w do
|
|
screen[x] = {}
|
|
for y = 1, h do
|
|
screen[x][y] = {}
|
|
end
|
|
end
|
|
screen[xPos][yPos] = { snake = true }
|
|
|
|
local nFruit = 1
|
|
local tFruits = {
|
|
"A", "B", "C", "D", "E", "F", "G", "H",
|
|
"I", "J", "K", "L", "M", "N", "O", "P",
|
|
"Q", "R", "S", "T", "U", "V", "W", "X",
|
|
"Y", "Z",
|
|
"a", "b", "c", "d", "e", "f", "g", "h",
|
|
"i", "j", "k", "l", "m", "n", "o", "p",
|
|
"q", "r", "s", "t", "u", "v", "w", "x",
|
|
"y", "z",
|
|
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
|
|
"@", "$", "%", "#", "&", "!", "?", "+", "*", "~",
|
|
}
|
|
|
|
local function addFruit()
|
|
while true do
|
|
local x = math.random(1, w)
|
|
local y = math.random(2, h)
|
|
local fruit = screen[x][y]
|
|
if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then
|
|
screen[x][y] = { fruit = true }
|
|
term.setCursorPos(x, y)
|
|
term.setBackgroundColour(fruitColour)
|
|
term.write(" ")
|
|
term.setBackgroundColour(colours.black)
|
|
break
|
|
end
|
|
end
|
|
|
|
nFruit = nFruit + 1
|
|
if nFruit > #tFruits then
|
|
nFruit = 1
|
|
end
|
|
end
|
|
|
|
local function drawMenu()
|
|
term.setTextColour(headingColour)
|
|
term.setCursorPos(1, 1)
|
|
term.write("SCORE ")
|
|
|
|
term.setTextColour(textColour)
|
|
term.setCursorPos(7, 1)
|
|
term.write(tostring(nScore))
|
|
|
|
term.setTextColour(headingColour)
|
|
term.setCursorPos(w - 11, 1)
|
|
term.write("DIFFICULTY ")
|
|
|
|
term.setTextColour(textColour)
|
|
term.setCursorPos(w, 1)
|
|
term.write(tostring(nDifficulty or "?"))
|
|
|
|
term.setTextColour(colours.white)
|
|
end
|
|
|
|
local function update( )
|
|
if pxVel and pyVel then
|
|
xVel, yVel = pxVel, pyVel
|
|
pxVel, pyVel = nil, nil
|
|
end
|
|
|
|
-- Remove the tail
|
|
if nExtraLength == 0 then
|
|
local tail = screen[tailX][tailY]
|
|
screen[tailX][tailY] = {}
|
|
term.setCursorPos(tailX, tailY)
|
|
term.write(" ")
|
|
tailX = tail.nextX
|
|
tailY = tail.nextY
|
|
else
|
|
nExtraLength = nExtraLength - 1
|
|
end
|
|
|
|
-- Update the head
|
|
local head = screen[xPos][yPos]
|
|
local newXPos = xPos + xVel
|
|
local newYPos = yPos + yVel
|
|
if newXPos < 1 then
|
|
newXPos = w
|
|
elseif newXPos > w then
|
|
newXPos = 1
|
|
end
|
|
if newYPos < 2 then
|
|
newYPos = h
|
|
elseif newYPos > h then
|
|
newYPos = 2
|
|
end
|
|
|
|
local newHead = screen[newXPos][newYPos]
|
|
if newHead.snake == true or newHead.wall == true then
|
|
bRunning = false
|
|
|
|
else
|
|
if newHead.fruit == true then
|
|
nScore = nScore + 10
|
|
nExtraLength = nExtraLength + 1
|
|
addFruit()
|
|
end
|
|
xPos = newXPos
|
|
yPos = newYPos
|
|
head.nextX = newXPos
|
|
head.nextY = newYPos
|
|
screen[newXPos][newYPos] = { snake = true }
|
|
|
|
end
|
|
|
|
term.setCursorPos(xPos, yPos)
|
|
term.setBackgroundColour(wormColour)
|
|
term.write(" ")
|
|
term.setBackgroundColour(colours.black)
|
|
|
|
drawMenu()
|
|
end
|
|
|
|
-- Display the frontend
|
|
term.clear()
|
|
local function drawFrontend()
|
|
--term.setTextColour( titleColour )
|
|
--printCentred( math.floor(h/2) - 4, " W O R M " )
|
|
|
|
term.setTextColour(headingColour)
|
|
printCentred(math.floor(h / 2) - 3, "")
|
|
printCentred(math.floor(h / 2) - 2, " SELECT DIFFICULTY ")
|
|
printCentred(math.floor(h / 2) - 1, "")
|
|
|
|
printCentred(math.floor(h / 2) + 0, " ")
|
|
printCentred(math.floor(h / 2) + 1, " ")
|
|
printCentred(math.floor(h / 2) + 2, " ")
|
|
printCentred(math.floor(h / 2) - 1 + nDifficulty, " [ ] ")
|
|
|
|
term.setTextColour(textColour)
|
|
printCentred(math.floor(h / 2) + 0, "EASY")
|
|
printCentred(math.floor(h / 2) + 1, "MEDIUM")
|
|
printCentred(math.floor(h / 2) + 2, "HARD")
|
|
printCentred(math.floor(h / 2) + 3, "")
|
|
|
|
term.setTextColour(colours.white)
|
|
end
|
|
|
|
drawMenu()
|
|
drawFrontend()
|
|
while true do
|
|
local _, key = os.pullEvent("key")
|
|
if key == keys.up or key == keys.w then
|
|
-- Up
|
|
if nDifficulty > 1 then
|
|
nDifficulty = nDifficulty - 1
|
|
drawMenu()
|
|
drawFrontend()
|
|
end
|
|
elseif key == keys.down or key == keys.s then
|
|
-- Down
|
|
if nDifficulty < 3 then
|
|
nDifficulty = nDifficulty + 1
|
|
drawMenu()
|
|
drawFrontend()
|
|
end
|
|
elseif key == keys.enter or key == keys.numPadEnter then
|
|
-- Enter/Numpad Enter
|
|
break
|
|
end
|
|
end
|
|
|
|
local tSpeeds = { 5, 10, 25 }
|
|
nSpeed = tSpeeds[nDifficulty]
|
|
nInterval = 1 / nSpeed
|
|
|
|
-- Grow the snake to its intended size
|
|
term.clear()
|
|
drawMenu()
|
|
screen[tailX][tailY].snake = true
|
|
while nExtraLength > 0 do
|
|
update()
|
|
end
|
|
addFruit()
|
|
addFruit()
|
|
|
|
-- Play the game
|
|
local timer = os.startTimer(0)
|
|
while bRunning do
|
|
local event, p1 = os.pullEvent()
|
|
if event == "timer" and p1 == timer then
|
|
timer = os.startTimer(nInterval)
|
|
update(false)
|
|
|
|
elseif event == "key" then
|
|
local key = p1
|
|
if key == keys.up or key == keys.w then
|
|
-- Up
|
|
if yVel == 0 then
|
|
pxVel, pyVel = 0, -1
|
|
end
|
|
elseif key == keys.down or key == keys.s then
|
|
-- Down
|
|
if yVel == 0 then
|
|
pxVel, pyVel = 0, 1
|
|
end
|
|
elseif key == keys.left or key == keys.a then
|
|
-- Left
|
|
if xVel == 0 then
|
|
pxVel, pyVel = -1, 0
|
|
end
|
|
|
|
elseif key == keys.right or key == keys.d then
|
|
-- Right
|
|
if xVel == 0 then
|
|
pxVel, pyVel = 1, 0
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Display the gameover screen
|
|
term.setTextColour(headingColour)
|
|
printCentred(math.floor(h / 2) - 2, " ")
|
|
printCentred(math.floor(h / 2) - 1, " G A M E O V E R ")
|
|
|
|
term.setTextColour(textColour)
|
|
printCentred(math.floor(h / 2) + 0, " ")
|
|
printCentred(math.floor(h / 2) + 1, " FINAL SCORE " .. nScore .. " ")
|
|
printCentred(math.floor(h / 2) + 2, " ")
|
|
term.setTextColour(colours.white)
|
|
|
|
local timer = os.startTimer(2.5)
|
|
repeat
|
|
local e, p = os.pullEvent()
|
|
if e == "timer" and p == timer then
|
|
term.setTextColour(textColour)
|
|
printCentred(math.floor(h / 2) + 2, " PRESS ANY KEY ")
|
|
printCentred(math.floor(h / 2) + 3, " ")
|
|
term.setTextColour(colours.white)
|
|
end
|
|
until e == "char"
|
|
|
|
term.clear()
|
|
term.setCursorPos(1, 1)
|