490 lines
14 KiB
Lua
490 lines
14 KiB
Lua
local tc=love.touch
|
|
local gc_setColor,gc_setLineWidth=GC.setColor,GC.setLineWidth
|
|
local gc_draw,gc_line=GC.draw,GC.line
|
|
local gc_circle,gc_print=GC.circle,GC.print
|
|
|
|
local SCR,VK=SCR,VK
|
|
local GAME,PLAYERS=GAME,PLAYERS
|
|
local setFont,mStr=FONT.set,GC.mStr
|
|
|
|
local noTouch,noKey=false,false
|
|
local touchMoveLastFrame=false
|
|
local trigGameRate,gameRate
|
|
local autoSkip=0
|
|
local modeTextPos,modeTextWidK
|
|
|
|
local replaying
|
|
local repRateStrings={[0]="pause",[.125]="0.125x",[.5]="0.5x",[1]="1x",[2]="2x",[5]="5x"}
|
|
|
|
local scene={}
|
|
|
|
-- Widget hashmap (key = widget name, value = index)
|
|
local widgetHashmap={}
|
|
local function widgetWithName(name)
|
|
if #widgetHashmap==0 then widgetHashmap=TABLE.kvSwap(TABLE.extract(scene.widgetList,'name')) end
|
|
return scene.widgetList[widgetHashmap[name]]
|
|
end
|
|
|
|
local function _updateMenuButtons()
|
|
widgetWithName('restart').hide=replaying
|
|
|
|
local pos=(GAME.tasUsed or replaying) and 'right' or SETTING.menuPos
|
|
modeTextWidK=math.min(280/TEXTOBJ.modeName:getWidth(),1)
|
|
if SETTING.portrait then
|
|
widgetWithName('restart').y=25-400
|
|
widgetWithName('pause').y=25-400
|
|
else
|
|
widgetWithName('restart').y=25
|
|
widgetWithName('pause').y=25
|
|
end
|
|
if GAME.replaying then
|
|
widgetWithName('pause').x=1195
|
|
modeTextPos=1185-TEXTOBJ.modeName:getWidth()*modeTextWidK
|
|
elseif pos=='right' then
|
|
widgetWithName('restart').x=1125
|
|
widgetWithName('pause').x=1195
|
|
modeTextPos=1115-TEXTOBJ.modeName:getWidth()*modeTextWidK
|
|
elseif pos=='middle' then
|
|
widgetWithName('restart').x=360
|
|
widgetWithName('pause').x=860
|
|
modeTextPos=940
|
|
elseif pos=='left' then
|
|
widgetWithName('restart').x=120
|
|
widgetWithName('pause').x=190
|
|
modeTextPos=1200-TEXTOBJ.modeName:getWidth()*modeTextWidK
|
|
end
|
|
end
|
|
|
|
local speedButtons={'rep0','repP8','repP2','rep1','rep2','rep5'}
|
|
local stepButtons={'step','autoSkip'}
|
|
local replayButtons=TABLE.combine(speedButtons,stepButtons)
|
|
local function _updateRepButtons()
|
|
local L=scene.widgetList
|
|
if replaying or GAME.tasUsed then
|
|
for i=1,#speedButtons do
|
|
widgetWithName(speedButtons[i]).hide=false
|
|
end
|
|
for i=1,#stepButtons do
|
|
widgetWithName(stepButtons[i]).hide=gameRate~=0
|
|
end
|
|
if gameRate==0 then
|
|
widgetWithName('rep0').hide=true
|
|
elseif gameRate==.125 then
|
|
widgetWithName('repP8').hide=true
|
|
elseif gameRate==.5 then
|
|
widgetWithName('repP2').hide=true
|
|
elseif gameRate==1 then
|
|
widgetWithName('rep1').hide=true
|
|
elseif gameRate==2 then
|
|
widgetWithName('rep2').hide=true
|
|
elseif gameRate==5 then
|
|
widgetWithName('rep5').hide=true
|
|
end
|
|
else
|
|
for i=1,#replayButtons do widgetWithName(replayButtons[i]).hide=true end
|
|
end
|
|
end
|
|
local function _speedUp()
|
|
if gameRate==.125 then gameRate=.5
|
|
elseif gameRate==.5 then gameRate=1
|
|
elseif gameRate==1 then gameRate=2
|
|
elseif gameRate==2 then gameRate=5
|
|
end
|
|
_updateRepButtons()
|
|
end
|
|
local function _speedDown()
|
|
if gameRate==.5 then gameRate=.125
|
|
elseif gameRate==1 then gameRate=.5
|
|
elseif gameRate==2 then gameRate=1
|
|
elseif gameRate==5 then gameRate=2
|
|
end
|
|
_updateRepButtons()
|
|
end
|
|
local function _rep0()
|
|
scene.widgetList[1].hide=true
|
|
scene.widgetList[7].hide=false
|
|
gameRate=0
|
|
_updateRepButtons()
|
|
end
|
|
local function _repP8()
|
|
scene.widgetList[2].hide=true
|
|
gameRate=.125
|
|
_updateRepButtons()
|
|
end
|
|
local function _repP2()
|
|
scene.widgetList[3].hide=true
|
|
gameRate=.5
|
|
_updateRepButtons()
|
|
end
|
|
local function _rep1()
|
|
scene.widgetList[4].hide=true
|
|
gameRate=1
|
|
_updateRepButtons()
|
|
end
|
|
local function _rep2()
|
|
scene.widgetList[5].hide=true
|
|
gameRate=2
|
|
_updateRepButtons()
|
|
end
|
|
local function _rep5()
|
|
scene.widgetList[6].hide=true
|
|
gameRate=5
|
|
_updateRepButtons()
|
|
end
|
|
local function _skip(P)
|
|
if P.frameRun<179 then
|
|
trigGameRate=trigGameRate+(179-P.frameRun)
|
|
else
|
|
trigGameRate=trigGameRate+MATH.clamp(P.waiting+P.falling,1,300)
|
|
end
|
|
end
|
|
local fastForwardObj = GC.newText(FONT.get(40),CHAR.icon.fastForward)
|
|
local nextFrameObj = GC.newText(FONT.get(40),CHAR.icon.nextFrame)
|
|
local function _updateStepButton()
|
|
local w=PLAYERS[1].waiting+PLAYERS[1].falling
|
|
if (autoSkip==1 and w>1) or (autoSkip>0 and PLAYERS[1].frameRun<178) then
|
|
widgetWithName('step').obj=fastForwardObj
|
|
else
|
|
widgetWithName('step').obj=nextFrameObj
|
|
end
|
|
end
|
|
local function _step()
|
|
local P=PLAYERS[1]
|
|
if autoSkip>0 then
|
|
_skip(P)
|
|
else
|
|
trigGameRate=trigGameRate+1
|
|
end
|
|
end
|
|
local function _fullSkipCheck()
|
|
if autoSkip<2 or PLAYERS[1].waiting+PLAYERS[1].falling<=0 then return end
|
|
_step()
|
|
end
|
|
local function _setAS(v)
|
|
autoSkip=v
|
|
if v==1 then _updateStepButton() end
|
|
end
|
|
local function _autoSkipDisp()
|
|
return (
|
|
autoSkip==0 and 'No skip' or
|
|
autoSkip==1 and 'Semi-skip' or
|
|
autoSkip==2 and 'Full skip'
|
|
)
|
|
end
|
|
|
|
local function _restart()
|
|
resetGameData(PLAYERS[1].frameRun<240 and 'q')
|
|
noKey=replaying
|
|
noTouch=replaying
|
|
trigGameRate,gameRate=0,1
|
|
_updateRepButtons()
|
|
end
|
|
local function _checkGameKeyDown(key)
|
|
local k=KEY_MAP.keyboard[key]
|
|
if k then
|
|
if k>0 then
|
|
if noKey then return end
|
|
PLAYERS[1]:pressKey(k)
|
|
VK.press(k)
|
|
_updateStepButton()
|
|
_fullSkipCheck()
|
|
return
|
|
elseif not GAME.fromRepMenu then
|
|
_restart()
|
|
return
|
|
end
|
|
end
|
|
return true-- No key pressed
|
|
end
|
|
|
|
function scene.enter()
|
|
if GAME.init then
|
|
resetGameData()
|
|
GAME.init=false
|
|
end
|
|
|
|
replaying=GAME.replaying
|
|
noKey=replaying
|
|
noTouch=not SETTING.VKSwitch or replaying
|
|
|
|
if SCN.prev~='depause' and SCN.prev~='pause' then
|
|
trigGameRate,gameRate=0,1
|
|
elseif not replaying then
|
|
if GAME.tasUsed then
|
|
trigGameRate,gameRate=0,0
|
|
autoSkip=1
|
|
else
|
|
trigGameRate,gameRate=0,1
|
|
autoSkip=0
|
|
end
|
|
end
|
|
|
|
_updateStepButton()
|
|
_updateRepButtons()
|
|
_updateMenuButtons()
|
|
|
|
DiscordRPC.update("Playing "..GAME.curMode.name)
|
|
end
|
|
|
|
scene.mouseDown=NULL
|
|
function scene.touchDown(x,y)
|
|
if noTouch then return end
|
|
|
|
local t=VK.on(x,y)
|
|
if t then
|
|
PLAYERS[1]:pressKey(t)
|
|
VK.touch(t,x,y)
|
|
_updateStepButton()
|
|
_fullSkipCheck()
|
|
end
|
|
end
|
|
function scene.touchUp(x,y)
|
|
if 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 noTouch or touchMoveLastFrame 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
|
|
local nextKey
|
|
for i=1,#L,2 do
|
|
if (L[i]-B.x)^2+(L[i+1]-B.y)^2<=B.r^2 then
|
|
nextKey=true
|
|
break-- goto CONTINUE_nextKey
|
|
end
|
|
end
|
|
if not nextKey then
|
|
PLAYERS[1]:releaseKey(n)
|
|
VK.release(n)
|
|
end
|
|
-- ::CONTINUE_nextKey::
|
|
end
|
|
end
|
|
end
|
|
function scene.keyDown(key,isRep)
|
|
if replaying then
|
|
if key=='space' then
|
|
if not isRep then
|
|
gameRate=gameRate==0 and 1 or 0
|
|
end
|
|
_updateRepButtons()
|
|
elseif key=='left' then
|
|
if not isRep then
|
|
_speedDown()
|
|
end
|
|
elseif key=='right' then
|
|
if gameRate==0 then
|
|
_step()
|
|
elseif not isRep then
|
|
_speedUp()
|
|
end
|
|
elseif key=='escape' then
|
|
pauseGame()
|
|
end
|
|
else
|
|
if isRep then
|
|
return
|
|
elseif _checkGameKeyDown(key) then
|
|
if GAME.tasUsed then
|
|
if key=='f1' then
|
|
if not isRep then
|
|
gameRate=gameRate==0 and .125 or 0
|
|
end
|
|
_updateRepButtons()
|
|
elseif key=='f2' then
|
|
if not isRep then
|
|
_speedDown()
|
|
end
|
|
elseif key=='f3' then
|
|
if gameRate==0 then
|
|
_step()
|
|
elseif not isRep then
|
|
_speedUp()
|
|
end
|
|
elseif key=='f4' then
|
|
autoSkip=(autoSkip+1)%3
|
|
end
|
|
end
|
|
if key=='escape' then
|
|
pauseGame()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
function scene.keyUp(key)
|
|
if noKey then return end
|
|
local k=KEY_MAP.keyboard[key]
|
|
if k then
|
|
if k>0 then
|
|
PLAYERS[1]:releaseKey(k)
|
|
VK.release(k)
|
|
end
|
|
end
|
|
end
|
|
function scene.gamepadDown(key)
|
|
if noKey then return end
|
|
local k=KEY_MAP.joystick[key]
|
|
if k then
|
|
if k>0 then
|
|
PLAYERS[1]:pressKey(k)
|
|
VK.press(k)
|
|
_updateStepButton()
|
|
_fullSkipCheck()
|
|
else
|
|
_restart()
|
|
end
|
|
elseif key=='back' then
|
|
pauseGame()
|
|
end
|
|
end
|
|
function scene.gamepadUp(key)
|
|
if noKey then return end
|
|
local k=KEY_MAP.joystick[key]
|
|
if k then
|
|
if k>0 then
|
|
PLAYERS[1]:releaseKey(k)
|
|
VK.release(k)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function _update_common(dt)
|
|
-- Update control
|
|
touchMoveLastFrame=false
|
|
VK.update(dt)
|
|
|
|
-- Update players
|
|
for p=1,#PLAYERS do PLAYERS[p]:update(dt) end
|
|
|
|
-- Fresh royale target
|
|
if PLAYERS[1].frameRun%120==0 and PLAYERS[1].gameEnv.layout=='royale' then
|
|
freshMostDangerous()
|
|
end
|
|
|
|
-- Warning check
|
|
checkWarning(PLAYERS[1],dt)
|
|
end
|
|
function scene.update(dt)
|
|
trigGameRate=trigGameRate+gameRate
|
|
while trigGameRate>=1 do
|
|
trigGameRate=trigGameRate-1
|
|
_update_common(dt)
|
|
_updateStepButton()
|
|
end
|
|
end
|
|
|
|
local tasText=GC.newText(getFont(100),"TAS")
|
|
local function _drawAtkPointer(x,y)
|
|
local t=TIME()
|
|
local a=t*3%1*.8
|
|
t=math.sin(t*20)
|
|
|
|
gc_setColor(.2,.7+t*.2,1,.6+t*.4)
|
|
gc_circle('fill',x,y,25,6)
|
|
|
|
gc_setColor(0,.6,1,.8-a)
|
|
gc_circle('line',x,y,30*(1+a),6)
|
|
end
|
|
function scene.draw()
|
|
local tas=GAME.tasUsed
|
|
if tas then
|
|
setFont(100)
|
|
gc_setColor(.4,.4,.4,.5)
|
|
mDraw(tasText,640,360,nil,5)
|
|
end
|
|
|
|
local repMode=GAME.replaying or tas
|
|
|
|
-- Players
|
|
for p=1,#PLAYERS do
|
|
PLAYERS[p]:draw(repMode)
|
|
end
|
|
|
|
-- Virtual keys
|
|
VK.draw()
|
|
|
|
-- Attacking & Being attacked
|
|
if PLAYERS[1].gameEnv.layout=='royale' then
|
|
local P=PLAYERS[1]
|
|
gc_setLineWidth(5)
|
|
gc_setColor(.8,1,0,.2)
|
|
for i=1,#P.atker do
|
|
local p=P.atker[i]
|
|
gc_line(p.centerX,p.centerY,P.x+300*P.size,P.y+620*P.size)
|
|
end
|
|
if P.atkMode~=4 then
|
|
if P.atking then
|
|
_drawAtkPointer(P.atking.centerX,P.atking.centerY)
|
|
end
|
|
else
|
|
for i=1,#P.atker do
|
|
local p=P.atker[i]
|
|
_drawAtkPointer(p.centerX,p.centerY)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Mode info & Highscore & Current Rank
|
|
local dy=SETTING.portrait and -390 or 0
|
|
gc_setColor(1,1,1,.82)
|
|
gc_draw(TEXTOBJ.modeName,modeTextPos,10+dy,0,modeTextWidK,1)
|
|
if not replaying then
|
|
local M=GAME.curMode
|
|
if M then
|
|
if M.score and M.records[1] then
|
|
setFont(15)
|
|
gc_setColor(1,1,1,.6)
|
|
gc_print(M.scoreDisp(M.records[1]),modeTextPos,45+dy)
|
|
end
|
|
if M.getRank then
|
|
local R=M.getRank(PLAYERS[1])
|
|
if R and R>0 then
|
|
setFont(100)
|
|
local c=RANK_COLORS[R]
|
|
gc_setColor(c[1],c[2],c[3],.12)
|
|
mStr(RANK_CHARS[R],640,50+dy)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Replaying
|
|
if replaying or tas then
|
|
setFont(20)
|
|
gc_setColor(1,1,TIME()%.8>.4 and 1 or 0)
|
|
mStr(replaying and text.replaying or text.tasUsing,770,6)
|
|
gc_setColor(1,1,1,.8)
|
|
mStr(("%s %sf"):format(repRateStrings[gameRate],PLAYERS[1].frameRun),770,31)
|
|
end
|
|
|
|
-- Warning
|
|
drawWarning()
|
|
end
|
|
scene.widgetList={
|
|
WIDGET.newKey {name='rep0', x=40, y=50, w=60, code=_rep0, font=40, fText=CHAR.icon.pause}, -- 1
|
|
WIDGET.newKey {name='repP8', x=105,y=50, w=60, code=_repP8, font=40, fText=CHAR.icon.speedOneEights}, -- 2
|
|
WIDGET.newKey {name='repP2', x=170,y=50, w=60, code=_repP2, font=40, fText=CHAR.icon.speedOneHalf}, -- 3
|
|
WIDGET.newKey {name='rep1', x=235,y=50, w=60, code=_rep1, font=40, fText=CHAR.icon.speedOne}, -- 4
|
|
WIDGET.newKey {name='rep2', x=300,y=50, w=60, code=_rep2, font=40, fText=CHAR.icon.speedTwo}, -- 5
|
|
WIDGET.newKey {name='rep5', x=365,y=50, w=60, code=_rep5, font=40, fText=CHAR.icon.speedFive}, -- 6
|
|
WIDGET.newKey {name='step', x=40, y=50, w=60, code=_step, font=40, fText=CHAR.icon.nextFrame}, -- 7
|
|
WIDGET.newSlider{name='autoSkip',x=40, y=130,w=100,code=_setAS, axis={0,2,1}, disp=function()return autoSkip end,show=_autoSkipDisp},
|
|
WIDGET.newKey {name='restart', x=0, y=25, w=60, code=_restart, font=40, fText=CHAR.icon.retry_spin}, -- 10
|
|
WIDGET.newKey {name='pause', x=0, y=25, w=60, code=pauseGame,font=40, fText=CHAR.icon.pause}, -- 11
|
|
}
|
|
|
|
return scene
|