Compare commits

..

2 Commits

Author SHA1 Message Date
wan-may e7926fab3c Text input widget; batch text. 2023-09-06 22:03:22 -03:00
wan-may 4d084488f7 Update options menu. Reorganize ui into proper folder. Add text input widget. 2023-09-05 23:24:25 -03:00
14 changed files with 382 additions and 156 deletions

Binary file not shown.

View File

@ -7,4 +7,5 @@ return setmetatable({
["option_name"] = "Player Name", ["option_name"] = "Player Name",
["option_pron"] = "Player Pronouns", ["option_pron"] = "Player Pronouns",
["option_tint"] = "Player Colour", ["option_tint"] = "Player Colour",
["option_keybinds"] = "Edit Keybindings",
}, {__index = function( t, k ) return k end } ) }, {__index = function( t, k ) return k end } )

View File

@ -1,26 +0,0 @@
local lg = assert( love.graphics )
local scene = assert( require 'client.scene' )
local browser = {}
function browser.draw()
lg.rectangle( "fill", 50, 50, 50, 50 )
end
function browser.update( dt )
end
function browser.onLoad( )
lg.setColor( 1, 1, 1, 1 )
end
function browser.mousepressed()
end
function browser.keypressed( key, code, isRepeat )
if code == "escape" then return scene.mainmenu() end
end
scene.browser = browser
return browser

15
src/client/config.lua Normal file
View File

@ -0,0 +1,15 @@
return {
name = "Player Name",
pronoun = "they",
colour = {0.8, 0.4, 0.4, 0.7},
gamma = 0.5,
keybinds = {
forward = "w",
back = "s",
left = "a",
right = "d",
chat = "t",
love = "q",
hate = "e",
}
}

View File

@ -7,14 +7,16 @@ local udp = socket.udp()
local game = {} local game = {}
local t = 0 local t = 0
local tick = 0 local tick = 0
local serverTick = "0"
function game.draw() function game.draw()
lg.print( tick, 0, 0 )
lg.print( serverTick, 0, 25 )
end end
function game.onPacket( data, msg ) function game.onPacket( data, msg )
if data then print( data, msg ) end if data then serverTick = data end
end end
function game.update( dt ) function game.update( dt )
@ -36,9 +38,11 @@ function game.disconnect( )
return scene.mainmenu() return scene.mainmenu()
end end
function game.onLoad( ) function game.onLoad( params )
params = params or {}
local serverIP, serverPort = params.serverIP or "192.168.2.15", params.serverPort or 51312
udp:settimeout( 0 ) udp:settimeout( 0 )
udp:setpeername( "192.168.2.15", 51312 ) udp:setpeername( serverIP, serverPort )
end end
function game.keypressed( key, code, isRepeat ) function game.keypressed( key, code, isRepeat )

View File

@ -1,108 +0,0 @@
local lg = assert( love.graphics )
local love = assert( love )
local scene = assert( require 'client.scene' )
local strings = assert( require 'client.assets.strings' )
local button = assert( require 'client.button' )
local menu = {}
local t = 0
local wWidth = 800
local wHeight = 600
local selectedButtonIdx = nil
local buttons =
{
button{
x = 15, w = 400, h = 50,
y = 115,
text = strings.option_name,
color = { 0.5, 0.7, 0.5, 1 },
callback = function() print("Adjust Name") end },
button{
x = 15, w = 400, h = 50,
y = 115 + 55,
text = strings.option_pron,
color = { 0.5, 0.7, 0.5, 1 },
callback = function() print("Adjust Name") end },
button{
x = 15, w = 400, h = 50,
y = 115 + 55 * 2,
text = strings.option_tint,
color = { 0.5, 0.7, 0.5, 1 },
callback = function() print("Adjust Colour") end },
button{
x = 15, w = 400, h = 50,
y = 115 + 55 * 3,
text = strings.mainmenu_button,
color = { 0.5, 0.7, 0.5, 1 },
callback = function() print("Adjust Name") return scene.mainmenu() end },
}
function menu.onLoad()
end
function menu.draw()
for id, button in pairs( buttons ) do button:draw( ) end
end
function menu.update( dt )
t = t + dt
end
function menu.resize( w, h )
wWidth, wHeight = w, h
end
function menu.mousemoved( x, y, dx, dy, istouch )
if selectedButtonIdx then
buttons[selectedButtonIdx].selected = false
selectedButtonIdx = nil
end
for id, menuButton in ipairs( buttons ) do
if menuButton:contains( x, y ) then
menuButton.selected = true
selectedButtonIdx = id
break
end
end
end
function menu.mousepressed( x, y, button, istouch, presses )
if not selectedButtonIdx then return end
local uiButton = buttons[selectedButtonIdx]
if uiButton:contains( x, y ) then return uiButton() end
end
function menu.keypressed( key, code, isrepeat )
if code == "escape" then
return scene.mainmenu()
end
if code == "return" and selectedButtonIdx then
return buttons[selectedButtonIdx]()
end
if code == "down" or code == "tab" or code == "up" then
local sbi = (selectedButtonIdx or 1)
buttons[sbi].selected = false
--Increment / decrement
sbi = sbi + ((code == "up") and -1 or 1)
if sbi > #buttons then sbi = 1 end
if sbi < 1 then sbi = #buttons end
--Assign
print( "selecting button: ", sbi )
selectedButtonIdx = sbi
buttons[selectedButtonIdx].selected = true
end
end
scene.options = menu
return menu

