mirror of
https://github.com/LDDestroier/CC/
synced 2024-10-31 15:16:19 +00:00
1092 lines
26 KiB
Lua
1092 lines
26 KiB
Lua
--[[
|
||
TRON Light Cycle Game
|
||
programmed by LDDestroier
|
||
|
||
wget https://raw.githubusercontent.com/LDDestroier/CC/master/tron.lua
|
||
--]]
|
||
|
||
local port = 701
|
||
local scr_x, scr_y = term.getSize()
|
||
local isColor = term.isColor()
|
||
|
||
-- lower value = faster game. I'd reccommend 0.1 for SMP play.
|
||
local gameDelayInit = 0.1
|
||
local doDrawPlayerNames = false
|
||
|
||
local initGrid = {
|
||
x1 = -100,
|
||
y1 = -100,
|
||
x2 = 100,
|
||
y2 = 100,
|
||
border = "#",
|
||
voidcol = "f",
|
||
forecol = "8",
|
||
backcol = "7",
|
||
edgecol = "0"
|
||
}
|
||
local resetPlayers = function()
|
||
return {
|
||
[1] = {
|
||
num = 1,
|
||
x = -2,
|
||
y = -5,
|
||
direction = -1,
|
||
char = "@",
|
||
color = {
|
||
colors.blue,
|
||
colors.blue,
|
||
colors.blue,
|
||
colors.cyan,
|
||
colors.cyan,
|
||
colors.lightBlue,
|
||
colors.lightBlue,
|
||
colors.cyan,
|
||
colors.cyan
|
||
},
|
||
dead = false,
|
||
putTrail = true,
|
||
name = "BLU"
|
||
},
|
||
[2] = {
|
||
num = 2,
|
||
x = 2,
|
||
y = -5,
|
||
direction = -1,
|
||
char = "@",
|
||
color = {
|
||
colors.red,
|
||
colors.red,
|
||
colors.red,
|
||
colors.orange,
|
||
colors.orange,
|
||
colors.yellow,
|
||
colors.yellow,
|
||
colors.orange,
|
||
colors.orange
|
||
},
|
||
dead = false,
|
||
putTrail = true,
|
||
name = "RED"
|
||
}
|
||
}
|
||
end
|
||
local tArg = {...}
|
||
local useSkynet = (tArg[1] or ""):lower() == "skynet"
|
||
local useOnce = (tArg[2] or tArg[1] or ""):lower() == "quick"
|
||
local argumentName = tArg[3] or tArg[2] or tArg[1] or nil
|
||
local skynetPath = "skynet"
|
||
local skynetURL = "https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"
|
||
|
||
local modem, skynet
|
||
if useSkynet then
|
||
if fs.exists(skynetPath) then
|
||
skynet = dofile(skynetPath)
|
||
skynet.open(port)
|
||
else
|
||
local prog = http.get(skynetURL)
|
||
if prog then
|
||
local file = fs.open(skynetPath, "w")
|
||
file.write(prog.readAll())
|
||
file.close()
|
||
skynet = dofile(skynetPath)
|
||
skynet.open(port)
|
||
else
|
||
error("Could not download Skynet.")
|
||
end
|
||
end
|
||
else
|
||
modem = peripheral.find("modem")
|
||
if (not modem) and ccemux then
|
||
ccemux.attach("top", "wireless_modem")
|
||
modem = peripheral.find("modem")
|
||
end
|
||
if modem then
|
||
modem.open(port)
|
||
else
|
||
error("You should attach a modem.")
|
||
end
|
||
end
|
||
|
||
local transmit = function(port, message)
|
||
if useSkynet then
|
||
skynet.send(port, message)
|
||
else
|
||
modem.transmit(port, port, message)
|
||
end
|
||
end
|
||
|
||
local gamename = ""
|
||
local isHost
|
||
local squareGrid = true
|
||
|
||
local waitingForGame = true
|
||
local toblit = {
|
||
[0] = " ",
|
||
[colors.white] = "0",
|
||
[colors.orange] = "1",
|
||
[colors.magenta] = "2",
|
||
[colors.lightBlue] = "3",
|
||
[colors.yellow] = "4",
|
||
[colors.lime] = "5",
|
||
[colors.pink] = "6",
|
||
[colors.gray] = "7",
|
||
[colors.lightGray] = "8",
|
||
[colors.cyan] = "9",
|
||
[colors.purple] = "a",
|
||
[colors.blue] = "b",
|
||
[colors.brown] = "c",
|
||
[colors.green] = "d",
|
||
[colors.red] = "e",
|
||
[colors.black] = "f"
|
||
}
|
||
local tograyCol, tograyBlit = {
|
||
[0] = 0,
|
||
[colors.white] = colors.white,
|
||
[colors.orange] = colors.lightGray,
|
||
[colors.magenta] = colors.lightGray,
|
||
[colors.lightBlue] = colors.white,
|
||
[colors.yellow] = colors.white,
|
||
[colors.lime] = colors.lightGray,
|
||
[colors.pink] = colors.lightGray,
|
||
[colors.gray] = colors.gray,
|
||
[colors.lightGray] = colors.lightGray,
|
||
[colors.cyan] = colors.lightGray,
|
||
[colors.purple] = colors.gray,
|
||
[colors.blue] = colors.gray,
|
||
[colors.brown] = colors.gray,
|
||
[colors.green] = colors.gray,
|
||
[colors.red] = colors.white,
|
||
[colors.black] = colors.black
|
||
}, {}
|
||
|
||
local tocolors = {}
|
||
for k,v in pairs(toblit) do
|
||
tocolors[v] = k
|
||
end
|
||
for k,v in pairs(tograyCol) do
|
||
tograyBlit[toblit[k]] = toblit[v]
|
||
end
|
||
|
||
local termwrite, termclear = term.write, term.clear
|
||
local termsetCursorPos, termgetCursorPos = term.setCursorPos, term.getCursorPos
|
||
local tableunpack, tableremove = unpack, table.remove
|
||
local mathfloor, mathceil, mathcos, mathsin, mathrandom, mathrad = math.floor, math.ceil, math.cos, math.sin, math.random, math.rad
|
||
|
||
local termsetTextColor = function(col)
|
||
return term.setTextColor(isColor and col or tograyCol[col])
|
||
end
|
||
|
||
local termsetBackgroundColor = function(col)
|
||
return term.setBackgroundColor(isColor and col or tograyCol[col])
|
||
end
|
||
|
||
local termblit = function(char, text, back)
|
||
if isColor then
|
||
return term.blit(char, text, back)
|
||
else
|
||
return term.blit(
|
||
char,
|
||
text:gsub(".", tograyBlit),
|
||
back:gsub(".", tograyBlit)
|
||
)
|
||
end
|
||
end
|
||
|
||
local tsv = function(visible)
|
||
if term.current().setVisible then
|
||
term.current().setVisible(visible)
|
||
end
|
||
end
|
||
|
||
local deepCopy
|
||
deepCopy = function(tbl, ...)
|
||
local output = {}
|
||
for k,v in pairs(tbl) do
|
||
if type(v) == "table" then
|
||
output[k] = deepCopy(v)
|
||
else
|
||
output[k] = v
|
||
end
|
||
end
|
||
for i = 1, #arg do
|
||
output[#output+1] = arg[i]
|
||
end
|
||
return output
|
||
end
|
||
|
||
grid = deepCopy(initGrid)
|
||
|
||
local you = 1
|
||
local nou = 2
|
||
|
||
local keysDown = {}
|
||
local netKeysDown = {}
|
||
local lastDirectionPressed
|
||
local netLastDirectionPressed
|
||
|
||
-- the scrolling of the screen
|
||
local scrollX = 0
|
||
local scrollY = 0
|
||
|
||
-- used when panning with WASD
|
||
local scrollAdjX = 0
|
||
local scrollAdjY = 0
|
||
|
||
local lockInput = false
|
||
local player
|
||
|
||
player = resetPlayers()
|
||
|
||
local images = {
|
||
logo = {
|
||
{
|
||
" ",
|
||
" ",
|
||
" ",
|
||
" ",
|
||
"
",
|
||
" ",
|
||
"
",
|
||
},
|
||
{
|
||
" f7777777777777777777f f77777f 7f f777",
|
||
" f99979999979999999999f 799999799 77f7 f997",
|
||
" 799 79999f997 9977997f f997",
|
||
" 799 7797777fffff997 9977997797997",
|
||
" 799 799 799977f7797fff7997799 79797",
|
||
" 799 799 7797f 797999997 799 797",
|
||
" 777 777 7777 7777777 777 77",
|
||
},
|
||
{
|
||
" 7999999999f9999999997 7999997 97 799f",
|
||
" 7777997777f77777779997 997777997 997f 799f",
|
||
" 997 f7777799 799f99997 799f",
|
||
" 997 997f9997fff799 799f997ff7999f",
|
||
" 997 997 f7999fff999777997f997 f799f",
|
||
" 997 997 f9997 f7999977f 997 f7f",
|
||
" fff fff ffff fffffff fff ff",
|
||
}
|
||
},
|
||
win = {
|
||
{
|
||
"",
|
||
"",
|
||
"",
|
||
"
",
|
||
"",
|
||
"",
|
||
},
|
||
{
|
||
"55 55 555555 5 5 55",
|
||
"55 5555 55 5 55 5 5 55",
|
||
"55 5 55 55 5555 5 55",
|
||
"55 55 55 55 55 5 5 55",
|
||
"5 55 5 55 5 55 55 555 5",
|
||
"555 555 555555 55 5 55",
|
||
},
|
||
{
|
||
"5 5 5555555 55 55 5 ",
|
||
"5 5 5 555 55 5 ",
|
||
"5 5 5 5 5 55 55 5 ",
|
||
"5 55 55 5 5 5 5555 5 ",
|
||
"555 555 5 5 5 5 55 5 ",
|
||
"5 5 5555555 5 55 5 ",
|
||
}
|
||
},
|
||
lose = {
|
||
{
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"
",
|
||
"",
|
||
},
|
||
{
|
||
"ee eee e eeeee eeeeeee",
|
||
"ee eee e e ee ee ee ee",
|
||
"ee ee e ee e e ",
|
||
"ee ee e eeeee e eeeeee ",
|
||
"ee e e e e e ee ",
|
||
"eeeeeee e eeeee eeeeee eeeeeee",
|
||
},
|
||
{
|
||
"e eeeeee eeeeeee eeeeeee",
|
||
"e e ee e e ",
|
||
"e e ee eeeeeee eeeee ",
|
||
"e e ee ee e ",
|
||
"e ee eee e ee e ee",
|
||
"eeeeeee eeee eeeeee eeeeeee",
|
||
}
|
||
},
|
||
tie = {
|
||
{
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
"",
|
||
},
|
||
{
|
||
"77888800 0000000 0888877",
|
||
" 88 00 0 0 08 7",
|
||
" 88 0 0 7 ",
|
||
" 88 0 088887 ",
|
||
" 88 0 0 08 ",
|
||
" 88 0000000 0888877",
|
||
},
|
||
{
|
||
"7788880 00000000 0888877",
|
||
" 8 00 0 ",
|
||
" 8 00 08888 ",
|
||
" 8 00 0 ",
|
||
" 8 0 00 0 0 7",
|
||
" 8 00000000 0888877",
|
||
},
|
||
}
|
||
}
|
||
for k,v in pairs(images) do
|
||
v.x = #v[1][1]
|
||
v.y = #v[1]
|
||
end
|
||
|
||
local drawImage = function(im, x, y)
|
||
local cx, cy = termgetCursorPos()
|
||
termsetBackgroundColor( tocolors[initGrid.voidcol] )
|
||
termsetTextColor( tocolors[initGrid.voidcol] )
|
||
for iy = 1, #im[1] do
|
||
for ix = 1, #im[1][iy] do
|
||
termsetCursorPos(x+(ix-1),y+(iy-1))
|
||
if not (im[2][iy]:sub(ix,ix) == " " and im[3][iy]:sub(ix,ix) == " ") then
|
||
termblit(
|
||
im[1][iy]:sub(ix,ix),
|
||
im[2][iy]:sub(ix,ix),
|
||
im[3][iy]:sub(ix,ix)
|
||
)
|
||
end
|
||
end
|
||
end
|
||
termsetCursorPos(cx,cy)
|
||
end
|
||
|
||
local deadGuys = {}
|
||
local trail = {}
|
||
local lastTrails = {}
|
||
isPuttingDown = false
|
||
|
||
local putTrailXY = function(x, y, p)
|
||
trail[y] = trail[y] or {}
|
||
trail[y][x] = {
|
||
player = p,
|
||
age = 0
|
||
}
|
||
end
|
||
|
||
local putTrail = function(p)
|
||
putTrailXY(p.x, p.y, p.num)
|
||
end
|
||
|
||
local getTrail = function(x, y)
|
||
if trail[y] then
|
||
if trail[y][x] then
|
||
return player[trail[y][x].player].char, player[trail[y][x].player].color, trail[y][x].age
|
||
end
|
||
end
|
||
return false
|
||
end
|
||
|
||
local ageTrails = function()
|
||
for y,l in pairs(trail) do
|
||
for x,v in pairs(l) do
|
||
trail[y][x].age = trail[y][x].age + 1
|
||
end
|
||
end
|
||
end
|
||
|
||
local control, revControl = {
|
||
up = keys.up,
|
||
down = keys.down,
|
||
left = keys.left,
|
||
right = keys.right,
|
||
lookUp = keys.w,
|
||
lookDown = keys.s,
|
||
lookLeft = keys.a,
|
||
lookRight = keys.d,
|
||
release = keys.space
|
||
}, {}
|
||
for k,v in pairs(control) do
|
||
revControl[v] = k
|
||
end
|
||
|
||
-- keeps track of where you are
|
||
local gamemode = ""
|
||
|
||
|
||
local gridFore, gridBack
|
||
if squareGrid then
|
||
gridFore = {
|
||
"+-------",
|
||
"| ",
|
||
"| ",
|
||
"| ",
|
||
"| "
|
||
}
|
||
gridBack = {
|
||
"+------------",
|
||
"| ",
|
||
"| ",
|
||
"| ",
|
||
"| ",
|
||
"| ",
|
||
"| ",
|
||
"| "
|
||
}
|
||
else
|
||
gridFore = {
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
"/__________"
|
||
}
|
||
gridBack = {
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
" / ",
|
||
"/_______________"
|
||
}
|
||
end
|
||
|
||
local dirArrow = {
|
||
[-1] = "^",
|
||
[0] = ">",
|
||
[1] = "V",
|
||
[2] = "<"
|
||
}
|
||
|
||
local doesIntersectBorder = function(x, y)
|
||
return x == grid.x1 or x == grid.x2 or y == grid.y1 or y == grid.y2
|
||
end
|
||
|
||
--draws grid and background at scroll 'x' and 'y', along with trails and players
|
||
local drawGrid = function(x, y, onlyDrawGrid, useSetVisible)
|
||
if useSetVisible then
|
||
tsv(false)
|
||
end
|
||
x, y = mathfloor(x + 0.5), mathfloor(y + 0.5)
|
||
local bg = {{},{},{}}
|
||
local foreX, foreY
|
||
local backX, backY
|
||
local adjX, adjY
|
||
local trailChar, trailColor, trailAge, isPlayer
|
||
for sy = 1, scr_y do
|
||
bg[1][sy] = ""
|
||
bg[2][sy] = ""
|
||
bg[3][sy] = ""
|
||
for sx = 1, scr_x do
|
||
adjX = (sx + x)
|
||
adjY = (sy + y)
|
||
foreX = 1 + (sx + x) % #gridFore[1]
|
||
foreY = 1 + (sy + y) % #gridFore
|
||
backX = 1 + mathfloor(sx + (x / 2)) % #gridBack[1]
|
||
backY = 1 + mathfloor(sy + (y / 2)) % #gridBack
|
||
trailChar, trailColor, trailAge = getTrail(adjX, adjY)
|
||
isPlayer = false
|
||
if not onlyDrawGrid then
|
||
for i = 1, #player do
|
||
if player[i].x == adjX and player[i].y == adjY then
|
||
isPlayer = i
|
||
break
|
||
end
|
||
end
|
||
end
|
||
if isPlayer and (not onlyDrawGrid) and (not doesIntersectBorder(adjX, adjY)) then
|
||
bg[1][sy] = bg[1][sy] .. dirArrow[player[isPlayer].direction]
|
||
bg[2][sy] = bg[2][sy] .. toblit[player[isPlayer].color[1]]
|
||
bg[3][sy] = bg[3][sy] .. grid.voidcol
|
||
else
|
||
if (not onlyDrawGrid) and trailChar and trailColor then
|
||
trailColor = trailColor[1 + ((trailAge - 1) % #trailColor)]
|
||
bg[1][sy] = bg[1][sy] .. trailChar
|
||
bg[2][sy] = bg[2][sy] .. toblit[trailColor]
|
||
bg[3][sy] = bg[3][sy] .. grid.voidcol
|
||
else
|
||
if (not onlyDrawGrid) and (adjX < grid.x1 or adjX > grid.x2 or adjY < grid.y1 or adjY > grid.y2) then
|
||
bg[1][sy] = bg[1][sy] .. " "
|
||
bg[2][sy] = bg[2][sy] .. grid.voidcol
|
||
bg[3][sy] = bg[3][sy] .. grid.voidcol
|
||
elseif (not onlyDrawGrid) and doesIntersectBorder(adjX, adjY) then
|
||
bg[1][sy] = bg[1][sy] .. grid.border
|
||
bg[2][sy] = bg[2][sy] .. grid.voidcol
|
||
bg[3][sy] = bg[3][sy] .. grid.edgecol
|
||
else
|
||
if gridFore[foreY]:sub(foreX,foreX) ~= " " then
|
||
bg[1][sy] = bg[1][sy] .. gridFore[foreY]:sub(foreX,foreX)
|
||
bg[2][sy] = bg[2][sy] .. grid.forecol
|
||
bg[3][sy] = bg[3][sy] .. grid.voidcol
|
||
elseif gridBack[backY]:sub(backX,backX) ~= " " then
|
||
bg[1][sy] = bg[1][sy] .. gridBack[backY]:sub(backX,backX)
|
||
bg[2][sy] = bg[2][sy] .. grid.backcol
|
||
bg[3][sy] = bg[3][sy] .. grid.voidcol
|
||
else
|
||
bg[1][sy] = bg[1][sy] .. " "
|
||
bg[2][sy] = bg[2][sy] .. grid.voidcol
|
||
bg[3][sy] = bg[3][sy] .. grid.voidcol
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
for sy = 1, scr_y do
|
||
termsetCursorPos(1,sy)
|
||
termblit(
|
||
bg[1][sy],
|
||
bg[2][sy],
|
||
bg[3][sy]
|
||
)
|
||
end
|
||
if doDrawPlayerNames and (not onlyDrawGrid) then
|
||
for i = 1, #player do
|
||
termsetTextColor(player[i].color[1])
|
||
adjX = player[i].x - (scrollX + scrollAdjX) - mathfloor(#player[i].name / 2)
|
||
adjY = player[i].y - (scrollY + scrollAdjY) - 2
|
||
for cx = adjX, adjX + #player[i].name do
|
||
if doesIntersectBorder(adjX + (scrollX + scrollAdjX), adjY + (scrollY + scrollAdjY)) then
|
||
termsetBackgroundColor(tocolors[grid.edgecol])
|
||
else
|
||
termsetBackgroundColor(tocolors[grid.voidcol])
|
||
end
|
||
termsetCursorPos(cx, adjY)
|
||
termwrite(player[i].name:sub(cx-adjX+1, cx-adjX+1))
|
||
end
|
||
end
|
||
end
|
||
if useSetVisible then
|
||
tsv(true)
|
||
end
|
||
end
|
||
|
||
local render = function(useSetVisible)
|
||
local p = player[you]
|
||
drawGrid(scrollX + scrollAdjX, scrollY + scrollAdjY, false, useSetVisible)
|
||
termsetCursorPos(1,1)
|
||
termsetTextColor(player[you].color[1])
|
||
termsetBackgroundColor(tocolors[grid.voidcol])
|
||
term.write("P" .. you)
|
||
end
|
||
|
||
local pleaseWait = function()
|
||
local periods = 1
|
||
local maxPeriods = 5
|
||
termsetBackgroundColor(colors.black)
|
||
termsetTextColor(colors.gray)
|
||
termclear()
|
||
|
||
local tID = os.startTimer(0.2)
|
||
local evt
|
||
local txt = "Waiting for game"
|
||
|
||
while true do
|
||
termsetCursorPos(mathfloor(scr_x / 2 - (#txt + maxPeriods) / 2), scr_y - 2)
|
||
termwrite(txt .. ("."):rep(periods))
|
||
evt = {os.pullEvent()}
|
||
if evt[1] == "timer" and evt[2] == tID then
|
||
tID = os.startTimer(0.5)
|
||
periods = (periods % maxPeriods) + 1
|
||
term.clearLine()
|
||
elseif evt[1] == "key" and evt[2] == keys.q then
|
||
return
|
||
end
|
||
end
|
||
end
|
||
|
||
local startCountdown = function()
|
||
local cName = "PLAYER " .. you
|
||
local col = colors.white
|
||
for k,v in pairs(colors) do
|
||
if player[you].color[1] == v then
|
||
cName = k:upper()
|
||
col = v
|
||
break
|
||
end
|
||
end
|
||
local cMessage = "You are "
|
||
scrollX = player[you].x - mathfloor(scr_x / 2)
|
||
scrollY = player[you].y - mathfloor(scr_y / 2)
|
||
for i = 3, 1, -1 do
|
||
render(true)
|
||
termsetTextColor(colors.white)
|
||
for x = 1, #cMessage+1 do
|
||
termsetCursorPos(-1 + x + mathfloor(scr_x / 2 - (#cMessage + #cName) / 2), mathfloor(scr_y / 2) + 2)
|
||
if cMessage:sub(x,x) ~= " " and x <= #cMessage then
|
||
termwrite(cMessage:sub(x,x))
|
||
end
|
||
end
|
||
termsetTextColor(col)
|
||
termwrite(cName)
|
||
termsetTextColor(colors.white)
|
||
termsetCursorPos(mathfloor(scr_x / 2 - 2), mathfloor(scr_y / 2) + 4)
|
||
termwrite(i .. "...")
|
||
sleep(1)
|
||
end
|
||
end
|
||
|
||
local makeMenu = function(x, y, options, doAnimate)
|
||
local cpos = 1
|
||
local cursor = "> "
|
||
local gsX, gsY = 0, 0
|
||
local step = 0
|
||
local lastPos = cpos
|
||
if not doAnimate then
|
||
drawImage(images.logo, mathceil(scr_x / 2 - images.logo.x / 2), 2)
|
||
end
|
||
local rend = function()
|
||
if doAnimate then
|
||
drawImage(images.logo, mathceil(scr_x / 2 - images.logo.x / 2), 2)
|
||
end
|
||
for i = 1, #options do
|
||
if i == cpos then
|
||
termsetCursorPos(x, y + (i - 1))
|
||
termsetTextColor(colors.white)
|
||
termwrite(cursor .. options[i])
|
||
else
|
||
if i == lastPos then
|
||
termsetCursorPos(x, y + (i - 1))
|
||
termwrite((" "):rep(#cursor))
|
||
lastPos = nil
|
||
else
|
||
termsetCursorPos(x + #cursor, y + (i - 1))
|
||
end
|
||
termsetTextColor(colors.gray)
|
||
termwrite(options[i])
|
||
end
|
||
end
|
||
end
|
||
local gstID, evt = mathrandom(1,65535)
|
||
if doAnimate then
|
||
os.queueEvent("timer", gstID)
|
||
end
|
||
while true do
|
||
rend()
|
||
evt = {os.pullEvent()}
|
||
if evt[1] == "key" then
|
||
if evt[2] == keys.up then
|
||
lastPos = cpos
|
||
cpos = (cpos - 2) % #options + 1
|
||
elseif evt[2] == keys.down then
|
||
lastPos = cpos
|
||
cpos = (cpos % #options) + 1
|
||
elseif evt[2] == keys.home then
|
||
lastPos = cpos
|
||
cpos = 1
|
||
elseif evt[2] == keys["end"] then
|
||
lastPos = cpos
|
||
cpos = #options
|
||
elseif evt[2] == keys.enter then
|
||
return cpos
|
||
end
|
||
elseif evt[1] == "timer" and evt[2] == gstID then
|
||
gstID = os.startTimer(gameDelayInit)
|
||
drawGrid(gsX, gsY, true, true)
|
||
step = step + 1
|
||
if mathceil(step / 100) % 2 == 1 then
|
||
gsX = gsX + 1
|
||
else
|
||
gsY = gsY - 1
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local titleScreen = function()
|
||
termclear()
|
||
local choice = makeMenu(2, scr_y - 4, {
|
||
"Start Game",
|
||
"How to Play",
|
||
"Grid Demo",
|
||
"Exit"
|
||
}, true)
|
||
if choice == 1 then
|
||
return "start"
|
||
elseif choice == 2 then
|
||
return "help"
|
||
elseif choice == 3 then
|
||
return "demo"
|
||
elseif choice == 4 then
|
||
return "exit"
|
||
end
|
||
end
|
||
|
||
local cleanExit = function()
|
||
termsetBackgroundColor(colors.black)
|
||
termsetTextColor(colors.white)
|
||
termclear()
|
||
termsetCursorPos(1,1)
|
||
print("Thanks for playing!")
|
||
end
|
||
|
||
local getInput = function()
|
||
local evt
|
||
while true do
|
||
evt = {os.pullEvent()}
|
||
if lockInput then
|
||
keysDown = {}
|
||
else
|
||
if evt[1] == "key" then
|
||
if (not keysDown[evt[2]]) and (
|
||
evt[2] == control.up or
|
||
evt[2] == control.down or
|
||
evt[2] == control.left or
|
||
evt[2] == control.right
|
||
) then
|
||
lastDirectionPressed = revControl[evt[2]]
|
||
end
|
||
keysDown[evt[2]] = true
|
||
elseif evt[1] == "key_up" then
|
||
keysDown[evt[2]] = false
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local scrollToPosition = function(x, y)
|
||
for i = 1, 16 do
|
||
scrollX = (scrollX + x - (scr_x/2)) / 2
|
||
scrollY = (scrollY + y - (scr_y/2)) / 2
|
||
render(true)
|
||
sleep(0.05)
|
||
end
|
||
end
|
||
|
||
local gridDemo = function()
|
||
keysDown = {}
|
||
while true do
|
||
if keysDown[keys.left] then
|
||
scrollX = scrollX - 1
|
||
end
|
||
if keysDown[keys.right] then
|
||
scrollX = scrollX + 1
|
||
end
|
||
if keysDown[keys.up] then
|
||
scrollY = scrollY - 1
|
||
end
|
||
if keysDown[keys.down] then
|
||
scrollY = scrollY + 1
|
||
end
|
||
if keysDown[keys.q] then
|
||
return "end"
|
||
end
|
||
drawGrid(scrollX, scrollY, false, true)
|
||
ageTrails()
|
||
sleep(gameDelay)
|
||
end
|
||
end
|
||
|
||
local sendInfo = function(gameID)
|
||
transmit(port, {
|
||
player = isHost and player or nil,
|
||
name = player[you].name,
|
||
putTrail = isPuttingDown,
|
||
gameID = gameID,
|
||
keysDown = isHost and nil or keysDown,
|
||
trail = isHost and lastTrails or nil,
|
||
deadGuys = isHost and deadGuys or nil,
|
||
lastDir = lastDirectionPressed
|
||
})
|
||
end
|
||
|
||
local waitForKey = function(time)
|
||
sleep(time or 0.5)
|
||
os.pullEvent("key")
|
||
end
|
||
|
||
local imageAnim = function(image)
|
||
while true do
|
||
drawImage(image, mathceil(scr_x / 2 - image.x / 2), mathfloor(scr_y / 2 - image.y / 2))
|
||
sleep(0.5)
|
||
render(true)
|
||
sleep(0.5)
|
||
end
|
||
end
|
||
|
||
local deadAnimation = function(doSend)
|
||
for k,v in pairs(deadGuys) do
|
||
player[k].char = "X"
|
||
lockInput = true
|
||
end
|
||
if doSend then
|
||
sendInfo(gamename)
|
||
end
|
||
if deadGuys[you] or deadGuys[nou] then
|
||
termsetTextColor(colors.white)
|
||
if deadGuys[you] and deadGuys[nou] then
|
||
scrollToPosition(player[nou].x, player[nou].y)
|
||
scrollToPosition(player[you].x, player[you].y)
|
||
parallel.waitForAny(function() imageAnim(images.tie) end, waitForKey)
|
||
return "end"
|
||
else
|
||
if deadGuys[you] then
|
||
scrollX, scrollY = player[nou].x - scr_x / 2, player[nou].y - scr_y / 2
|
||
scrollToPosition(player[you].x, player[you].y)
|
||
parallel.waitForAny(function() imageAnim(images.lose) end, waitForKey)
|
||
return "end"
|
||
elseif deadGuys[nou] then
|
||
scrollToPosition(player[nou].x, player[nou].y)
|
||
parallel.waitForAny(function() imageAnim(images.win) end, waitForKey)
|
||
return "end"
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local moveTick = function(doSend)
|
||
local p
|
||
for i = 1, #player do
|
||
p = player[i]
|
||
if not p.dead then
|
||
if isHost then
|
||
p.x = p.x + mathfloor(mathcos(mathrad(p.direction * 90)))
|
||
p.y = p.y + mathfloor(mathsin(mathrad(p.direction * 90)))
|
||
if doesIntersectBorder(p.x, p.y) or getTrail(p.x, p.y) then
|
||
p.dead = true
|
||
deadGuys[i] = true
|
||
elseif p.putTrail then
|
||
putTrail(p)
|
||
lastTrails[#lastTrails+1] = {p.x, p.y, p.num}
|
||
if #lastTrails > #player then
|
||
tableremove(lastTrails, 1)
|
||
end
|
||
end
|
||
end
|
||
for a = 1, #player do
|
||
if (a ~= i) and (player[a].x == p.x and player[a].y == p.y) then
|
||
p.dead = true
|
||
deadGuys[i] = true
|
||
if (p.direction + 2) % 4 == player[a].direction % 4 then
|
||
player[a].dead = true
|
||
deadGuys[a] = true
|
||
end
|
||
break
|
||
end
|
||
end
|
||
end
|
||
end
|
||
return deadAnimation(doSend)
|
||
end
|
||
|
||
local setDirection = function(p, checkDir, lastDir)
|
||
if (lastDir == control.left) and (checkDir or p.direction) ~= 0 then
|
||
p.direction = 2
|
||
elseif (lastDir == control.right) and (checkDir or p.direction) ~= 2 then
|
||
p.direction = 0
|
||
elseif (lastDir == control.up) and (checkDir or p.direction) ~= 1 then
|
||
p.direction = -1
|
||
elseif (lastDir == control.down) and (checkDir or p.direction) ~= -1 then
|
||
p.direction = 1
|
||
end
|
||
end
|
||
|
||
local game = function()
|
||
local outcome
|
||
local p, np
|
||
if argumentName then
|
||
player[you].name = argumentName
|
||
end
|
||
while true do
|
||
if isHost then
|
||
sleep(gameDelay)
|
||
else
|
||
os.pullEvent("move_tick")
|
||
end
|
||
p = player[you]
|
||
np = player[nou]
|
||
|
||
if isHost then
|
||
setDirection(p, nil, control[lastDirectionPressed])
|
||
setDirection(np, nil, control[netLastDirectionPressed])
|
||
p.putTrail = not keysDown[control.release]
|
||
else
|
||
setDirection(p, nil, control[lastDirectionPressed])
|
||
isPuttingDown = not keysDown[control.release]
|
||
end
|
||
|
||
if keysDown[control.lookLeft] then
|
||
scrollAdjX = scrollAdjX - 2
|
||
end
|
||
if keysDown[control.lookRight] then
|
||
scrollAdjX = scrollAdjX + 2
|
||
end
|
||
if keysDown[control.lookUp] then
|
||
scrollAdjY = scrollAdjY - 1.5
|
||
end
|
||
if keysDown[control.lookDown] then
|
||
scrollAdjY = scrollAdjY + 1.5
|
||
end
|
||
|
||
scrollAdjX = scrollAdjX * 0.8
|
||
scrollAdjY = scrollAdjY * 0.8
|
||
|
||
if isHost then
|
||
outcome = moveTick(true)
|
||
else
|
||
outcome = deadAnimation(true)
|
||
end
|
||
ageTrails()
|
||
if outcome == "end" then
|
||
return
|
||
else
|
||
scrollX = p.x - mathfloor(scr_x / 2)
|
||
scrollY = p.y - mathfloor(scr_y / 2)
|
||
render(true)
|
||
end
|
||
end
|
||
end
|
||
|
||
local networking = function()
|
||
local evt, side, channel, repchannel, msg, distance
|
||
while true do
|
||
if useSkynet then
|
||
evt, channel, msg = os.pullEvent("skynet_message")
|
||
else
|
||
evt, side, channel, repchannel, msg, distance = os.pullEvent("modem_message")
|
||
end
|
||
if channel == port and type(msg) == "table" then
|
||
if type(msg.gameID) == "string" then
|
||
if waitingForGame and (type(msg.new) == "number") then
|
||
if msg.new < os.time() then
|
||
isHost = false
|
||
gamename = msg.gameID
|
||
gameDelay = tonumber(msg.gameDelay) or gameDelayInit
|
||
grid = msg.grid or deepCopy(initGrid)
|
||
player = msg.player or player
|
||
else
|
||
isHost = true
|
||
you, nou = nou, you
|
||
end
|
||
you, nou = nou, you
|
||
transmit(port, {
|
||
player = player,
|
||
gameID = gamename,
|
||
new = isHost and (-math.huge) or (math.huge),
|
||
grid = initGrid
|
||
})
|
||
waitingForGame = false
|
||
netKeysDown = {}
|
||
os.queueEvent("new_game", gameID)
|
||
return gameID
|
||
|
||
elseif msg.gameID == gamename then
|
||
if not isHost then
|
||
if type(msg.player) == "table" then
|
||
player[nou].name = msg.name or player[nou].name
|
||
player = msg.player
|
||
if msg.trail then
|
||
for i = 1, #msg.trail do
|
||
putTrailXY(unpack(msg.trail[i]))
|
||
end
|
||
end
|
||
deadGuys = msg.deadGuys
|
||
os.queueEvent("move_tick")
|
||
end
|
||
elseif type(msg.keysDown) == "table" then
|
||
netKeysDown = msg.keysDown
|
||
netLastDirectionPressed = msg.lastDir
|
||
player[nou].putTrail = msg.putTrail
|
||
player[nou].name = msg.name or player[nou].name
|
||
end
|
||
end
|
||
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
local helpScreen = function()
|
||
termsetBackgroundColor(colors.black)
|
||
termsetTextColor(colors.white)
|
||
termclear()
|
||
termsetCursorPos(1,2)
|
||
print([[
|
||
Move with arrow keys.
|
||
Pan the camera with WASD.
|
||
Hold SPACE to create gaps.
|
||
|
||
That's basically it.
|
||
Press any key to go back.
|
||
]])
|
||
waitForKey(0.25)
|
||
end
|
||
|
||
local startGame = function()
|
||
-- reset all info between games
|
||
trail = {}
|
||
deadGuys = {}
|
||
lastDirectionPressed = nil
|
||
netLastDirectionPressed = nil
|
||
gameDelay = gameDelayInit
|
||
grid = deepCopy(initGrid)
|
||
player = resetPlayers()
|
||
you, nou = 1, 2
|
||
gamename = ""
|
||
for i = 1, 32 do
|
||
gamename = gamename .. string.char(mathrandom(1,126))
|
||
end
|
||
|
||
waitingForGame = true
|
||
transmit(port, {
|
||
player = player,
|
||
gameID = gamename,
|
||
new = os.time(),
|
||
gameDelay = gameDelayInit,
|
||
grid = initGrid
|
||
})
|
||
rVal = parallel.waitForAny( pleaseWait, networking )
|
||
-- give time for skynet
|
||
sleep(0.1)
|
||
if rVal == 2 then
|
||
startCountdown()
|
||
parallel.waitForAny( getInput, game, networking )
|
||
end
|
||
end
|
||
|
||
local decision
|
||
|
||
local main = function()
|
||
local rVal
|
||
while true do
|
||
decision = titleScreen()
|
||
lockInput = false
|
||
if decision == "start" then
|
||
startGame()
|
||
elseif decision == "help" then
|
||
helpScreen()
|
||
elseif decision == "demo" then
|
||
parallel.waitForAny( getInput, gridDemo )
|
||
elseif decision == "exit" then
|
||
return cleanExit()
|
||
end
|
||
end
|
||
end
|
||
|
||
if useOnce then
|
||
if useSkynet then
|
||
parallel.waitForAny(startGame, skynet.listen)
|
||
skynet.socket.close()
|
||
else
|
||
startGame()
|
||
end
|
||
else
|
||
if useSkynet then
|
||
parallel.waitForAny(main, skynet.listen)
|
||
skynet.socket.close()
|
||
else
|
||
main()
|
||
end
|
||
end
|