1
0
mirror of https://github.com/LDDestroier/CC/ synced 2025-02-23 06:20:02 +00:00

Added options, enabled name display, etc.

In the new Options menu, you can:
1. change your grid
2. change your name (13 character limit)
3. demo the grid scrolling

A big change is that you now need fuel to release your trail. You start with 10, and it slowly regenerates whenever you aren't holding down the button to release. This is to prevent stalling.
This commit is contained in:
LDDestroier 2019-02-23 00:37:51 -05:00 committed by GitHub
parent 234cb77147
commit f6aabddae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

467
tron.lua
View File

@ -7,7 +7,6 @@
local port = 701 local port = 701
local kioskMode = false local kioskMode = false
local debugShowKeys = false
local useLegacyMouseControl = false local useLegacyMouseControl = false
local scr_x, scr_y = term.getSize() local scr_x, scr_y = term.getSize()
@ -16,8 +15,14 @@ local isColor = term.isColor()
-- lower value = faster game. I'd reccommend 0.1 for SMP play. -- lower value = faster game. I'd reccommend 0.1 for SMP play.
local gameDelayInit = 0.1 local gameDelayInit = 0.1
local doDrawPlayerNames = false -- draws the names of players onscreen
local doDrawPlayerNames = true
-- if doDrawPlayerNames, also draws your own name
local doRenderOwnName = false
-- whether or not to use term.current().setVisible, which speeds things up at the cost of multishell
local useSetVisible = false local useSetVisible = false
-- determines which grid is used
local gridID = 3
local initGrid = { local initGrid = {
x1 = -100, x1 = -100,
@ -34,7 +39,7 @@ local resetPlayers = function()
return { return {
[1] = { [1] = {
num = 1, num = 1,
x = -2, x = -3,
y = -5, y = -5,
direction = -1, direction = -1,
char = "@", char = "@",
@ -50,12 +55,16 @@ local resetPlayers = function()
colors.cyan colors.cyan
}, },
dead = false, dead = false,
trailLevel = 10,
trailMax = 10,
trailRegen = 0.1,
putTrail = true, putTrail = true,
name = "BLU" name = "BLU",
initName = "BLU"
}, },
[2] = { [2] = {
num = 2, num = 2,
x = 2, x = 3,
y = -5, y = -5,
direction = -1, direction = -1,
char = "@", char = "@",
@ -71,8 +80,12 @@ local resetPlayers = function()
colors.orange colors.orange
}, },
dead = false, dead = false,
trailLevel = 10,
trailMax = 10,
trailRegen = 0.1,
putTrail = true, putTrail = true,
name = "RED" name = "RED",
initName = "RED"
} }
} }
end end
@ -83,6 +96,10 @@ local argumentName = tArg[3] or tArg[2] or tArg[1] or nil
local skynetPath = "skynet" local skynetPath = "skynet"
local skynetURL = "https://raw.githubusercontent.com/osmarks/skynet/master/client.lua" local skynetURL = "https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"
if argumentName then
argumentName = argumentName:sub(1, 13) -- gotta enforce that limit
end
local modem, skynet local modem, skynet
if useSkynet then if useSkynet then
if fs.exists(skynetPath) then if fs.exists(skynetPath) then
@ -123,7 +140,6 @@ end
local gamename = "" local gamename = ""
local isHost local isHost
local squareGrid = true
local waitingForGame = true local waitingForGame = true
local toblit = { local toblit = {
@ -232,6 +248,8 @@ grid = copyTable(initGrid)
local you, nou = 1, 2 local you, nou = 1, 2
local keysDown, netKeysDown = {}, {} local keysDown, netKeysDown = {}, {}
local miceDown = {}
local lastDirectionPressed, netLastDirectionPressed local lastDirectionPressed, netLastDirectionPressed
-- the scrolling of the screen -- the scrolling of the screen
@ -468,43 +486,99 @@ for k,v in pairs(control) do
end end
local gridFore, gridBack local gridFore, gridBack
if squareGrid then local gridList = {
gridFore = { [1] = {
"+-------", {
"| ", "+-------",
"| ", "| ",
"| ", "| ",
"| " "| ",
"| "
},
{
"+------------",
"| ",
"| ",
"| ",
"| ",
"| ",
"| ",
"| "
}
},
[2] = {
{
" / ",
" / ",
" / ",
" / ",
"/__________"
},
{
" / ",
" / ",
" / ",
" / ",
" / ",
" / ",
" / ",
"/_______________"
}
},
[3] = {
{
"+- -+------",
"| | ",
" | ",
". | ",
"+------+- -",
"| | ",
"| ",
"| . ",
},
{
"+- -+--------",
"| | ",
" | ",
" | ",
" | ",
"| | ",
"+--------+- -",
"| | ",
"| ",
"| ",
"| ",
"| | ",
}
},
[4] = {
{
" /\\ ",
" / \\ ",
" / \\ ",
"/ \\",
"\\ /",
" \\ / ",
" \\ / ",
" \\/ ",
},
{
" /\\ ",
" / \\ ",
" / \\ ",
" / \\ ",
" / \\ ",
"/ \\",
"\\ /",
" \\ / ",
" \\ / ",
" \\ / ",
" \\ / ",
" \\/ ",
}
} }
gridBack = { }
"+------------", gridFore, gridBack = table.unpack(gridList[gridID])
"| ",
"| ",
"| ",
"| ",
"| ",
"| ",
"| "
}
else
gridFore = {
" / ",
" / ",
" / ",
" / ",
"/__________"
}
gridBack = {
" / ",
" / ",
" / ",
" / ",
" / ",
" / ",
" / ",
"/_______________"
}
end
local dirArrow = { local dirArrow = {
[-1] = "^", [-1] = "^",
@ -513,8 +587,15 @@ local dirArrow = {
[2] = "<" [2] = "<"
} }
local cwrite = function(text, y, xdiff, wordPosCheck)
wordPosCheck = wordPosCheck or #text
termsetCursorPos(mathfloor(scr_x / 2 - (#text + (xdiff or 0)) / 2), y or (scr_y - 2))
term.write(text)
return (scr_x / 2) - (#text / 2) + wordPosCheck
end
local doesIntersectBorder = function(x, y) local doesIntersectBorder = function(x, y)
return x == grid.x1 or x == grid.x2 or y == grid.y1 or y == grid.y2 return mathfloor(x) == grid.x1 or mathfloor(x) == grid.x2 or mathfloor(y) == grid.y1 or mathfloor(y) == grid.y2
end end
--draws grid and background at scroll 'x' and 'y', along with trails and players --draws grid and background at scroll 'x' and 'y', along with trails and players
@ -608,17 +689,19 @@ local drawGrid = function(x, y, onlyDrawGrid, useSetVisible)
end end
if doDrawPlayerNames and (not onlyDrawGrid) then if doDrawPlayerNames and (not onlyDrawGrid) then
for i = 1, #player do for i = 1, #player do
termsetTextColor(player[i].color[1]) if doRenderOwnName or (i ~= you) then
adjX = player[i].x - (scrollX + scrollAdjX) - mathfloor(#player[i].name / 2) termsetTextColor(player[i].color[1])
adjY = player[i].y - (scrollY + scrollAdjY) - 2 adjX = mathfloor(player[i].x - (scrollX + scrollAdjX) - (#player[i].name / 2) + 1)
for cx = adjX, adjX + #player[i].name do adjY = mathfloor(player[i].y - (scrollY + scrollAdjY) - 1.5)
if doesIntersectBorder(adjX + (scrollX + scrollAdjX), adjY + (scrollY + scrollAdjY)) then for cx = adjX, adjX + #player[i].name do
termsetBackgroundColor(tocolors[grid.edgecol]) if doesIntersectBorder(adjX + (scrollX + scrollAdjX), adjY + (scrollY + scrollAdjY)) then
else termsetBackgroundColor(tocolors[grid.edgecol])
termsetBackgroundColor(tocolors[grid.voidcol]) else
termsetBackgroundColor(tocolors[grid.voidcol])
end
termsetCursorPos(cx, adjY)
termwrite(player[i].name:sub(cx-adjX+1, cx-adjX+1))
end end
termsetCursorPos(cx, adjY)
termwrite(player[i].name:sub(cx-adjX+1, cx-adjX+1))
end end
end end
end end
@ -635,22 +718,27 @@ local render = function(useSetVisible, netTime)
termsetBackgroundColor(tocolors[grid.voidcol]) termsetBackgroundColor(tocolors[grid.voidcol])
term.write("P" .. you) term.write("P" .. you)
term.setTextColor(colors.white) term.setTextColor(colors.white)
for x = 0, p.trailMax - 1 do
if not (x - p.trailLevel >= -0.4) then
if (x - p.trailLevel) > -0.7 then
term.setTextColor(colors.gray)
term.write("@")
elseif (x - p.trailLevel) > -1 then
term.setTextColor(colors.lightGray)
term.write("@")
else
term.setTextColor(colors.white)
term.write("@")
end
end
end
term.setCursorPos(1,2)
if netTime and useSkynet then if netTime and useSkynet then
ping = (os.epoch() - netTime) / round(72, 2) ping = (os.epoch() - netTime) / round(72, 2)
term.write(" " .. tostring(ping) .. " ms") term.write(" " .. tostring(ping) .. " ms")
end end
if debugShowKeys then term.setTextColor(colors.white)
term.setCursorPos(1,2)
term.write("dir = " .. player[you].direction .. " ")
local y = 3
for k,v in pairs(keysDown) do
if v then
term.setCursorPos(1,y)
term.write(k.." = "..tostring(v).." ")
y = y + 1
end
end
end
end end
local pleaseWait = function() local pleaseWait = function()
@ -665,8 +753,9 @@ local pleaseWait = function()
local txt = "Waiting for game" local txt = "Waiting for game"
while true do while true do
termsetCursorPos(mathfloor(scr_x / 2 - (#txt + maxPeriods) / 2), scr_y - 2) cwrite("(Press 'Q' to cancel)", 2)
termwrite(txt .. ("."):rep(periods)) cwrite(txt, scr_y - 2, maxPeriods)
termwrite(("."):rep(periods))
evt = {os.pullEvent()} evt = {os.pullEvent()}
if evt[1] == "timer" and evt[2] == tID then if evt[1] == "timer" and evt[2] == tID then
tID = os.startTimer(0.5) tID = os.startTimer(0.5)
@ -701,7 +790,7 @@ local startCountdown = function()
end end
end end
termsetTextColor(col) termsetTextColor(col)
termwrite(cName) termwrite(player[you].name)
termsetTextColor(colors.white) termsetTextColor(colors.white)
termsetCursorPos(mathfloor(scr_x / 2 - 2), mathfloor(scr_y / 2) + 4) termsetCursorPos(mathfloor(scr_x / 2 - 2), mathfloor(scr_y / 2) + 4)
termwrite(i .. "...") termwrite(i .. "...")
@ -709,11 +798,11 @@ local startCountdown = function()
end end
end end
local makeMenu = function(x, y, options, doAnimate) local makeMenu = function(x, y, options, doAnimate, scrollInfo, _cpos)
local cpos = 1 local cpos = _cpos or 1
local cursor = "> " local cursor = "> "
local gsX, gsY = 0, 0 local gsX, gsY = (scrollInfo or {})[2] or 0, (scrollInfo or {})[3] or 0
local step = 0 local step = (scrollInfo or {})[1] or 0
local lastPos = cpos local lastPos = cpos
if not doAnimate then if not doAnimate then
drawImage(images.logo, mathceil(scr_x / 2 - images.logo.x / 2), 2) drawImage(images.logo, mathceil(scr_x / 2 - images.logo.x / 2), 2)
@ -744,9 +833,8 @@ local makeMenu = function(x, y, options, doAnimate)
if doAnimate then if doAnimate then
os.queueEvent("timer", gstID) os.queueEvent("timer", gstID)
end end
rend()
while true do while true do
rend()
tsv(true)
evt = {os.pullEvent()} evt = {os.pullEvent()}
tsv(false) tsv(false)
if evt[1] == "key" then if evt[1] == "key" then
@ -764,15 +852,16 @@ local makeMenu = function(x, y, options, doAnimate)
cpos = #options cpos = #options
elseif evt[2] == keys.enter then elseif evt[2] == keys.enter then
tsv(true) tsv(true)
return cpos return cpos, {step, gsX, gsY}
end end
elseif evt[1] == "mouse_click" then elseif evt[1] == "mouse_click" then
if evt[4] >= y and evt[4] < y+#options then if evt[4] >= y and evt[4] < y+#options then
if cpos == evt[4] - (y - 1) then if cpos == evt[4] - (y - 1) then
tsv(true) tsv(true)
return cpos return cpos, {step, gsX, gsY}
else else
cpos = evt[4] - (y - 1) cpos = evt[4] - (y - 1)
rend()
end end
end end
elseif evt[1] == "timer" and evt[2] == gstID then elseif evt[1] == "timer" and evt[2] == gstID then
@ -784,13 +873,101 @@ local makeMenu = function(x, y, options, doAnimate)
else else
gsY = gsY - 1 gsY = gsY - 1
end end
rend()
end
if lastPos ~= cpos then
rend()
end
end
end
local nameChange = function(scrollInfo)
local gsX, gsY = (scrollInfo or {})[2] or 0, (scrollInfo or {})[3] or 0
local step = (scrollInfo or {})[1] or 0
local tID = os.startTimer(gameDelayInit)
local buff = {}
local cpos = 1
local maxSize = 13
local evt
-- this has no functional significance, I'm just messing around
local specialNames = {
["blu"] = colors.blue,
["red"] = colors.red,
["ldd"] = colors.orange,
["lddestroier"] = colors.orange,
["3d6"] = colors.lime,
["lyqyd"] = colors.red,
["squiddev"] = colors.cyan,
["oeed"] = colors.green,
["dog"] = colors.purple,
["nothy"] = colors.lightGray,
["kepler"] = colors.cyan,
["crazed"] = colors.lightBlue,
["ape"] = colors.brown
}
local prevName = argumentName or player[you].initName
for x = 1, #prevName do
buff[x] = prevName:sub(x, x)
cpos = cpos + 1
end
term.setCursorBlink(true)
local rend = function()
drawGrid(gsX, gsY, true)
term.setTextColor(colors.white)
cwrite("Enter your name.", scr_y - 5)
term.setTextColor(specialNames[table.concat(buff):lower()] or colors.white)
term.setCursorPos( cwrite(table.concat(buff), scr_y - 3, nil, cpos) - 1, scr_y - 3)
term.setTextColor(colors.white)
end
while true do
evt = {os.pullEvent()}
if evt[1] == "timer" and evt[2] == tID then
-- render the bg
tID = os.startTimer(gameDelayInit)
step = step + 1
if mathceil(step / 100) % 2 == 1 then
gsX = gsX + 1
else
gsY = gsY - 1
end
rend()
elseif evt[1] == "char" then
if #buff < maxSize then
table.insert(buff, cpos, evt[2])
cpos = cpos + 1
rend()
end
elseif evt[1] == "key" then
if evt[2] == keys.left then
cpos = math.max(1, cpos - 1)
elseif evt[2] == keys.right then
cpos = math.min(#buff + 1, cpos + 1)
elseif evt[2] == keys.home then
cpos = 1
elseif evt[2] == keys["end"] then
cpos = #buff
elseif evt[2] == keys.backspace then
if cpos > 1 then
table.remove(buff, cpos - 1)
cpos = cpos - 1
rend()
end
elseif evt[2] == keys.delete then
if buff[cpos] then
table.remove(buff, cpos)
rend()
end
elseif evt[2] == keys.enter then
term.setCursorBlink(false)
return table.concat(buff), {step, gsX, gsY}
end
end end
end end
end end
local titleScreen = function() local titleScreen = function()
termclear() termclear()
local menuOptions local menuOptions, options, choice, scrollInfo
if kioskMode then if kioskMode then
menuOptions = { menuOptions = {
"Start Game", "Start Game",
@ -800,19 +977,50 @@ local titleScreen = function()
menuOptions = { menuOptions = {
"Start Game", "Start Game",
"How to Play", "How to Play",
"Grid Demo", "Options...",
"Exit" "Exit"
} }
end end
local choice = makeMenu(2, scr_y - 4, menuOptions, true) options = {
if choice == 1 then "Grid Demo",
return "start" "Change Name",
elseif choice == 2 then "Change Grid",
return "help" "Back..."
elseif choice == 3 then }
return "demo" while true do
elseif choice == 4 then choice, scrollInfo = makeMenu(2, scr_y - #menuOptions, menuOptions, true, scrollInfo)
return "exit" if choice == 1 then
return "start"
elseif choice == 2 then
return "help"
elseif choice == 3 then
local _cpos
while true do
choice, scrollInfo = makeMenu(14, scr_y - #menuOptions, options, true, scrollInfo, _cpos)
_cpos = choice
if choice == 1 then
return "demo"
elseif choice == 2 then
local newName = nameChange(scrollInfo)
if #newName > 0 then
if newName:upper() == "BLU" or newName:upper() == "RED" then
argumentName = nil
else
argumentName = newName
end
else
argumentName = nil
end
elseif choice == 3 then
gridID = (gridID % #gridList) + 1
gridFore, gridBack = table.unpack(gridList[gridID])
elseif choice == 4 then
break
end
end
elseif choice == 4 then
return "exit"
end
end end
end end
@ -876,6 +1084,7 @@ local getInput = function()
evt = {os.pullEvent()} evt = {os.pullEvent()}
if lockInput then if lockInput then
keysDown = {} keysDown = {}
miceDown = {}
else else
if evt[1] == "key" then if evt[1] == "key" then
if (not keysDown[evt[2]]) and ( if (not keysDown[evt[2]]) and (
@ -893,11 +1102,15 @@ local getInput = function()
if evt[1] == "mouse_drag" then if evt[1] == "mouse_drag" then
keysDown[mkey] = false keysDown[mkey] = false
end end
miceDown[evt[2]] = {evt[3], evt[4]}
mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1 mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1
lastDirectionPressed = revControl[mkey] lastDirectionPressed = revControl[mkey]
keysDown[mkey] = true keysDown[mkey] = true
elseif evt[1] == "mouse_drag" then
miceDown[evt[2]] = {evt[3], evt[4]}
elseif evt[1] == "mouse_up" then elseif evt[1] == "mouse_up" then
keysDown[mkey] = false keysDown[mkey] = false
miceDown[evt[2]] = nil
mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1 mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1
keysDown[mkey] = false keysDown[mkey] = false
end end
@ -916,6 +1129,8 @@ end
local gridDemo = function() local gridDemo = function()
keysDown = {} keysDown = {}
miceDown = {}
scrollX, scrollY = math.floor(scr_x * -0.5), math.floor(scr_y * -0.75)
while true do while true do
if keysDown[keys.left] then if keysDown[keys.left] then
scrollX = scrollX - 1 scrollX = scrollX - 1
@ -1013,11 +1228,20 @@ local moveTick = function(doSend)
if doesIntersectBorder(p.x, p.y) or getTrail(p.x, p.y) then if doesIntersectBorder(p.x, p.y) or getTrail(p.x, p.y) then
p.dead = true p.dead = true
deadGuys[i] = true deadGuys[i] = true
elseif p.putTrail then else
putTrail(p) if p.putTrail or (p.trailLevel < 1) then
lastTrails[#lastTrails+1] = {p.x, p.y, p.num} putTrail(p)
if #lastTrails > #player then lastTrails[#lastTrails+1] = {p.x, p.y, p.num}
tableremove(lastTrails, 1) if #lastTrails > #player then
tableremove(lastTrails, 1)
end
if p.putTrail then
p.trailLevel = math.min(p.trailLevel + p.trailRegen, p.trailMax)
else
p.trailLevel = math.max(p.trailLevel - 1, 0)
end
else
p.trailLevel = math.max(p.trailLevel - 1, 0)
end end
end end
end end
@ -1090,18 +1314,22 @@ local game = function()
sendInfo(gamename) sendInfo(gamename)
end end
if miceDown[3] then
if keysDown[control.lookLeft] then scrollAdjX = scrollAdjX + (miceDown[3][1] - scr_x / 2) / (scr_x / 4)
scrollAdjX = scrollAdjX - 2 scrollAdjY = scrollAdjY + (miceDown[3][2] - scr_y / 2) / (scr_y / 2.795)
end else
if keysDown[control.lookRight] then if keysDown[control.lookLeft] then
scrollAdjX = scrollAdjX + 2 scrollAdjX = scrollAdjX - 2
end end
if keysDown[control.lookUp] then if keysDown[control.lookRight] then
scrollAdjY = scrollAdjY - 1.25 scrollAdjX = scrollAdjX + 2
end end
if keysDown[control.lookDown] then if keysDown[control.lookUp] then
scrollAdjY = scrollAdjY + 1.25 scrollAdjY = scrollAdjY - 1.25
end
if keysDown[control.lookDown] then
scrollAdjY = scrollAdjY + 1.25
end
end end
scrollAdjX = scrollAdjX * 0.8 scrollAdjX = scrollAdjX * 0.8
@ -1138,21 +1366,24 @@ local networking = function()
-- called while waiting for match -- called while waiting for match
if msg.new < os.time() then if msg.new < os.time() then
isHost = false isHost = false
you, nou = nou, you
gamename = msg.gameID gamename = msg.gameID
gameDelay = tonumber(msg.gameDelay) or gameDelayInit gameDelay = tonumber(msg.gameDelay) or gameDelayInit
grid = msg.grid or copyTable(initGrid) grid = msg.grid or copyTable(initGrid)
player = msg.player or player player = msg.player or player
player[you].name = argumentName or player[you].initName
else else
isHost = true isHost = true
you, nou = nou, you
end end
you, nou = nou, you
player[nou].name = msg.name or player[nou].name player[nou].name = msg.name or player[nou].initName
transmit(port, { transmit(port, {
player = player, player = player,
gameID = gamename, gameID = gamename,
new = isHost and (-math.huge) or (math.huge), new = isHost and (-math.huge) or (math.huge),
time = os.epoch(), time = os.epoch(),
name = argumentName,
grid = initGrid grid = initGrid
}) })
waitingForGame = false waitingForGame = false
@ -1179,7 +1410,7 @@ local networking = function()
netKeysDown = msg.keysDown netKeysDown = msg.keysDown
netLastDirectionPressed = msg.lastDir netLastDirectionPressed = msg.lastDir
player[nou].putTrail = msg.putTrail player[nou].putTrail = msg.putTrail
player[nou].name = msg.name or player[nou].name player[nou].name = msg.name or "???" --player[nou].name
end end
end end
@ -1197,11 +1428,12 @@ local helpScreen = function()
Move with arrow keys. Move with arrow keys.
Pan the camera with WASD. Pan the camera with WASD.
Hold SPACE to create gaps. Hold SPACE to create gaps.
This takes fuel, which will
recharge over time..
If you're P2 (red), a gray If you're P2 (red), a gray circle
circle will indicate where will indicate where you'll turn,
you'll turn, to help with to help with Skynet's netlag.
skynet's netlag.
That's basically it. That's basically it.
Press any key to go back. Press any key to go back.
@ -1211,6 +1443,11 @@ end
local startGame = function() local startGame = function()
-- reset all info between games -- reset all info between games
keysDown = {}
miceDown = {}
scrollAdjX = 0
scrollAdjY = 0
trail = {} trail = {}
deadGuys = {} deadGuys = {}
lastDirectionPressed = nil lastDirectionPressed = nil
@ -1231,11 +1468,12 @@ local startGame = function()
new = os.time(), new = os.time(),
gameDelay = gameDelayInit, gameDelay = gameDelayInit,
time = os.epoch(), time = os.epoch(),
name = argumentName or player[you].name, name = argumentName,
grid = initGrid grid = initGrid
}) })
rVal = parallel.waitForAny( pleaseWait, networking ) rVal = parallel.waitForAny( pleaseWait, networking )
sleep(0.1) sleep(0.1)
player[you].name = argumentName or player[you].initName
if rVal == 2 then if rVal == 2 then
startCountdown() startCountdown()
parallel.waitForAny( getInput, game, networking ) parallel.waitForAny( getInput, game, networking )
@ -1262,6 +1500,7 @@ local main = function()
end end
if useOnce then if useOnce then
term.setCursorBlink(false)
if useSkynet then if useSkynet then
parallel.waitForAny(startGame, skynet.listen) parallel.waitForAny(startGame, skynet.listen)
skynet.socket.close() skynet.socket.close()