View File

@ -2,12 +2,12 @@ local scene = {}
local love = assert( love ) local love = assert( love )
local mt = {} local mt = {}
local function loadScene( scene ) local function loadScene( scene, params )
print( "Loading Scene:", scene.name ) print( "Loading Scene:", scene.name )
for k, v in pairs( scene ) do for k, v in pairs( scene ) do
love[k] = v love[k] = v
end end
scene.onLoad() scene.onLoad( params )
end end
local function newScene( scenes, name, t ) local function newScene( scenes, name, t )

51
src/client/ui/browser.lua Normal file
View File

@ -0,0 +1,51 @@
local lg = assert( love.graphics )
local scene = assert( require 'client.scene' )
local textInput = assert( require 'client.ui.textinput' )
local button = assert( require 'client.ui.button' )
local browser = {}
local ti = textInput.new{
width = 300,
length = 20,
x = 15,
y = 165
}
function browser.draw()
lg.setColor( 1, 1, 1, 1 )
lg.print( "Server Browser", 15, 115 )
ti:draw()
end
function browser.update( dt )
end
function browser.onLoad( )
lg.setColor( 1, 1, 1, 1 )
end
function browser.mousepressed(x, y, button, istouch, pressed)
if ti:contains( x, y ) then return ti:enterText( browser.joinIPString ) end
end
function browser.joinIPString( s )
--Parse IP address and port from string. If it's valid, join the server.
if not s then return end
ti:clear()
local valid, ip, port
if valid then return browser.joinIP( ip, port ) end
end
function browser.joinIP( ip, port )
return scene.game{ serverIP = ip, serverPort = port }
end
function browser.keypressed( key, code, isRepeat )
if code == "escape" then return scene.mainmenu() end
if code == "return" then return ti:enterText( browser.joinIPString ) end
end
scene.browser = browser
return browser

View File

@ -31,8 +31,6 @@ function button:draw( )
if self.selected then if self.selected then
lg.setColor( 1, 1, 1, 0.8 ) lg.setColor( 1, 1, 1, 0.8 )
lg.rectangle( "fill", self.x + 3, self.y + 3, self.w - 6, self.h - 6, 10 ) lg.rectangle( "fill", self.x + 3, self.y + 3, self.w - 6, self.h - 6, 10 )
else
lg.setColor( 0, 0, 0, 0.7 )
end end
lg.setColor( 0, 0, 0, 0.7 ) lg.setColor( 0, 0, 0, 0.7 )

View File

@ -2,7 +2,7 @@ local lg = assert( love.graphics )
local love = assert( love ) local love = assert( love )
local scene = assert( require 'client.scene' ) local scene = assert( require 'client.scene' )
local strings = assert( require 'client.assets.strings' ) local strings = assert( require 'client.assets.strings' )
local button = assert( require 'client.button' ) local button = assert( require 'client.ui.button' )
local menu = {} local menu = {}
local t = 0 local t = 0
@ -93,7 +93,7 @@ function menu.paint()
end end
function menu.onLoad() function menu.onLoad()
lg.setNewFont( "client/assets/SitkaB.ttc", 28 ) lg.setNewFont( 28 )
return menu.resize( lg.getDimensions() ) return menu.resize( lg.getDimensions() )
end end
@ -119,11 +119,9 @@ function menu.mousemoved( x, y, dx, dy, istouch )
if menuButton:contains( x, y ) then if menuButton:contains( x, y ) then
menuButton.selected = true menuButton.selected = true
selectedButtonIdx = id selectedButtonIdx = id
break
end
end
return menu.paint() return menu.paint()
end
end
end end
function menu.mousepressed( x, y, button, istouch, presses ) function menu.mousepressed( x, y, button, istouch, presses )

181
src/client/ui/options.lua Normal file
View File

