Files
Techmino/parts/scenes/net_game.lua
MrZ_26 7ac6f45b9b 实现玩家设置同步到服务器
实现玩家离开房间(各种途径)
修改云存读档代码(还未实现)
移除sid,准备之后用uid本地排序序号代替(排序还未实现)
整理代码,框架跟进
2022-10-09 06:47:08 +08:00

340 lines
8.5 KiB
Lua

local gc,kb,tc=love.graphics,love.keyboard,love.touch
local gc_setColor=gc.setColor
local gc_print,gc_printf=gc.print,gc.printf
local gc_draw=gc.draw
local setFont,mStr=FONT.set,GC.mStr
local ins=table.insert
local SCR,VK,NET,NETPLY=SCR,VK,NET,NETPLY
local PLAYERS,GAME=PLAYERS,GAME
local textBox=NET.textBox
local inputBox=NET.inputBox
local playing
local lastUpstreamTime
local upstreamProgress
local noTouch,noKey=false,false
local touchMoveLastFrame=false
local function _hideReadyUI()
return
playing or
NET.roomState.start or
TASK.getLock('ready')
end
local function _setCancel()
NET.player_setPlaying(true)
NET.player_setReady(true)
end
local function _setReady()
NET.player_setReady(true)
end
local function _setSpectate()
NET.player_setPlaying(false)
end
local function _gotoSetting()
GAME.prevBG=BG.cur
SCN.go('setting_game')
end
local function _quit()
if tryBack() then
NET.room_leave()
if SCN.stack[#SCN.stack-1]=='net_newRoom' then
SCN.pop()
end
SCN.back()
end
end
local function _switchChat()
if inputBox.hide then
textBox.hide=false
inputBox.hide=false
WIDGET.focus(inputBox)
else
textBox.hide=true
inputBox.hide=true
WIDGET.unFocus(true)
end
end
local scene={}
function scene.sceneInit()
noTouch=not SETTING.VKSwitch
playing=false
lastUpstreamTime=0
upstreamProgress=1
if SCN.prev=='setting_game' then
NET.player_updateConf()
end
if GAME.prevBG then
BG.set(GAME.prevBG)
GAME.prevBG=false
end
end
function scene.sceneBack()
GAME.playing=false
end
scene.mouseDown=NULL
function scene.mouseMove(x,y) NETPLY.mouseMove(x,y) end
function scene.touchDown(x,y)
if not playing then NETPLY.mouseMove(x,y)return end
if noTouch then return end
local t=VK.on(x,y)
if t then
PLAYERS[1]:pressKey(t)
VK.touch(t,x,y)
end
end
function scene.touchUp(x,y)
if not playing or noTouch then return end
local n=VK.on(x,y)
if n then
PLAYERS[1]:releaseKey(n)
VK.release(n)
end
end
function scene.touchMove()
if touchMoveLastFrame or not playing or noTouch then return end
touchMoveLastFrame=true
local L=tc.getTouches()
for i=#L,1,-1 do
L[2*i-1],L[2*i]=SCR.xOy:inverseTransformPoint(tc.getPosition(L[i]))
end
local keys=VK.keys
for n=1,#keys do
local B=keys[n]
if B.ava then
for i=1,#L,2 do
if (L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
goto CONTINUE_nextKey
end
end
PLAYERS[1]:releaseKey(n)
VK.release(n)
end
::CONTINUE_nextKey::
end
end
function scene.keyDown(key,isRep)
if key=='escape' then
if not inputBox.hide then
_switchChat()
else
_quit()
end
elseif key=='return' then
local mes=STRING.trim(inputBox:getText())
if not inputBox.hide and #mes>0 then
if NET.room_chat(mes) then
inputBox:clear()
end
else
_switchChat()
end
elseif not inputBox.hide then
WIDGET.focus(inputBox)
inputBox:keypress(key)
elseif playing then
if noKey or isRep then return end
local k=KEY_MAP.keyboard[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
VK.press(k)
end
elseif not _hideReadyUI() then
if key=='space' then
if NETPLY.getSelfJoinMode()==0 then
(kb.isDown('lctrl','rctrl','lalt','ralt') and _setSpectate or _setReady)()
else
_setCancel()
end
elseif key=='s' then
_gotoSetting()
end
end
end
function scene.keyUp(key)
if not playing or noKey then return end
local k=KEY_MAP.keyboard[key]
if k and k>0 then
PLAYERS[1]:releaseKey(k)
VK.release(k)
end
end
function scene.gamepadDown(key)
if key=='back' then
scene.keyDown('escape')
else
if not playing then return end
local k=KEY_MAP.joystick[key]
if k and k>0 then
PLAYERS[1]:pressKey(k)
VK.press(k)
end
end
end
function scene.gamepadUp(key)
if not playing then return end
local k=KEY_MAP.joystick[key]
if k and k>0 then
PLAYERS[1]:releaseKey(k)
VK.release(k)
end
end
function scene._(cmd,d)
if cmd=='join' then
textBox:push{
COLOR.lR,d.username,
COLOR.dY,"#"..d.uid.." ",
COLOR.Y,text.joinRoom,
}
SFX.play('warn_1')
elseif cmd=='leave' then
textBox:push{
COLOR.lR,d.username,
COLOR.dY,"#"..d.uid.." ",
COLOR.Y,text.leaveRoom,
}
elseif cmd=='go' then
if not playing then
playing=true
lastUpstreamTime=0
upstreamProgress=1
resetGameData('n',NET.seed)
NETPLY.mouseMove(0,0)
end
elseif cmd=='finish' then
playing=false
BG.set()
end
end
function scene.update(dt)
if WS.status('game')~='running' then
NET.ws_close()
SCN.back()
return
end
if playing then
local P1=PLAYERS[1]
touchMoveLastFrame=false
VK.update(dt)
-- Update players
for p=1,#PLAYERS do PLAYERS[p]:update(dt) end
-- Warning check
checkWarning(dt)
-- Upload stream
if not NET.spectate and P1.frameRun-lastUpstreamTime>8 then
local stream
if not GAME.rep[upstreamProgress] then
ins(GAME.rep,P1.frameRun)
ins(GAME.rep,0)
end
stream,upstreamProgress=DATA.dumpRecording(GAME.rep,upstreamProgress)
if #stream%3==1 then
stream=stream.."\0\0"
elseif #stream%3==2 then
stream=stream.."\0\0\0\0"
end
NET.player_stream(stream)
lastUpstreamTime=PLAYERS[1].alive and P1.frameRun or 1e99
end
else
NETPLY.update(dt)
end
end
function scene.draw()
if playing then
-- Players
for p=1,#PLAYERS do
PLAYERS[p]:draw()
end
-- Virtual keys
VK.draw()
-- Warning
drawWarning()
if NET.spectate then
setFont(30)
gc_setColor(.2,1,0,.8)
gc_print(text.spectating,940,0)
end
else
-- Users
NETPLY.draw()
-- Ready & Set mark
setFont(50)
if NET.roomReadyState=='allReady' then
gc_setColor(1,.85,.6,.9)
mStr(text.ready,640,15)
elseif NET.roomReadyState=='connecting' then
gc_setColor(.6,1,.9,.9)
mStr(text.connStream,640,15)
elseif NET.roomReadyState=='waitConn' then
gc_setColor(.6,.95,1,.9)
mStr(text.waitStream,640,15)
end
-- Room info.
gc_setColor(1,1,1)
setFont(25)
gc_printf(NET.roomState.info.name,0,685,1270,'right')
setFont(40)
gc_print(NETPLY.getCount().."/"..NET.roomState.capacity,70,655)
if NET.roomState.private then
gc_draw(IMG.lock,30,668)
end
if NET.roomState.start then
gc_setColor(0,1,0)
gc_print(text.started,230,655)
end
-- Profile
drawSelfProfile()
-- Player count
drawOnlinePlayerCount()
end
-- New message
local a=TASK.getLock('receiveMessage')
if a then
setFont(40)
gc_setColor(.3,.7,1,a^2)
gc_print("M",430,10)
end
end
local function _hideF_ingame() return _hideReadyUI() or NETPLY.getSelfReady() end
local function _hideF_ingame2() return _hideReadyUI() or not NETPLY.getSelfReady() end
scene.widgetList={
textBox,
inputBox,
WIDGET.newKey{name='setting', x=1200,y=160,w=90,h=90,font=60,fText=CHAR.icon.settings,code=_gotoSetting,hideF=_hideF_ingame},
WIDGET.newKey{name='ready', x=1060,y=510,w=360,h=90,color='lG',font=35, code=_setReady,hideF=_hideF_ingame},
WIDGET.newKey{name='spectate',x=1060,y=610,w=360,h=90,color='lO',font=35, code=_setSpectate,hideF=_hideF_ingame},
WIDGET.newKey{name='cancel', x=1060,y=560,w=360,h=120,color='lH',font=40,code=_setCancel,hideF=_hideF_ingame2},
WIDGET.newKey{name='chat', x=390,y=45,w=60,fText="···", code=_switchChat},
WIDGET.newKey{name='quit', x=890,y=45,w=60,font=30,fText=CHAR.icon.cross_thick,code=_quit},
}
return scene