Files
Techmino/parts/player/draw.lua
2024-10-30 00:14:28 +08:00

1136 lines
36 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local gc=love.graphics
local gc_push,gc_pop,gc_clear,gc_origin=gc.push,gc.pop,gc.clear,gc.origin
local gc_translate,gc_scale,gc_rotate=gc.translate,gc.scale,gc.rotate
local gc_setCanvas,gc_setShader=gc.setCanvas,gc.setShader
local gc_draw,gc_line,gc_rectangle=gc.draw,gc.line,gc.rectangle
local gc_print,gc_printf=gc.print,gc.printf
local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth
local gc_stencil,gc_setStencilTest=gc.stencil,gc.setStencilTest
local floor,ceil,rnd=math.floor,math.ceil,math.random
local max,min,sin,modf=math.max,math.min,math.sin,math.modf
local setFont=FONT.set
local SKIN,TEXTURE,IMG=SKIN,TEXTURE,IMG
local TEXT,COLOR,TIME=TEXT,COLOR,TIME
local shader_alpha,shader_lighter=SHADER.alpha,SHADER.lighter
local shader_fieldSatur,shader_blockSatur=SHADER.fieldSatur,SHADER.blockSatur
local TEXTOBJ,ENUM_MISSION,BLOCK_COLORS=TEXTOBJ,ENUM_MISSION,BLOCK_COLORS
local RCPB={10,33,200,33,105,5,105,60}
local attackColor={
{COLOR.dH,COLOR.Z},
{COLOR.H,COLOR.Z},
{COLOR.lV,COLOR.Z},
{COLOR.lR,COLOR.Z},
{COLOR.dG,COLOR.C},
}
local hideBoardStencil={
up=function() gc_rectangle('fill',0,-600,300,300,6) end,
down=function() gc_rectangle('fill',0,-300,300,300,6) end,
all=function() gc_rectangle('fill',0,-600,300,600,6) end,
}
local dialNeedle=TEXTURE.dial.needle
local multiple=TEXTURE.multiple
local playerborder=TEXTURE.playerBorder
local gridLines=TEXTURE.gridLines
local seqGenBanner=setmetatable({
none=GC.DO{1,1},
bag=GC.DO{100,10,
{'fRect',35,2,-2,6},
{'fRect',40,4,20,2},
{'fRect',65,2,2,6},
},
bagES=GC.DO{100,10,
{'fRect',35,2,-2,6},
{'fRect',40,4,20,2},
{'fRect',65,2,2,6},
{'fCirc',40,5,3},
},
his=GC.DO{100,10,
{'fRect',15,3,2,7},
{'fRect',20,3,2,7},
{'fRect',25,3,2,7},
{'fRect',30,3,2,7},
},
hisPool=GC.DO{100,10,
{'fRect',15,3,2,7},
{'fRect',20,3,2,7},
{'fRect',25,3,2,7},
{'fRect',30,3,2,7},
{'fRect',60,5,25,2},
},
c2=GC.DO{100,10,
{'fRect',20-1,5-1,2,2},
{'fRect',30-2,5-2,4,4},
{'fRect',40-1,5-1,2,2},
{'fRect',50-2,5-2,4,4},
{'fRect',60-1,5-1,2,2},
{'fRect',70-2,5-2,4,4},
{'fRect',80-1,5-1,2,2},
},
bagP1inf=GC.DO{100,10,
{'fRect',10,4,40,2},
{'fRect',55,4,20,2},
{'fRect',80,4,10,2},
},
rnd=GC.DO{100,10,
{'fRect',30-3,1,6,6},
{'fRect',70-3,1,6,6},
},
mess=GC.DO{100,10,
{'setLW',2},
{'dRect',30-3,1,6,6},
{'dRect',70-3,1,6,6},
},
reverb=GC.DO{100,10,
{'fRect',25,1,30,2},
{'fRect',20,4,60,2},
{'fRect',45,7,30,2},
},
loop=GC.DO{100,10,
{'fRect',25,4,20,2},
{'fRect',55,4,20,2},
},
fixed=GC.DO{100,10,
{'fRect',40,4,20,2},
},
},{__index=function(self,k)
self[k]=self.none
return self.none
end})
local LDmarks=gc.newSpriteBatch(GC.DO{14,5,{'fRect',0,0,14,5,3}},15,'static')
for i=0,14 do LDmarks:add(3+20*i,615) end
local function _boardTransform(mode)
if mode then
if mode=="U-D" then
gc_translate(0,590)
gc_scale(1,-1)
elseif mode=="L-R" then
gc_translate(300,0)
gc_scale(-1,1)
elseif mode=="180" then
gc_translate(300,590)
gc_scale(-1,-1)
end
end
end
local function _stencilBoard() gc_rectangle('fill',0,-10,300,610) end
local function _applyField(P)
gc_push('transform')
-- Apply shaking
if P.shakeTimer>0 then
local dx=floor(P.shakeTimer/2)
local dy=floor(P.shakeTimer/3)
gc_translate(dx^1.6*(dx%2*2-1)*(P.gameEnv.shakeFX+1)/30,dy^1.4*(dy%2*2-1)*(P.gameEnv.shakeFX+1)/30)
end
-- Apply swingOffset
local O=P.swingOffset
if P.gameEnv.shakeFX then
local k=P.gameEnv.shakeFX
gc_translate(O.x*k+150+150,O.y*k+300)
gc_rotate(O.a*k)
gc_translate(-150,-300)
else
gc_translate(150,0)
end
-- Apply stencil
gc_stencil(_stencilBoard)
gc_setStencilTest('equal',1)
-- Move camera
gc_push('transform')
_boardTransform(P.gameEnv.flipBoard)
gc_translate(0,P.fieldBeneath+P.fieldUp)
end
local function _cancelField()
gc_setStencilTest()
gc_pop()
gc_pop()
end
local function _drawRow(texture,h,V,L,showInvis)
local t=TIME()*4
for i=1,10 do
if L[i]>0 then
if V[i]>0 then
gc_setColor(1,1,1,V[i]*.05)
gc_draw(texture[L[i]],30*i-30,-30*h)
elseif showInvis then
gc_setColor(1,1,1,.3+.08*sin(.5*(h-i)+t))
gc_rectangle('fill',30*i-30,-30*h,30,30)
end
end
end
end
local function _drawField(P,showInvis)
local ENV=P.gameEnv
local V,F=P.visTime,P.field
local start=floor((P.fieldBeneath+P.fieldUp)/30+1)
local texture=P.skinLib
if P.falling==0 then-- Blocks only
if ENV.upEdge then
gc_setShader(shader_lighter)
gc_translate(0,-6)
-- <drawRow>
for j=start,min(start+21,#F) do _drawRow(texture,j,V[j],F[j]) end
-- </drawRow>
gc_setShader(shader_fieldSatur)
gc_translate(0,6)
else
gc_setShader(shader_fieldSatur)
end
-- <drawRow>
for j=start,min(start+21,#F) do _drawRow(texture,j,V[j],F[j],showInvis) end
-- </drawRow>
else-- With falling animation
local stepY=ENV.smooth and (P.falling/(ENV.fall+1))^1.6*30 or 30
local alpha=P.falling/ENV.fall
local h=1
if ENV.upEdge then
gc_push('transform')
gc_setShader(shader_lighter)
gc_translate(0,-6)
-- <drawRow>
for j=start,min(start+21,#F) do
while j==P.clearingRow[h] do
h=h+1
gc_translate(0,-stepY)
end
_drawRow(texture,j,V[j],F[j])
end
-- </drawRow>
gc_setShader(shader_fieldSatur)
gc_pop()
h=1
else
gc_setShader(shader_fieldSatur)
end
gc_push('transform')
-- <drawRow>
for j=start,min(start+21,#F) do
while j==P.clearingRow[h] do
h=h+1
gc_translate(0,-stepY)
gc_setColor(1,1,1,alpha)
gc_rectangle('fill',0,30-30*j,300,stepY)
end
_drawRow(texture,j,V[j],F[j],showInvis)
end
-- </drawRow>
gc_pop()
end
gc_setShader()
end
local function _drawFXs(P)
-- LockFX
for i=1,#P.lockFX do
local S=P.lockFX[i]
if S[3]<.5 then
gc_setColor(1,1,1,2*S[3])
gc_rectangle('fill',S[1],S[2],60*S[3],30)
else
gc_setColor(1,1,1,2-2*S[3])
gc_rectangle('fill',S[1]+30,S[2],60*S[3]-60,30)
end
end
-- DropFX
for i=1,#P.dropFX do
local S=P.dropFX[i]
gc_setColor(1,1,1,.6-S[5]*.6)
local w=30*S[3]*(1-S[5]*.5)
gc_rectangle('fill',30*S[1]-30+15*S[3]-w*.5,-30*S[2],w,30*S[4])
end
-- MoveFX
local texture=P.skinLib
for i=1,#P.moveFX do
local S=P.moveFX[i]
gc_setColor(1,1,1,.6-S[4]*.6)
gc_draw(texture[S[1]],30*S[2]-30,-30*S[3])
end
-- ClearFX
for i=1,#P.clearFX do
local S=P.clearFX[i]
local t=S[2]
local x=t<.3 and 1-(3.3333*t-1)^2 or 1
local y=t<.2 and 5*t or 1-1.25*(t-.2)
gc_setColor(1,1,1,y)
gc_rectangle('fill',150-x*150,15-S[1]*30-y*15,300*x,y*30)
end
end
local drawGhost={
color=function(CB,curX,ghoY,alpha,texture,clr)
gc_setColor(1,1,1,alpha)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_draw(texture[clr],30*(j+curX-1)-30,-30*(i+ghoY-1))
end
end end
end,
gray=function(CB,curX,ghoY,alpha,texture,_)
gc_setColor(1,1,1,alpha)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_draw(texture[21],30*(j+curX-1)-30,-30*(i+ghoY-1))
end
end end
end,
colorCell=function(CB,curX,ghoY,alpha,_,clr)
clr=BLOCK_COLORS[clr]
gc_setColor(clr[1],clr[2],clr[3],alpha)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_rectangle('fill',30*(j+curX-1)-30,-30*(i+ghoY-1),30,30)
end
end end
end,
grayCell=function(CB,curX,ghoY,alpha,_,_)
gc_setColor(1,1,1,alpha)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_rectangle('fill',30*(j+curX-1)-30,-30*(i+ghoY-1),30,30)
end
end end
end,
colorLine=function(CB,curX,ghoY,alpha,_,clr)
clr=BLOCK_COLORS[clr]
gc_setColor(clr[1],clr[2],clr[3],alpha)
gc_setLineWidth(4)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_rectangle('line',30*(j+curX-1)-30+4,-30*(i+ghoY-1)+4,22,22)
end
end end
end,
grayLine=function(CB,curX,ghoY,alpha,_,_)
gc_setColor(1,1,1,alpha)
gc_setLineWidth(4)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_rectangle('line',30*(j+curX-1)-30+4,-30*(i+ghoY-1)+4,22,22)
end
end end
end,
}
local function _drawBlockOutline(CB,curX,curY,texture,trans)
shader_alpha:send('a',trans)
gc_setShader(shader_alpha)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
local x=30*(j+curX)-60-3
local y=30-30*(i+curY)-3
gc_draw(texture,x,y)
gc_draw(texture,x+6,y+6)
gc_draw(texture,x+6,y)
gc_draw(texture,x,y+6)
end
end end
gc_setShader()
end
local function _drawBlockShade(CB,curX,curY,alpha)
gc_setColor(1,1,1,alpha)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_rectangle('fill',30*(j+curX)-60,30-30*(i+curY),30,30)
end
end end
end
local function _drawBlock(CB,curX,curY,texture)
gc_setColor(1,1,1)
gc_setShader(shader_blockSatur)
for i=1,#CB do for j=1,#CB[1] do
if CB[i][j] then
gc_draw(texture,30*(j+curX-1)-30,-30*(i+curY-1))
end
end end
gc_setShader()
end
local function _drawNextPreview(B,x,y)
gc_setColor(1,1,1,.8)
B=B.bk
local cross=TEXTURE.puzzleMark[-1]
for i=1,#B do for j=1,#B[1] do
if B[i][j] then
gc_draw(cross,30*(x+j-2),30*(1-y-i))
end
end end
end
local function _drawHoldPreview(B,x,y)
gc_setColor(1,1,1,.3)
y=y+.14
B=B.bk
local cross=TEXTURE.puzzleMark[-1]
for i=1,#B do for j=1,#B[1] do
if B[i][j] then
gc_draw(cross,30*(x+j-2),30*(1-y-i))
end
end end
end
local function _drawBuffer(atkBuffer,bufferWarn,atkBufferSum1,atkBufferSum)
local h=0
for i=1,#atkBuffer do
local A=atkBuffer[i]
local bar=A.amount*30
if h+bar>600 then bar=600-h end
if not A.sent then
if A.time<20 then
-- Appear
bar=bar*(20*A.time)^.5*.05
end
if A.countdown>0 then
-- Timing
gc_setColor(attackColor[A.lv][1])
gc_rectangle('fill',303,600-h-bar,11,bar,2)
gc_setColor(1,1,1)
for j=30,A.cd0-30,30 do
gc_rectangle('fill',303,600-h-bar*(j/A.cd0),6,2)
end
gc_setColor(attackColor[A.lv][2])
gc_rectangle('fill',303,600-h-bar,11,bar*(1-A.countdown/A.cd0),2)
else
-- Warning
local a=math.sin((TIME()-i)*30)*.5+.5
local c1,c2=attackColor[A.lv][1],attackColor[A.lv][2]
gc_setColor(c1[1]*a+c2[1]*(1-a),c1[2]*a+c2[2]*(1-a),c1[3]*a+c2[3]*(1-a))
gc_rectangle('fill',303,600-h-bar,11,bar,2)
end
else
-- Disappear
gc_setColor(attackColor[A.lv][1])
bar=bar*(20-A.time)*.05
gc_rectangle('fill',303,600-h-bar,11,bar,2)
end
h=h+bar
if h>=600 then break end
end
if bufferWarn then
local sum=atkBufferSum1
if sum>=8 then
gc_push('transform')
gc_translate(300,max(0,600-30*sum))
gc_scale(min(.2+sum/50,1))
gc_setColor(1,.2+min(sum*.02,.8)*(.5+.5*sin(TIME()*min(sum,32))),.2,min(sum/30,.8))
setFont(100)
if sum>20 then
local d=atkBufferSum-sum
if d>.5 then
gc_translate(d^.5*(rnd()-.5)*15,d^.5*(rnd()-.5)*15)
end
end
gc_printf(floor(sum),-300,-20,292,'right')
gc_pop()
end
end
end
local function _drawB2Bbar(b2b,b2b1)
local a,b=b2b,b2b1
if a>b then a,b=b,a end
if b>0 then
gc_setColor(.8,1,.2)
gc_rectangle('fill',-14,600-b*.6,11,b*.6,2)
gc_setColor(b2b<50 and COLOR.Z or b2b<=800 and COLOR.lR or COLOR.lB)
gc_rectangle('fill',-14,600-a*.6,11,a*.6,2)
if TIME()%.5<.3 then
gc_setColor(1,1,1)
gc_rectangle('fill',-15,b<50 and 570 or 120,13,3,2)
end
end
end
local function _drawLDI(easyFresh,length,freshTime)-- Lock Delay Indicator
if easyFresh then
gc_setColor(.97,.97,.97)
else
gc_setColor(1,.5,.5)
end
if length>=0 then
gc_rectangle('fill',0,602,300*length,4)
end
if freshTime>0 then
LDmarks:setDrawRange(1,min(freshTime,15))
gc_draw(LDmarks)
end
end
local function _drawHold(holdQueue,holdCount,holdTime,skinLib)
local N=holdCount*72
gc_push('transform')
gc_translate(12,20)
gc_setLineWidth(2)
gc_setColor(0,0,0,.4)gc_rectangle('fill',0,0,100,N+8,5)
gc_setColor(.97,.97,.97)gc_rectangle('line',0,0,100,N+8,5)
N=#holdQueue<holdCount and holdQueue[1] and 1 or holdTime+1
gc_push('transform')
gc_translate(50,40)
gc_setLineWidth(8)
gc_setColor(1,1,1)
gc_setShader(shader_blockSatur)
for n=1,#holdQueue do
if n==N then gc_setColor(.7,.5,.5) end
local bk,clr=holdQueue[n].bk,holdQueue[n].color
local texture=skinLib[clr]
local k=min(2.3/#bk,3/#bk[1],.85)
gc_scale(k)
for i=1,#bk do for j=1,#bk[1] do
if bk[i][j] then
gc_draw(texture,30*(j-#bk[1]*.5)-30,-30*(i-#bk*.5))
end
end end
gc_scale(1/k)
gc_translate(0,72)
end
gc_setShader()
gc_pop()
gc_pop()
end
local function _drawNext(P,repMode)
local ENV=P.gameEnv
local texture=P.skinLib
gc_translate(488,20)
gc_setLineWidth(2)
local h=ENV.nextCount*72
gc_setColor(ENV.nextStartPos>1 and .5 or 0,0,0,.4)
gc_rectangle('fill',0,0,100,h+8,5)
gc_setColor(1,1,1,.626)
gc_draw(seqGenBanner[ENV.sequence],0,-11)
gc_setColor(.97,.97,.97)
if ENV.holdMode=='swap' then
gc_rectangle('fill',100,72*ENV.holdCount+2,-50,4)
elseif ENV.holdMode=='skip' then
gc_setColor(.97,.97,.97,.26)
gc_rectangle('fill',100,72*P.holdTime+2,-50,4)
gc_setColor(.97,.97,.97)
gc_rectangle('fill',100,72*ENV.holdCount+2,-50,4)
end
gc_rectangle('line',0,0,100,h+8,5)
gc_push('transform')
gc_translate(50,40)
-- Draw nexts
gc_setLineWidth(6)
gc_setColor(1,1,1,.2)
gc_setShader(shader_blockSatur)
local hiding
if ENV.holdMode=='swap' then
gc_setColor(.7,.5,.5)
hiding=true
else
gc_setColor(1,1,1)
end
local queue=P.nextQueue
local N=1
while N<=ENV.nextCount and queue[N] do
if hiding and N>ENV.holdCount-P.holdTime then
gc_setColor(1,1,1)
hiding=false
end
local bk,sprite=queue[N].bk,texture[queue[N].color]
local k=min(2.3/#bk,3/#bk[1],.85)
gc_scale(k)
for i=1,#bk do for j=1,#bk[1] do
if bk[i][j] then
gc_draw(sprite,30*(j-#bk[1]*.5)-30,-30*(i-#bk*.5))
end
end end
gc_scale(1/k)
gc_translate(0,72)
N=N+1
end
gc_setShader()
-- Draw more nexts
if repMode then
gc_translate(50,-28)
local blockImg=TEXTURE.miniBlock
local n=N
while n<=10 and queue[n] do
local id=queue[n].id
local _=BLOCK_COLORS[queue[n].color]
gc_setColor(_[1],_[2],_[3],.26)
_=blockImg[id]
gc_draw(_,-_:getWidth()*10,0,nil,10,nil)
gc_translate(0,10*_:getHeight()+3)
n=n+1
end
end
gc_pop()
local c=min(ENV.nextStartPos-1,P.pieceCount)
if c>0 then
gc_setColor(.3,.3,.3,repMode and .8 or 1)
gc_rectangle('fill',1,1,98,c*72+4,4)
end
if ENV.bagLine then
gc_setColor(.8,.8,.8,.8)
for i=1,ENV.nextCount+1 do
if queue[i] and queue[i].bagLine and queue[i].bagLine>0 then
gc_rectangle('fill',1,72*(i-1)+3,98,2)
end
end
end
gc_translate(-488,-20)
end
local _drawDial do
local function _getDialBackColor(speed)
if speed<60 then return COLOR.H
elseif speed<120 then return COLOR.Z
elseif speed<180 then return COLOR.lC
elseif speed<240 then return COLOR.lG
elseif speed<300 then return COLOR.lY
elseif speed<420 then return COLOR.O
else return COLOR.R
end
end
local function _getDialColor(speed)
if speed<60 then return COLOR.Z
elseif speed<120 then return COLOR.lC
elseif speed<180 then return COLOR.lG
elseif speed<240 then return COLOR.lY
elseif speed<300 then return COLOR.O
else return COLOR.R
end
end
function _drawDial(x,y,speed)
local theta=3*math.pi/2+((math.pi*(speed<300 and speed or 150+speed/2)/30)%MATH.tau)
gc_setColor(0,0,0,.4)
gc.circle('fill',x+40,y+40,36)
gc_setColor(1,1,1)
gc_draw(dialNeedle,x+40,y+40,theta,nil,nil,1,1)
gc_setLineWidth(3)
gc_setColor(_getDialBackColor(speed))
gc.circle('line',x+40,y+40,37)
gc_setColor(_getDialColor(speed))
if speed<420 then
gc.arc('line','open',x+40,y+40,37,3*math.pi/2,theta)
else
gc.circle('line',x+40,y+40,37)
end
setFont(30)GC.mStr(floor(speed),x+40,y+19)
end
end
local function _drawFinesseCombo_norm(P)
if P.finesseCombo>2 then
local S=P.stat
local t=P.finesseComboTime
local str=P.finesseCombo.."x"
if S.finesseRate==5*S.piece then
gc_setColor(.9,.9,.3,t*.2)
gc_print(str,20,570)
gc_setColor(.9,.9,.3,1.2-t*.1)
elseif S.maxFinesseCombo==S.piece then
gc_setColor(.7,.7,1,t*.2)
gc_print(str,20,570)
gc_setColor(.7,.7,1,1.2-t*.1)
else
gc_setColor(1,1,1,t*.2)
gc_print(str,20,570)
gc_setColor(1,1,1,1.2-t*.1)
end
gc_print(str,20,600,nil,1+t*.08,nil,0,30)
end
end
local function _drawFinesseCombo_remote(P)
if P.finesseCombo>2 then
local S=P.stat
if S.finesseRate==5*S.piece then
gc_setColor(.9,.9,.3)
elseif S.maxFinesseCombo==S.piece then
gc_setColor(.7,.7,1)
else
gc_setColor(.97,.97,.97)
end
gc_print(P.finesseCombo.."x",20,570)
end
end
local function _drawLife(life)
gc_setColor(.97,.97,.97)
gc_draw(IMG.lifeIcon,475,595,nil,.8)
if life>3 then
gc_draw(multiple,502,602)
setFont(20)gc_print(life,517,595)
else
if life>1 then gc_draw(IMG.lifeIcon,500,595,nil,.8) end
if life>2 then gc_draw(IMG.lifeIcon,525,595,nil,.8) end
end
end
local function _drawMission(curMission,L,missionkill)
if curMission~=prevMissionNum or not TABLE.compare(L,prevL) then
prevMissionNum=curMission
prevL=TABLE.copy(L)
RLEMissions=TABLE.RLE(TABLE.sub(L,curMission))
end
-- Draw current mission
if missionkill then
gc_setColor(1,.7+.2*sin(TIME()*6.26),.4)
else
gc_setColor(.97,.97,.97)
end
gc_push()
if RLEMissions[1][2]>1 then
setFont(20)
gc_print("×"..RLEMissions[1][2],98,130)
gc_translate(-30,0)
end
setFont(35)
gc_print(ENUM_MISSION[RLEMissions[1][1]],85,110)
-- Draw next mission
for i=2,4 do
local m=RLEMissions[i]
if m then
local amt=m[2]
m=ENUM_MISSION[m[1]]
if RLEMissions[i][2]>1 then
setFont(14)
gc_print("×"..amt,118-28*i,127)
gc_translate(-18,0)
end
setFont(20)
gc_print(m,115-28*i,117)
else
break
end
end
gc_pop()
end
local function _drawStartCounter(time)
time=179-time
gc_push('transform')
gc_translate(300,300)
local r,g,b
local num=floor(time/60)+1
local d=time%60
if num==3 then
r,g,b=.7,.8,.98
if d>45 then gc_rotate((d-45)^2*.00355) end
elseif num==2 then
r,g,b=.98,.85,.75
if d>45 then gc_scale(1+(d/15-3)^2,1) end
elseif num==1 then
r,g,b=1,.7,.7
if d>45 then gc_scale(1,1+(d/15-3)^2) end
end
setFont(100)
gc_setColor(r,g,b,d/60)
gc_push('transform')
gc_scale((1.5-d/60*.6)^1.5)
GC.mStr(num,0,-70)
gc_pop()
gc_setColor(r,g,b)
gc_scale(min(d/20,1)^.4)
GC.mStr(num,0,-70)
gc_pop()
end
local draw={}
draw.drawGhost=drawGhost
draw.applyField=_applyField
draw.cancelField=_cancelField
function draw.drawTargetLine(P,h,overrideColor)
if h<=20+(P.fieldBeneath+P.fieldUp+10)/30 and h>0 then
gc_setLineWidth(3)
if not overrideColor then
gc_setColor(1,h>10 and 0 or .2+.8*rnd(),.5)
end
_applyField(P)
h=600-30*h
if P.falling~=-1 then
h=h-#P.clearingRow*(P.gameEnv.smooth and (P.falling/(P.gameEnv.fall+1))^1.6*30 or 30)
end
gc_line(0,h,300,h)
_cancelField()
end
end
function draw.drawMarkLine(P,h,r,g,b,a)
if h<=20+(P.fieldBeneath+P.fieldUp+10)/30 and h>0 then
gc_setLineWidth(4)
gc_setColor(r,g,b,a)
_applyField(P)
h=600-30*h
gc_line(0,h,300,h)
_cancelField()
end
end
function draw.drawProgress(s1,s2)
setFont(40)
GC.mStr(s1,62,322)
GC.mStr(s2,62,376)
gc_rectangle('fill',15,375,90,4,2)
end
function draw.norm(P,repMode)
local ENV=P.gameEnv
local FBN,FUP=P.fieldBeneath,P.fieldUp
local camDY=FBN+FUP
local t=TIME()
gc_push('transform')
gc_translate(P.x,P.y)
gc_scale(P.size)
-- Draw username
setFont(30)
gc_setColor(GROUP_COLORS[P.group])
GC.mStr(P.username or USERS.getUsername(P.uid),300,-60)
-- Draw HUD
if ENV.nextCount>0 then _drawNext(P,repMode) end
if ENV.holdMode=='hold' and ENV.holdCount>0 then _drawHold(P.holdQueue,ENV.holdCount,P.holdTime,P.skinLib) end
if P.curMission then _drawMission(P.curMission,ENV.mission,ENV.missionKill) end
_drawDial(499,505,P.dropSpeed)
if P.life>0 then _drawLife(P.life) end
-- Field-related things
_applyField(P)
-- Fill field
gc_setColor(0,0,0,.6)
gc_rectangle('fill',0,-10-camDY,300,610)
-- Draw grid
if ENV.grid then
gc_setColor(1,1,1,ENV.grid)
gc_draw(gridLines,0,-40-(camDY-camDY%30))
end
gc_translate(0,600)
local fieldTop=-ENV.fieldH*30
-- Draw dangerous area
if fieldTop-camDY<610 then
gc_setColor(1,0,0,.26)
gc_rectangle('fill',0,fieldTop,300,-10-camDY-(600-fieldTop))
end
-- Draw field
_drawField(P,repMode)
-- Draw line number
if ENV.lineNum then
setFont(20)
local dy=camDY<900 and 0 or camDY-camDY%300-600
for i=1,3 do
local num=10+10*i+dy/30
local y=-325-300*i-dy
gc_setColor(0,0,0,ENV.lineNum)
gc.print(num,1,y)
gc.print(num,2,y+1)
gc_setColor(.97,.97,.97,ENV.lineNum)
gc.print(num,2,y)
gc.print(num,2,y)
end
end
-- Draw spawn line
gc_setLineWidth(4)
gc_setColor(1,sin(t)*.4+.5,0,.5)
gc_rectangle('fill',0,fieldTop,300,4)
-- Draw height limit line
gc_setColor(.4,.7+sin(t*12)*.3,1,.7)
gc_rectangle('fill',0,-ENV.heightLimit*30-FBN-2,300,4)
-- Draw FXs
_drawFXs(P)
-- Draw current block
if P.alive and P.control and P.cur then
local C=P.cur
local curColor=C.color
local trans=P.lockDelay/ENV.lock
local centerPos=C.RS.centerPos[C.id][C.dir]
local centerX=30*(P.curX+centerPos[2])-20
-- Draw ghost & rotation center
local centerDisp=ENV.center and C.RS.centerDisp[C.id]
if ENV.ghost then
drawGhost[ENV.ghostType](P.cur.bk,P.curX,P.ghoY,ENV.ghost,P.skinLib,curColor)
if centerDisp then
gc_setColor(1,1,1,ENV.center)
gc_draw(C.RS.centerTex,centerX,-30*(P.ghoY+centerPos[1])+10)
end
elseif repMode then
drawGhost.grayCell(P.cur.bk,P.curX,P.ghoY,.15,nil,nil)
end
local dy=ENV.smooth and P.ghoY~=P.curY and (P.dropDelay/ENV.drop-1)*30 or 0
gc_translate(0,-dy)
-- Draw block & rotation center
if ENV.block then
_drawBlockOutline(P.cur.bk,P.curX,P.curY,P.skinLib[curColor],trans)
_drawBlock(P.cur.bk,P.curX,P.curY,P.skinLib[curColor])
if centerDisp then
gc_setColor(1,1,1,ENV.center)
gc_draw(C.RS.centerTex,centerX,-30*(P.curY+centerPos[1])+10)
end
elseif repMode then
_drawBlockShade(P.cur.bk,P.curX,P.curY,trans*.3)
end
gc_translate(0,dy)
end
-- Draw next preview
if ENV.nextPos then
if P.nextQueue[1] then _drawNextPreview(P.nextQueue[1],P:getSpawnX(P.nextQueue[1]),P:getSpawnY(P.nextQueue[1])) end
if P.holdQueue[1] then _drawHoldPreview(P.holdQueue[1],P:getSpawnX(P.holdQueue[1]),P:getSpawnY(P.holdQueue[1])) end
end
-- Draw AI's drop destination
if P.destFX then
local L=P.destFX
local texture=TEXTURE.puzzleMark[21]
for i=1,#L,2 do
gc_draw(texture,30*L[i],-30*L[i+1]-30)
end
end
-- Board cover
if ENV.hideBoard then
gc_stencil(hideBoardStencil[ENV.hideBoard])
gc_setStencilTest('equal',1)
local alpha
if repMode then
gc_setLineWidth(18.8)
alpha=.7
else
gc_setLineWidth(20)
alpha=1
end
for i=0,24 do
local l=.32+.05*sin(i*.26+t*.2)
gc_setColor(l,l,l,alpha)
gc_line(20*i-190,-602,20*i+10,2)
end
end
gc_translate(0,-600)
gc_setStencilTest()
gc_pop()
-- Draw Frame and buffers
gc_setColor(P.frameColor)
gc_draw(playerborder,-17,-12)
_drawBuffer(P.atkBuffer,ENV.bufferWarn,P.atkBufferSum1,P.atkBufferSum)
_drawB2Bbar(P.b2b,P.b2b1)
_drawLDI(ENV.easyFresh,P.lockDelay/ENV.lock,P.freshTime)
-- Draw target selecting pad
if ENV.layout=='royale' then
if P.atkMode then
gc_setColor(1,.8,0,min(P.swappingAtkMode,30)*.02)
gc_rectangle('fill',RCPB[2*P.atkMode-1],RCPB[2*P.atkMode],90,35,8,4)
end
gc_setColor(1,1,1,min(P.swappingAtkMode,30)*.025)
setFont(35)
gc_setLineWidth(1)
for i=1,4 do
gc_rectangle('line',RCPB[2*i-1],RCPB[2*i],90,35,8,4)
gc_printf(text.atkModeName[i],RCPB[2*i-1]-4,RCPB[2*i]+4,200,"center",nil,.5)
end
end
-- Spike
local sp,spt=P.spike,P.spikeTime
if ENV.showSpike and spt>0 and sp>=10 then
local rg=10/sp
gc_setColor(rg,rg,1,min(spt/30,.8))
local x,y=150,100
if spt>85 then
local d=2*(spt-85)*min(sp/50,1)
x,y=x+(rnd()-.5)*d,y+(rnd()-.5)*d
end
mDraw(P.spikeText,x,y,nil,min(.3+(sp/26)*.4+spt/100*.3,1))
end
-- Bonus texts
TEXT.draw(P.bonus)
-- Display Ys
-- gc_setLineWidth(6)
-- if P.curY then gc_setColor(COLOR.R)gc_line(0,611-P.curY*30,300,610-P.curY*30) end
-- if P.ghoY then gc_setColor(COLOR.G)gc_line(0,615-P.ghoY*30,300,615-P.ghoY*30) end
-- if P.minY then gc_setColor(COLOR.B)gc_line(0,619-P.minY*30,300,620-P.minY*30) end
-- gc_line(0,600-P.garbageBeneath*30,300,600-P.garbageBeneath*30)
gc_pop()
-- Score & Time
setFont(25)
local tm=STRING.time(P.stat.time)
gc_setColor(0,0,0,.3)
gc_print(ceil(P.score1),18,509)
gc_print(tm,18,539)
gc_setColor(.97,.97,.92)
gc_print(ceil(P.score1),20,510)
gc_setColor(.85,.9,.97)
gc_print(tm,20,540)
-- FinesseCombo
;(P.type=='remote' and _drawFinesseCombo_remote or _drawFinesseCombo_norm)(P)
-- Mode informations
for i=1,#ENV.mesDisp do
gc_setColor(.97,.97,.97)
ENV.mesDisp[i](P,repMode)
end
-- Torikan miss amount
if P.result=='torikan' then
local diff=P.stat.time-P.stat.torikanReq
if diff>=60 then gc_setColor(COLOR.R)
elseif diff>=30 then gc_setColor(COLOR.F)
elseif diff>=15 then gc_setColor(COLOR.O)
elseif diff>=10 then gc_setColor(COLOR.Y)
elseif diff>=5 then gc_setColor(COLOR.flicker(COLOR.G,COLOR.L,.1))
else gc_setColor(COLOR.flicker(COLOR.G,COLOR.J,.05)) end
setFont(40)
-- self:_showText(STRING.time(self.stat.time).." / "..STRING.time(requiredTime),0,160,50,'beat',.5,.2)
GC.mStr(STRING.time(P.stat.time).." / "..STRING.time(P.stat.torikanReq),300,401)
GC.mStr("(+"..STRING.time_short(diff)..")",300,451)
end
if P.frameRun<180 then
_drawStartCounter(P.frameRun)
end
gc_pop()
end
function draw.small(P)
-- Update canvas
P.frameWait=P.frameWait-1
if P.frameWait==0 then
P.frameWait=10
gc_setCanvas(P.canvas)
gc_clear(0,0,0,.4)
gc_push('transform')
gc_origin()
gc_setColor(1,1,1,P.result and max(20-P.endCounter,0)*.05 or 1)
-- Field
local F=P.field
local texture=SKIN.libMini[SETTING.skinSet]
for j=1,#F do
for i=1,10 do if F[j][i]>0 then
gc_draw(texture[F[j][i]],6*i-6,120-6*j)
end end
end
-- Draw border
if P.alive then
gc_setLineWidth(2)
gc_setColor(P.frameColor)
gc_rectangle('line',0,0,60,120)
end
-- Draw badge
if P.gameEnv.layout=='royale' then
gc_setColor(1,1,1)
for i=1,P.strength do
gc_draw(IMG.badgeIcon,12*i-7,4,nil,.5)
end
end
-- Draw result
if P.result then
gc_setColor(1,1,1,min(P.endCounter,60)*.01)
setFont(20)mDraw(TEXTOBJ[P.result],30,60,nil,P.size)
setFont(15)GC.mStr(P.modeData.place,30,82)
end
gc_pop()
gc_setCanvas()
end
-- Draw Canvas
gc_setColor(1,1,1)
local size=P.size
gc_draw(P.canvas,P.x,P.y,nil,size*10)
if P.killMark then
gc_setColor(1,0,0)
gc_rectangle('fill',P.x+40*size,P.y+40*size,160*size,160*size)
end
end
function draw.demo(P)
local ENV=P.gameEnv
-- Camera
gc_push('transform')
gc_translate(P.x,P.y)
gc_scale(P.size)
gc_translate(-150,0)
_applyField(P)
gc_setStencilTest()
gc_setColor(0,0,0,.6)
gc_rectangle('fill',0,0,300,600,3)
gc_push('transform')
gc_translate(0,600)
_drawField(P)
_drawFXs(P)
if P.alive and P.cur then
local curColor=P.cur.color
if ENV.ghost then
drawGhost[ENV.ghostType](P.cur.bk,P.curX,P.ghoY,ENV.ghost,P.skinLib,curColor)
end
if ENV.block then
local dy=ENV.smooth and P.ghoY~=P.curY and (P.dropDelay/ENV.drop-1)*30 or 0
gc_translate(0,-dy)
_drawBlockOutline(P.cur.bk,P.curX,P.curY,P.skinLib[curColor],P.lockDelay/ENV.lock)
_drawBlock(P.cur.bk,P.curX,P.curY,P.skinLib[curColor])
gc_translate(0,dy)
end
end
gc_pop()
local blockImg=TEXTURE.miniBlock
local skinSet=ENV.skin
-- Draw hold
local N=1
while ENV.holdMode=='hold' and N<=ENV.holdCount and P.holdQueue[N] do
local id=P.holdQueue[N].id
local _=BLOCK_COLORS[skinSet[id]]
gc_setColor(_[1],_[2],_[3],.3)
_=blockImg[id]
gc_draw(_,15,40*N-10,nil,8,nil,0,_:getHeight()*.5)
N=N+1
end
-- Draw next
N=1
while N<=ENV.nextCount and P.nextQueue[N] do
local id=P.nextQueue[N].id
local _=BLOCK_COLORS[skinSet[id]]
gc_setColor(_[1],_[2],_[3],.3)
_=blockImg[id]
gc_draw(_,285,40*N-10,nil,8,nil,_:getWidth(),_:getHeight()*.5)
N=N+1
end
-- Frame
gc_setLineWidth(2)
gc_setColor(COLOR.Z)
gc_rectangle('line',-1,-1,302,602,3)
gc_pop()
gc_pop()
gc_translate(150,0)
TEXT.draw(P.bonus)
gc_pop()
end
return draw