@ -0,0 +1,181 @@
local lg = assert( love.graphics )
local love = assert( love )
local scene = assert( require 'client.scene' )
local strings = assert( require 'client.assets.strings' )
local button = assert( require 'client.ui.button' )
local textinput = assert( require 'client.ui.textinput' )
local menu = {}
local t = 0
local wWidth = 800
local wHeight = 600
local canvas = lg.newCanvas()
local selectedButtonIdx = nil
local gradientQuad = lg.newMesh{
{ 0, 0, 0, 0, 0.4, 0.1, 0.4, 0.0 },
{ 1, 0, 1, 0, 0.8, 0.3, 0.1, 1.0 },
{ 1, 1, 1, 1, 0.7, 0.4, 0.1, 1.0 },
{ 0, 1, 0, 1, 0.4, 0.1, 0.3, 0.0 },
}
local buttons =
{
button{
x = 15, w = 400, h = 50,
y = 115,
text = strings.mainmenu_button,
color = { 0.5, 0.2, 0.8, 0.6 },
callback = function() return scene.mainmenu() end },
button{
x = 15, w = 400, h = 50,
y = 115 + 55,
option = 'name',
text = strings.option_name,
color = { 0.5, 0.2, 0.2, 0.6 },
callback = menu.textOption },
button{
x = 15, w = 400, h = 50,
y = 115 + 55 * 2,
option = 'pronoun',
text = strings.option_pron,
color = { 0.5, 0.2, 0.4, 0.6 },
callback = menu.textOption },
button{
x = 15, w = 400, h = 50,
y = 115 + 55 * 3,
option = 'colour',
text = strings.option_tint,
color = { 0.5, 0.2, 0.6, 0.6 },
callback = menu.colourOption },
button{
x = 15, w = 400, h = 50,
y = 115 + 55 * 4,
option = 'keybinds',
text = strings.keybinding_button,
color = { 0.8, 0.0, 0.4, 0.8 },
callback = menu.editKeybinds,
}
}
--[[local keybindButtons = {
button{
x = wWidth / 2, w = 400, h = 50
y = 115,
text = options:get( 'forward_key' ),
color = { 0.8, 0.0, 0.4, 0.8 },
callback = function() options:set( 'forward_key' ) end,
},
button{
x = wWidth / 2, w = 400, h = 50
y = 115,
text = strings.backward_key,
color = { 0.8, 0.0, 0.4, 0.8 },
callback = function() return setOption( 'backward_key' ) end,
}
}]]
function menu.onLoad()
lg.setNewFont( 28 )
return menu.resize( lg.getDimensions() )
end
function menu.draw()
lg.setCanvas()
lg.setColor( 1,1,1,1 )
lg.draw( canvas )
end
function menu.paint()
lg.setCanvas( canvas )
--bg
lg.setColor( 0.8, 0.6, 0.3, 1 )
lg.rectangle( "fill", 0, 0, wWidth, wHeight )
--buttons
for id, button in pairs( buttons ) do button:draw( ) end
--gradient
lg.setColor( 1, 1, 1, 1 )
lg.draw( gradientQuad, 0, 0, 0, wWidth, wHeight )
lg.setCanvas()
end
function menu.update( dt )
t = t + dt
end
function menu.resize( w, h )
wWidth, wHeight = w, h
canvas = lg.newCanvas()
for id, uiButton in pairs( buttons ) do
uiButton.w = wWidth
end
return menu.paint()
end
function menu.mousemoved( x, y, dx, dy, istouch )
if selectedButtonIdx then
buttons[selectedButtonIdx].selected = false
selectedButtonIdx = nil
end
for id, menuButton in ipairs( buttons ) do
if menuButton:contains( x, y ) then
menuButton.selected = true
selectedButtonIdx = id
return menu.paint()
end
end
end
function menu.mousepressed( x, y, button, istouch, presses )
if not selectedButtonIdx then return end
local uiButton = buttons[selectedButtonIdx]
if uiButton:contains( x, y ) then return uiButton( ) end
return menu.paint()
end
function menu.keypressed( key, code, isrepeat )
if code == "escape" then
return scene.mainmenu()
end
if code == "return" and selectedButtonIdx then
return buttons[selectedButtonIdx].callback()
end
if code == "down" or code == "tab" or code == "up" then
local sbi = (selectedButtonIdx or 1)
buttons[sbi].selected = false
--Increment / decrement
sbi = sbi + ((code == "up") and -1 or 1)
if sbi > #buttons then sbi = 1 end
if sbi < 1 then sbi = #buttons end
--Assign
print( "selecting button: ", sbi )
selectedButtonIdx = sbi
buttons[selectedButtonIdx].selected = true
end
return menu.paint()
end
scene.options = menu
return menu

