统一管理玩家update函数而不是在特定时候切换,方便之后把帧步进改为时间同步
This commit is contained in:
@@ -6,7 +6,6 @@ local rnd,max=math.random,math.max
|
||||
local ins=table.insert
|
||||
|
||||
local ply_draw=require"parts.player.draw"
|
||||
local ply_update=require"parts.player.update"
|
||||
local PLY={draw=ply_draw}
|
||||
|
||||
--------------------------<Libs>--------------------------
|
||||
@@ -79,7 +78,6 @@ local function _newEmptyPlayer(id,mini)
|
||||
P.pressKey=_pressKey
|
||||
P.releaseKey=_releaseKey
|
||||
end
|
||||
P.update=ply_update.alive
|
||||
|
||||
--Field position
|
||||
P.fieldOff={--Shake FX
|
||||
@@ -434,7 +432,6 @@ end
|
||||
function PLY.newRemotePlayer(id,mini,ply)
|
||||
local P=_newEmptyPlayer(id,mini)
|
||||
P.type='remote'
|
||||
P.update=ply_update.remote_alive
|
||||
|
||||
P.draw=ply_draw.norm
|
||||
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
local Player={}--Player class
|
||||
|
||||
local int,ceil,rnd=math.floor,math.ceil,math.random
|
||||
local max,min,modf=math.max,math.min,math.modf
|
||||
local max,min,abs,modf=math.max,math.min,math.abs,math.modf
|
||||
local ins,rem=table.insert,table.remove
|
||||
local resume,yield,status=coroutine.resume,coroutine.yield,coroutine.status
|
||||
local assert=assert
|
||||
|
||||
local SFX,BGM,VOC,VIB,SYSFX=SFX,BGM,VOC,VIB,SYSFX
|
||||
local FREEROW,TABLE,TEXT,NET,TASK=FREEROW,TABLE,TEXT,NET,TASK
|
||||
local PLAYERS,PLY_ALIVE,GAME=PLAYERS,PLY_ALIVE,GAME
|
||||
|
||||
local ply_draw=require"parts.player.draw"
|
||||
local ply_update=require"parts.player.update"
|
||||
|
||||
--------------------------<FX>--------------------------
|
||||
function Player:_showText(text,dx,dy,font,style,spd,stop)
|
||||
@@ -1589,9 +1589,9 @@ function Player:loadAI(data)--Load AI params
|
||||
self.bot=BOT.new(self,data)
|
||||
self.bot.data=data
|
||||
end
|
||||
--------------------------</Methods>--------------------------
|
||||
--------------------------</Method>--------------------------
|
||||
|
||||
--------------------------<Ticks>--------------------------
|
||||
--------------------------<Tick>--------------------------
|
||||
local function task_throwBadge(ifAI,sender,time)
|
||||
while true do
|
||||
yield()
|
||||
@@ -1685,14 +1685,471 @@ local function task_autoPause()
|
||||
end
|
||||
end
|
||||
end
|
||||
--------------------------</Ticks>--------------------------
|
||||
--------------------------</Tick>--------------------------
|
||||
|
||||
--------------------------<Events>--------------------------
|
||||
--------------------------<Event>--------------------------
|
||||
local function _updateMisc(P,dt)
|
||||
--Finesse combo animation
|
||||
if P.finesseComboTime>0 then
|
||||
P.finesseComboTime=P.finesseComboTime-1
|
||||
end
|
||||
|
||||
--Update spike counter
|
||||
if P.spikeTime>0 then
|
||||
P.spikeTime=P.spikeTime-1
|
||||
end
|
||||
|
||||
--Update atkBuffer alert
|
||||
local t=P.atkBufferSum1
|
||||
if t<P.atkBufferSum then
|
||||
P.atkBufferSum1=t+.25
|
||||
elseif t>P.atkBufferSum then
|
||||
P.atkBufferSum1=t-.5
|
||||
end
|
||||
|
||||
--Update attack buffer
|
||||
local bf=P.atkBuffer
|
||||
for i=#bf,1,-1 do
|
||||
local A=bf[i]
|
||||
A.time=A.time+1
|
||||
if not A.sent then
|
||||
if A.countdown>0 then
|
||||
A.countdown=max(A.countdown-P.gameEnv.garbageSpeed,0)
|
||||
end
|
||||
else
|
||||
if A.time>20 then
|
||||
rem(bf,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Push up garbages
|
||||
local y=P.fieldBeneath
|
||||
if y>0 then
|
||||
P.fieldBeneath=max(y-P.gameEnv.pushSpeed,0)
|
||||
end
|
||||
|
||||
--Move camera
|
||||
if P.gameEnv.highCam then
|
||||
if not P.alive then
|
||||
y=0
|
||||
else
|
||||
y=30*max(min(#P.field-18.5-P.fieldBeneath/30,P.ghoY-17),0)
|
||||
end
|
||||
local f=P.fieldUp
|
||||
if f~=y then
|
||||
P.fieldUp=f>y and max(f*.95+y*.05-2,y)or min(f*.97+y*.03+1,y)
|
||||
end
|
||||
end
|
||||
|
||||
--Update Score
|
||||
if P.stat.score>P.score1 then
|
||||
if P.stat.score-P.score1<10 then
|
||||
P.score1=P.score1+1
|
||||
else
|
||||
P.score1=int(min(P.score1*.9+P.stat.score*.1+1))
|
||||
end
|
||||
end
|
||||
|
||||
--Update lock FX
|
||||
for i=#P.lockFX,1,-1 do
|
||||
local S=P.lockFX[i]
|
||||
S[3]=S[3]+S[4]*dt
|
||||
if S[3]>1 then
|
||||
rem(P.lockFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Update drop FX
|
||||
for i=#P.dropFX,1,-1 do
|
||||
local S=P.dropFX[i]
|
||||
S[5]=S[5]+S[6]*dt
|
||||
if S[5]>1 then
|
||||
rem(P.dropFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Update move FX
|
||||
for i=#P.moveFX,1,-1 do
|
||||
local S=P.moveFX[i]
|
||||
S[4]=S[4]+S[5]*dt
|
||||
if S[4]>1 then
|
||||
rem(P.moveFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Update clear FX
|
||||
for i=#P.clearFX,1,-1 do
|
||||
local S=P.clearFX[i]
|
||||
S[2]=S[2]+S[3]*dt
|
||||
if S[2]>1 then
|
||||
rem(P.clearFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Field shaking
|
||||
if P.gameEnv.shakeFX then
|
||||
local O=P.fieldOff
|
||||
O.vx=O.vx*.7-abs(O.x)^1.3*(O.x>0 and .1 or -.1)
|
||||
O.x=O.x+O.vx
|
||||
|
||||
O.vy=O.vy*.7-abs(O.y)^1.2*(O.y>0 and .1 or -.1)
|
||||
O.y=O.y+O.vy
|
||||
|
||||
O.va=O.va*.7-abs(O.a)^1.4*(O.a>0 and .08 or -.08)
|
||||
O.a=O.a+O.va
|
||||
if abs(O.a)<.0006 then
|
||||
O.a,O.va=0,0
|
||||
end
|
||||
end
|
||||
|
||||
--Update texts
|
||||
if P.bonus then
|
||||
TEXT.update(P.bonus)
|
||||
end
|
||||
|
||||
--Update tasks
|
||||
local L=P.tasks
|
||||
for i=#L,1,-1 do
|
||||
local tr=L[i].thread
|
||||
assert(resume(tr))
|
||||
if status(tr)=='dead'then
|
||||
rem(L,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
local function update_alive(P,dt)
|
||||
local ENV=P.gameEnv
|
||||
local S=P.stat
|
||||
|
||||
P.frameRun=P.frameRun+1
|
||||
if P.frameRun<=180 then
|
||||
if P.frameRun==180 then
|
||||
if P.id==1 then
|
||||
SFX.play('start')
|
||||
end
|
||||
P.control=true
|
||||
P.timing=true
|
||||
P:popNext()
|
||||
elseif P.frameRun==60 or P.frameRun==120 then
|
||||
if P.id==1 then
|
||||
SFX.play('ready')
|
||||
end
|
||||
end
|
||||
if P.movDir~=0 then
|
||||
if P.moving<P.gameEnv.das then
|
||||
P.moving=P.moving+1
|
||||
end
|
||||
else
|
||||
P.moving=0
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if P.timing then
|
||||
S.time=S.time+dt
|
||||
S.frame=S.frame+1
|
||||
end
|
||||
|
||||
--Calculate key speed
|
||||
do
|
||||
local v=0
|
||||
for i=2,10 do v=v+i*(i-1)*72/(P.frameRun-P.dropTime[i])end
|
||||
P.dropSpeed=P.dropSpeed*.99+v*.01
|
||||
end
|
||||
|
||||
if GAME.modeEnv.royaleMode then
|
||||
local v=P.swappingAtkMode
|
||||
if P.keyPressing[9]then
|
||||
P.swappingAtkMode=min(v+2,30)
|
||||
else
|
||||
local tar=#P.field>15 and 4 or 8
|
||||
if v~=tar then
|
||||
P.swappingAtkMode=v+(v<tar and 1 or -1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if P.type=='computer'then
|
||||
P.bot:update(dt)
|
||||
end
|
||||
|
||||
--Fresh visible time
|
||||
if not P.keepVisible then
|
||||
local V=P.visTime
|
||||
for j=1,#P.field do
|
||||
local L=V[j]
|
||||
for i=1,10 do
|
||||
if L[i]>0 then
|
||||
L[i]=L[i]-1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Moving pressed
|
||||
if P.movDir~=0 then
|
||||
local das,arr=ENV.das,ENV.arr
|
||||
local mov=P.moving
|
||||
if P.waiting==-1 then
|
||||
if P.movDir==1 then
|
||||
if P.keyPressing[2]then
|
||||
if arr>0 then
|
||||
if mov==das+arr or mov==das then
|
||||
if not P.cur or P:ifoverlap(P.cur.bk,P.curX+1,P.curY)then
|
||||
mov=das+arr-1
|
||||
else
|
||||
P:act_moveRight(true)
|
||||
mov=das
|
||||
end
|
||||
end
|
||||
mov=mov+1
|
||||
else
|
||||
if mov==das then
|
||||
P:act_insRight(true)
|
||||
else
|
||||
mov=mov+1
|
||||
end
|
||||
end
|
||||
if mov>=das and ENV.shakeFX and P.cur and P:ifoverlap(P.cur.bk,P.curX+1,P.curY)then
|
||||
P.fieldOff.vx=.5
|
||||
end
|
||||
else
|
||||
P.movDir=0
|
||||
end
|
||||
else
|
||||
if P.keyPressing[1]then
|
||||
if arr>0 then
|
||||
if mov==das+arr or mov==das then
|
||||
if not P.cur or P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then
|
||||
mov=das+arr-1
|
||||
else
|
||||
P:act_moveLeft(true)
|
||||
mov=das
|
||||
end
|
||||
end
|
||||
mov=mov+1
|
||||
else
|
||||
if mov==das then
|
||||
P:act_insLeft(true)
|
||||
else
|
||||
mov=mov+1
|
||||
end
|
||||
end
|
||||
if mov>=das and ENV.shakeFX and P.cur and P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then
|
||||
P.fieldOff.vx=-.5
|
||||
end
|
||||
else
|
||||
P.movDir=0
|
||||
end
|
||||
end
|
||||
elseif mov<das then
|
||||
mov=mov+1
|
||||
end
|
||||
P.moving=mov
|
||||
elseif P.keyPressing[1]then
|
||||
P.movDir=-1
|
||||
P.moving=0
|
||||
elseif P.keyPressing[2]then
|
||||
P.movDir=1
|
||||
P.moving=0
|
||||
end
|
||||
|
||||
--Drop pressed
|
||||
if P.keyPressing[7]and not P.keyPressing[9]then
|
||||
P.downing=P.downing+1
|
||||
local d=P.downing-ENV.sddas
|
||||
if d>1 then
|
||||
if ENV.sdarr>0 then
|
||||
if d%ENV.sdarr==0 then
|
||||
P:act_down1()
|
||||
end
|
||||
else
|
||||
P:act_insDown()
|
||||
end
|
||||
if ENV.shakeFX then
|
||||
P.fieldOff.vy=.2
|
||||
end
|
||||
end
|
||||
else
|
||||
P.downing=0
|
||||
end
|
||||
|
||||
--Falling animation
|
||||
if P.falling>=0 then
|
||||
P.falling=P.falling-1
|
||||
if P.falling>=0 then
|
||||
goto THROW_stop
|
||||
else
|
||||
local L=#P.clearingRow
|
||||
if P.sound and ENV.fall>0 and #P.field+L>P.clearingRow[L]then
|
||||
SFX.play('fall')
|
||||
end
|
||||
P.clearingRow={}
|
||||
end
|
||||
end
|
||||
|
||||
--Update block state
|
||||
if P.control then
|
||||
--Try spawn new block
|
||||
if P.waiting>=0 then
|
||||
P.waiting=P.waiting-1
|
||||
if P.waiting<0 then
|
||||
P:popNext()
|
||||
end
|
||||
goto THROW_stop
|
||||
end
|
||||
|
||||
--Natural block falling
|
||||
if P.cur then
|
||||
if P.curY>P.ghoY then
|
||||
local D=P.dropDelay
|
||||
if D>1 then
|
||||
P.dropDelay=D-1
|
||||
goto THROW_stop
|
||||
end
|
||||
|
||||
if D==1 then
|
||||
if ENV.moveFX and ENV.block then
|
||||
P:createMoveFX('down')
|
||||
end
|
||||
P.curY=P.curY-1
|
||||
else
|
||||
D=min(1/D,P.curY-P.ghoY)--1/D=Drop dist, lowest to ghost
|
||||
if ENV.moveFX and ENV.block then
|
||||
for _=1,D do
|
||||
P:createMoveFX('down')
|
||||
P.curY=P.curY-1
|
||||
end
|
||||
else
|
||||
P.curY=P.curY-D
|
||||
end
|
||||
end
|
||||
P:freshBlock('fresh')
|
||||
P.spinLast=false
|
||||
|
||||
if P.ghoY~=P.curY then
|
||||
P.dropDelay=ENV.drop
|
||||
end
|
||||
else
|
||||
P.lockDelay=P.lockDelay-1
|
||||
if P.lockDelay>=0 then
|
||||
goto THROW_stop
|
||||
end
|
||||
P:drop(true)
|
||||
if P.bot then
|
||||
P.bot:lockWrongPlace()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
::THROW_stop::
|
||||
|
||||
--B2B bar animation
|
||||
if P.b2b1==P.b2b then
|
||||
elseif P.b2b1<P.b2b then
|
||||
P.b2b1=min(P.b2b1*.98+P.b2b*.02+.4,P.b2b)
|
||||
else
|
||||
P.b2b1=max(P.b2b1*.95+P.b2b*.05-.6,P.b2b)
|
||||
end
|
||||
|
||||
--Others
|
||||
_updateMisc(P,dt)
|
||||
-- P:setPosition(640-150-(30*(P.curX+P.cur.sc[2])-15),30*(P.curY+P.cur.sc[1])+15-300+(ENV.smooth and P.ghoY~=P.curY and(P.dropDelay/ENV.drop-1)*30 or 0))
|
||||
end
|
||||
local function update_remote_alive(P,dt)
|
||||
local frameRate=(P.stream[#P.stream-1]or 0)-P.frameRun
|
||||
frameRate=
|
||||
frameRate<26 and 1 or
|
||||
frameRate<50 and 2 or
|
||||
frameRate<80 and 3 or
|
||||
frameRate<120 and 5 or
|
||||
frameRate<160 and 7 or
|
||||
frameRate<200 and 10 or
|
||||
20
|
||||
for _=1,frameRate do
|
||||
local eventTime=P.stream[P.streamProgress]
|
||||
if eventTime then--Normal state, event forward
|
||||
if P.frameRun==eventTime then--Event time, execute action, read next so don't update immediately
|
||||
local event=P.stream[P.streamProgress+1]
|
||||
if event==0 then--Just wait
|
||||
elseif event<=32 then--Press key
|
||||
P:pressKey(event)
|
||||
elseif event<=64 then--Release key
|
||||
P:releaseKey(event-32)
|
||||
elseif event>0x2000000000000 then--Sending lines
|
||||
local sid=event%0x100
|
||||
local amount=int(event/0x100)%0x100
|
||||
local time=int(event/0x10000)%0x10000
|
||||
local line=int(event/0x100000000)%0x10000
|
||||
for _,p in next,PLY_ALIVE do
|
||||
if p.sid==sid then
|
||||
P:attack(p,amount,time,line,true)
|
||||
P:createBeam(p,amount)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif event>0x1000000000000 then--Receiving lines
|
||||
local sid=event%0x100
|
||||
for _,p in next,PLY_ALIVE do
|
||||
if p.sid==sid then
|
||||
P:receive(
|
||||
p,
|
||||
int(event/0x100)%0x100,--amount
|
||||
int(event/0x10000)%0x10000,--time
|
||||
int(event/0x100000000)%0x10000--line
|
||||
)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
P.streamProgress=P.streamProgress+2
|
||||
else--No event now, run one frame
|
||||
update.alive(P,dt/frameRate)
|
||||
P.stat.time=P.frameRun/60
|
||||
end
|
||||
else--Pause state, no actions, quit loop
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local function update_dead(P,dt)
|
||||
local S=P.stat
|
||||
|
||||
--Final average speed
|
||||
P.dropSpeed=P.dropSpeed*.96+S.piece/S.frame*144
|
||||
|
||||
if GAME.modeEnv.royaleMode then
|
||||
P.swappingAtkMode=min(P.swappingAtkMode+2,30)
|
||||
end
|
||||
|
||||
if P.falling>=0 then
|
||||
P.falling=P.falling-1
|
||||
if P.falling<0 then
|
||||
local L=#P.clearingRow
|
||||
if P.sound and P.gameEnv.fall>0 and #P.field+L>P.clearingRow[L]then
|
||||
SFX.play('fall')
|
||||
end
|
||||
P.clearingRow={}
|
||||
end
|
||||
end
|
||||
if P.b2b1>0 then
|
||||
P.b2b1=max(0,P.b2b1*.92-1)
|
||||
end
|
||||
_updateMisc(P,dt)
|
||||
end
|
||||
function Player:update(dt)
|
||||
(
|
||||
self.alive and(
|
||||
self.type=='remote'and update_remote_alive
|
||||
or update_alive
|
||||
)or update_dead
|
||||
)(self,dt)
|
||||
end
|
||||
function Player:die()--Called both when win/lose!
|
||||
self.alive=false
|
||||
self.timing=false
|
||||
self.control=false
|
||||
self.update=ply_update.dead
|
||||
self.waiting=1e99
|
||||
self.b2b=0
|
||||
self.tasks={}
|
||||
@@ -1847,9 +2304,9 @@ function Player:lose(force)
|
||||
PLY_ALIVE[1]:win()
|
||||
end
|
||||
end
|
||||
--------------------------<\Events>--------------------------
|
||||
--------------------------<\Event>--------------------------
|
||||
|
||||
--------------------------<Actions>--------------------------
|
||||
--------------------------<Action>--------------------------
|
||||
function Player:act_moveLeft(auto)
|
||||
if not auto then
|
||||
self.ctrlCount=self.ctrlCount+1
|
||||
@@ -2143,5 +2600,5 @@ Player.actList={
|
||||
Player.act_zangiLeft, --19
|
||||
Player.act_zangiRight,--20
|
||||
}
|
||||
--------------------------</Actions>--------------------------
|
||||
--------------------------</Action>--------------------------
|
||||
return Player
|
||||
|
||||
@@ -1,462 +0,0 @@
|
||||
local max,min=math.max,math.min
|
||||
local int,abs=math.floor,math.abs
|
||||
local rem=table.remove
|
||||
local assert,resume,status=assert,coroutine.resume,coroutine.status
|
||||
|
||||
local TEXT,GAME=TEXT,GAME
|
||||
local PLY_ALIVE=PLY_ALIVE
|
||||
|
||||
local function _updateMisc(P,dt)
|
||||
--Finesse combo animation
|
||||
if P.finesseComboTime>0 then
|
||||
P.finesseComboTime=P.finesseComboTime-1
|
||||
end
|
||||
|
||||
--Update spike counter
|
||||
if P.spikeTime>0 then
|
||||
P.spikeTime=P.spikeTime-1
|
||||
end
|
||||
|
||||
--Update atkBuffer alert
|
||||
local t=P.atkBufferSum1
|
||||
if t<P.atkBufferSum then
|
||||
P.atkBufferSum1=t+.25
|
||||
elseif t>P.atkBufferSum then
|
||||
P.atkBufferSum1=t-.5
|
||||
end
|
||||
|
||||
--Update attack buffer
|
||||
local bf=P.atkBuffer
|
||||
for i=#bf,1,-1 do
|
||||
local A=bf[i]
|
||||
A.time=A.time+1
|
||||
if not A.sent then
|
||||
if A.countdown>0 then
|
||||
A.countdown=max(A.countdown-P.gameEnv.garbageSpeed,0)
|
||||
end
|
||||
else
|
||||
if A.time>20 then
|
||||
rem(bf,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Push up garbages
|
||||
local y=P.fieldBeneath
|
||||
if y>0 then
|
||||
P.fieldBeneath=max(y-P.gameEnv.pushSpeed,0)
|
||||
end
|
||||
|
||||
--Move camera
|
||||
if P.gameEnv.highCam then
|
||||
if not P.alive then
|
||||
y=0
|
||||
else
|
||||
y=30*max(min(#P.field-18.5-P.fieldBeneath/30,P.ghoY-17),0)
|
||||
end
|
||||
local f=P.fieldUp
|
||||
if f~=y then
|
||||
P.fieldUp=f>y and max(f*.95+y*.05-2,y)or min(f*.97+y*.03+1,y)
|
||||
end
|
||||
end
|
||||
|
||||
--Update Score
|
||||
if P.stat.score>P.score1 then
|
||||
if P.stat.score-P.score1<10 then
|
||||
P.score1=P.score1+1
|
||||
else
|
||||
P.score1=int(min(P.score1*.9+P.stat.score*.1+1))
|
||||
end
|
||||
end
|
||||
|
||||
--Update lock FX
|
||||
for i=#P.lockFX,1,-1 do
|
||||
local S=P.lockFX[i]
|
||||
S[3]=S[3]+S[4]*dt
|
||||
if S[3]>1 then
|
||||
rem(P.lockFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Update drop FX
|
||||
for i=#P.dropFX,1,-1 do
|
||||
local S=P.dropFX[i]
|
||||
S[5]=S[5]+S[6]*dt
|
||||
if S[5]>1 then
|
||||
rem(P.dropFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Update move FX
|
||||
for i=#P.moveFX,1,-1 do
|
||||
local S=P.moveFX[i]
|
||||
S[4]=S[4]+S[5]*dt
|
||||
if S[4]>1 then
|
||||
rem(P.moveFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Update clear FX
|
||||
for i=#P.clearFX,1,-1 do
|
||||
local S=P.clearFX[i]
|
||||
S[2]=S[2]+S[3]*dt
|
||||
if S[2]>1 then
|
||||
rem(P.clearFX,i)
|
||||
end
|
||||
end
|
||||
|
||||
--Field shaking
|
||||
if P.gameEnv.shakeFX then
|
||||
local O=P.fieldOff
|
||||
O.vx=O.vx*.7-abs(O.x)^1.3*(O.x>0 and .1 or -.1)
|
||||
O.x=O.x+O.vx
|
||||
|
||||
O.vy=O.vy*.7-abs(O.y)^1.2*(O.y>0 and .1 or -.1)
|
||||
O.y=O.y+O.vy
|
||||
|
||||
O.va=O.va*.7-abs(O.a)^1.4*(O.a>0 and .08 or -.08)
|
||||
O.a=O.a+O.va
|
||||
if abs(O.a)<.0006 then
|
||||
O.a,O.va=0,0
|
||||
end
|
||||
end
|
||||
|
||||
--Update texts
|
||||
if P.bonus then
|
||||
TEXT.update(P.bonus)
|
||||
end
|
||||
|
||||
--Update tasks
|
||||
local L=P.tasks
|
||||
for i=#L,1,-1 do
|
||||
local tr=L[i].thread
|
||||
assert(resume(tr))
|
||||
if status(tr)=='dead'then
|
||||
rem(L,i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local update={
|
||||
}
|
||||
function update.alive(P,dt)
|
||||
local ENV=P.gameEnv
|
||||
local S=P.stat
|
||||
|
||||
P.frameRun=P.frameRun+1
|
||||
if P.frameRun<=180 then
|
||||
if P.frameRun==180 then
|
||||
if P.id==1 then
|
||||
SFX.play('start')
|
||||
end
|
||||
P.control=true
|
||||
P.timing=true
|
||||
P:popNext()
|
||||
elseif P.frameRun==60 or P.frameRun==120 then
|
||||
if P.id==1 then
|
||||
SFX.play('ready')
|
||||
end
|
||||
end
|
||||
if P.movDir~=0 then
|
||||
if P.moving<P.gameEnv.das then
|
||||
P.moving=P.moving+1
|
||||
end
|
||||
else
|
||||
P.moving=0
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
if P.timing then
|
||||
S.time=S.time+dt
|
||||
S.frame=S.frame+1
|
||||
end
|
||||
|
||||
--Calculate key speed
|
||||
do
|
||||
local v=0
|
||||
for i=2,10 do v=v+i*(i-1)*72/(P.frameRun-P.dropTime[i])end
|
||||
P.dropSpeed=P.dropSpeed*.99+v*.01
|
||||
end
|
||||
|
||||
if GAME.modeEnv.royaleMode then
|
||||
local v=P.swappingAtkMode
|
||||
if P.keyPressing[9]then
|
||||
P.swappingAtkMode=min(v+2,30)
|
||||
else
|
||||
local tar=#P.field>15 and 4 or 8
|
||||
if v~=tar then
|
||||
P.swappingAtkMode=v+(v<tar and 1 or -1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if P.type=='computer'then
|
||||
P.bot:update(dt)
|
||||
end
|
||||
|
||||
--Fresh visible time
|
||||
if not P.keepVisible then
|
||||
local V=P.visTime
|
||||
for j=1,#P.field do
|
||||
local L=V[j]
|
||||
for i=1,10 do
|
||||
if L[i]>0 then
|
||||
L[i]=L[i]-1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Moving pressed
|
||||
if P.movDir~=0 then
|
||||
local das,arr=ENV.das,ENV.arr
|
||||
local mov=P.moving
|
||||
if P.waiting==-1 then
|
||||
if P.movDir==1 then
|
||||
if P.keyPressing[2]then
|
||||
if arr>0 then
|
||||
if mov==das+arr or mov==das then
|
||||
if not P.cur or P:ifoverlap(P.cur.bk,P.curX+1,P.curY)then
|
||||
mov=das+arr-1
|
||||
else
|
||||
P:act_moveRight(true)
|
||||
mov=das
|
||||
end
|
||||
end
|
||||
mov=mov+1
|
||||
else
|
||||
if mov==das then
|
||||
P:act_insRight(true)
|
||||
else
|
||||
mov=mov+1
|
||||
end
|
||||
end
|
||||
if mov>=das and ENV.shakeFX and P.cur and P:ifoverlap(P.cur.bk,P.curX+1,P.curY)then
|
||||
P.fieldOff.vx=.5
|
||||
end
|
||||
else
|
||||
P.movDir=0
|
||||
end
|
||||
else
|
||||
if P.keyPressing[1]then
|
||||
if arr>0 then
|
||||
if mov==das+arr or mov==das then
|
||||
if not P.cur or P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then
|
||||
mov=das+arr-1
|
||||
else
|
||||
P:act_moveLeft(true)
|
||||
mov=das
|
||||
end
|
||||
end
|
||||
mov=mov+1
|
||||
else
|
||||
if mov==das then
|
||||
P:act_insLeft(true)
|
||||
else
|
||||
mov=mov+1
|
||||
end
|
||||
end
|
||||
if mov>=das and ENV.shakeFX and P.cur and P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then
|
||||
P.fieldOff.vx=-.5
|
||||
end
|
||||
else
|
||||
P.movDir=0
|
||||
end
|
||||
end
|
||||
elseif mov<das then
|
||||
mov=mov+1
|
||||
end
|
||||
P.moving=mov
|
||||
elseif P.keyPressing[1]then
|
||||
P.movDir=-1
|
||||
P.moving=0
|
||||
elseif P.keyPressing[2]then
|
||||
P.movDir=1
|
||||
P.moving=0
|
||||
end
|
||||
|
||||
--Drop pressed
|
||||
if P.keyPressing[7]and not P.keyPressing[9]then
|
||||
P.downing=P.downing+1
|
||||
local d=P.downing-ENV.sddas
|
||||
if d>1 then
|
||||
if ENV.sdarr>0 then
|
||||
if d%ENV.sdarr==0 then
|
||||
P:act_down1()
|
||||
end
|
||||
else
|
||||
P:act_insDown()
|
||||
end
|
||||
if ENV.shakeFX then
|
||||
P.fieldOff.vy=.2
|
||||
end
|
||||
end
|
||||
else
|
||||
P.downing=0
|
||||
end
|
||||
|
||||
--Falling animation
|
||||
if P.falling>=0 then
|
||||
P.falling=P.falling-1
|
||||
if P.falling>=0 then
|
||||
goto THROW_stop
|
||||
else
|
||||
local L=#P.clearingRow
|
||||
if P.sound and ENV.fall>0 and #P.field+L>P.clearingRow[L]then
|
||||
SFX.play('fall')
|
||||
end
|
||||
P.clearingRow={}
|
||||
end
|
||||
end
|
||||
|
||||
--Update block state
|
||||
if P.control then
|
||||
--Try spawn new block
|
||||
if P.waiting>=0 then
|
||||
P.waiting=P.waiting-1
|
||||
if P.waiting<0 then
|
||||
P:popNext()
|
||||
end
|
||||
goto THROW_stop
|
||||
end
|
||||
|
||||
--Natural block falling
|
||||
if P.cur then
|
||||
if P.curY>P.ghoY then
|
||||
local D=P.dropDelay
|
||||
if D>1 then
|
||||
P.dropDelay=D-1
|
||||
goto THROW_stop
|
||||
end
|
||||
|
||||
if D==1 then
|
||||
if ENV.moveFX and ENV.block then
|
||||
P:createMoveFX('down')
|
||||
end
|
||||
P.curY=P.curY-1
|
||||
else
|
||||
D=min(1/D,P.curY-P.ghoY)--1/D=Drop dist, lowest to ghost
|
||||
if ENV.moveFX and ENV.block then
|
||||
for _=1,D do
|
||||
P:createMoveFX('down')
|
||||
P.curY=P.curY-1
|
||||
end
|
||||
else
|
||||
P.curY=P.curY-D
|
||||
end
|
||||
end
|
||||
P:freshBlock('fresh')
|
||||
P.spinLast=false
|
||||
|
||||
if P.ghoY~=P.curY then
|
||||
P.dropDelay=ENV.drop
|
||||
end
|
||||
else
|
||||
P.lockDelay=P.lockDelay-1
|
||||
if P.lockDelay>=0 then
|
||||
goto THROW_stop
|
||||
end
|
||||
P:drop(true)
|
||||
if P.bot then
|
||||
P.bot:lockWrongPlace()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
::THROW_stop::
|
||||
|
||||
--B2B bar animation
|
||||
if P.b2b1==P.b2b then
|
||||
elseif P.b2b1<P.b2b then
|
||||
P.b2b1=min(P.b2b1*.98+P.b2b*.02+.4,P.b2b)
|
||||
else
|
||||
P.b2b1=max(P.b2b1*.95+P.b2b*.05-.6,P.b2b)
|
||||
end
|
||||
|
||||
--Others
|
||||
_updateMisc(P,dt)
|
||||
-- P:setPosition(640-150-(30*(P.curX+P.cur.sc[2])-15),30*(P.curY+P.cur.sc[1])+15-300+(ENV.smooth and P.ghoY~=P.curY and(P.dropDelay/ENV.drop-1)*30 or 0))
|
||||
end
|
||||
function update.dead(P,dt)
|
||||
local S=P.stat
|
||||
|
||||
--Final average speed
|
||||
P.dropSpeed=P.dropSpeed*.96+S.piece/S.frame*144
|
||||
|
||||
if GAME.modeEnv.royaleMode then
|
||||
P.swappingAtkMode=min(P.swappingAtkMode+2,30)
|
||||
end
|
||||
|
||||
if P.falling>=0 then
|
||||
P.falling=P.falling-1
|
||||
if P.falling<0 then
|
||||
local L=#P.clearingRow
|
||||
if P.sound and P.gameEnv.fall>0 and #P.field+L>P.clearingRow[L]then
|
||||
SFX.play('fall')
|
||||
end
|
||||
P.clearingRow={}
|
||||
end
|
||||
end
|
||||
if P.b2b1>0 then
|
||||
P.b2b1=max(0,P.b2b1*.92-1)
|
||||
end
|
||||
_updateMisc(P,dt)
|
||||
end
|
||||
function update.remote_alive(P,dt)
|
||||
local frameRate=(P.stream[#P.stream-1]or 0)-P.frameRun
|
||||
frameRate=
|
||||
frameRate<26 and 1 or
|
||||
frameRate<50 and 2 or
|
||||
frameRate<80 and 3 or
|
||||
frameRate<120 and 5 or
|
||||
frameRate<160 and 7 or
|
||||
frameRate<200 and 10 or
|
||||
20
|
||||
for _=1,frameRate do
|
||||
local eventTime=P.stream[P.streamProgress]
|
||||
if eventTime then--Normal state, event forward
|
||||
if P.frameRun==eventTime then--Event time, execute action, read next so don't update immediately
|
||||
local event=P.stream[P.streamProgress+1]
|
||||
if event==0 then--Just wait
|
||||
elseif event<=32 then--Press key
|
||||
P:pressKey(event)
|
||||
elseif event<=64 then--Release key
|
||||
P:releaseKey(event-32)
|
||||
elseif event>0x2000000000000 then--Sending lines
|
||||
local sid=event%0x100
|
||||
local amount=int(event/0x100)%0x100
|
||||
local time=int(event/0x10000)%0x10000
|
||||
local line=int(event/0x100000000)%0x10000
|
||||
for _,p in next,PLY_ALIVE do
|
||||
if p.sid==sid then
|
||||
P:attack(p,amount,time,line,true)
|
||||
P:createBeam(p,amount)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif event>0x1000000000000 then--Receiving lines
|
||||
local sid=event%0x100
|
||||
for _,p in next,PLY_ALIVE do
|
||||
if p.sid==sid then
|
||||
P:receive(
|
||||
p,
|
||||
int(event/0x100)%0x100,--amount
|
||||
int(event/0x10000)%0x10000,--time
|
||||
int(event/0x100000000)%0x10000--line
|
||||
)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
P.streamProgress=P.streamProgress+2
|
||||
else--No event now, run one frame
|
||||
update.alive(P,dt/frameRate)
|
||||
P.stat.time=P.frameRun/60
|
||||
end
|
||||
else--Pause state, no actions, quit loop
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return update
|
||||
Reference in New Issue
Block a user