111
src/client/ui/textinput.lua Normal file
View File

@ -0,0 +1,111 @@
local love = assert( love )
local lk = assert( love.keyboard )
local lg = assert( love.graphics )
local utf8 = assert( require 'utf8' )
local string = assert( string )
local _lt
local _lkp
local _lmm
local _lmp
local _callback
local textInput = { }
local __mt = { __index = textInput }
local font = lg.newFont( 36 )
-- There is only one active text input widget at a time.
-- It takes exclusive control of key input.
local activeWidget
textInput.width = 200
textInput.length = 20
textInput.x = 0
textInput.y = 0
function textInput.new( t )
t = t or {}
t.text = lg.newText( font, "")
t.str = ""
return setmetatable( t, __mt )
end
function textInput.keypressed(key, code, isRepeat)
if activeWidget and textInput[code] then return textInput[code]() end
end
function textInput:clear()
self.str = ""
self.text:set( self.str )
end
function textInput:contains(x, y)
local mx, my, Mx, My = self.x, self.y, self.x + self.width, self.y + font:getHeight()
return (x < Mx and x > mx and y > my and y < My)
end
function textInput:draw()
local w, h = self.text:getDimensions()
lg.setColor( 1, 1, 1, 0.5 )
lg.rectangle( "fill", self.x, self.y, w, h )
if activeWidget == self then lg.rectangle( "fill", self.x, self.y, self.width, font:getHeight(), 5 ) end
lg.rectangle( "line", self.x - 3, self.y - 3, self.width + 6, font:getHeight() + 6, 5 )
lg.setColor( 0, 0, 0, 1 )
lg.draw( self.text, self.x or 0, self.y or 0)
end
function textInput:getText()
return self.str
end
function textInput.textInput( s )
activeWidget.str = activeWidget.str..s
activeWidget.text:set( activeWidget.str )
end
function textInput.backspace( )
local str = activeWidget.str
local byteoffset = utf8.offset(str, -1)
if byteoffset then str = string.sub(str, 1, byteoffset - 1)
else return end
activeWidget.str = str
activeWidget.text:set( activeWidget.str )
end
function textInput:enterText( callback )
_lt = love.textinput
_lkp = love.keypressed
_lmm = love.mousemoved
_lmp = love.mousepressed
_callback = assert( callback )
love.textinput = textInput.textInput
love.keypressed = textInput.keypressed
self.oldStr = self.str
activeWidget = self
end
local function disable()
activeWidget = nil
love.textinput = _lt
love.keypressed = _lkp
love.mousemoved = _lmm
love.mousepressed = _lmp
end
function textInput.escape()
activeWidget.str = activeWidget.oldStr or ""
activeWidget.text:set( activeWidget.str )
disable()
return _callback()
end
textInput["return"] = function() --unusual decl because return is a keyword
local str = activeWidget.str
disable()
return _callback( str )
end
return textInput

View File

@ -4,9 +4,9 @@ local love = assert( love )
function love.load() function love.load()
local scenes = assert( require 'client.scene' ) local scenes = assert( require 'client.scene' )
assert( require 'client.menu' ) assert( require 'client.ui.menu' )
assert( require 'client.browser' ) assert( require 'client.ui.browser' )
assert( require 'client.game' ) assert( require 'client.game' )
assert( require 'client.options' ) assert( require 'client.ui.options' )
scenes.mainmenu() scenes.mainmenu()
end end

View File

@ -9,9 +9,7 @@ local server = {
serverName = "dajjal-server", serverName = "dajjal-server",
} }
local clients = { local clients = {}
}
do do
local _print = print local _print = print
@ -32,7 +30,10 @@ end
--Incoming packet. --Incoming packet.
function server.Parse( packet, ip, port ) function server.Parse( packet, ip, port )
if not packet then return end if not packet then return end
print( packet, ip, port ) if not clients[ip] then
clients[ip] = { ip = ip, port = port }
end
clients[ip].tick = packet
return server.Parse( udp:receivefrom() ) -- Process any packets we missed. return server.Parse( udp:receivefrom() ) -- Process any packets we missed.
end end
@ -49,7 +50,7 @@ end
function server.Advance() function server.Advance()
server.tick = server.tick + 1 server.tick = server.tick + 1
for id, client in ipairs( clients ) do for id, client in pairs( clients ) do
udp:sendto( string.format("server: %d client: %d", server.tick, client.tick), client.ip, client.port) udp:sendto( string.format("server: %d client: %d", server.tick, client.tick), client.ip, client.port)
end end
end end