390 lines
10 KiB
Lua
390 lines
10 KiB
Lua
local gc=love.graphics
|
|
local setFont,mStr=FONT.set,GC.mStr
|
|
|
|
local int,rnd=math.floor,math.random
|
|
local ins,rem=table.insert,table.remove
|
|
|
|
local targets={
|
|
[40]=true,
|
|
[100]=true,
|
|
[200]=true,
|
|
[400]=true,
|
|
[620]=true,
|
|
[1000]=true,
|
|
[2600]=true,
|
|
}
|
|
|
|
local state,progress
|
|
local startTime,time
|
|
local keyTime
|
|
local speed,maxSpeed
|
|
local arcade,rollSpeed
|
|
|
|
local reset=error--function, defined later
|
|
|
|
local bgm="secret7th"
|
|
local tileColor="black"
|
|
local mode="Normal"
|
|
local modeSelector=WIDGET.newSelector{name='mode',x=150,y=220,w=290,
|
|
list={
|
|
"Normal",
|
|
"Split",
|
|
"Short",
|
|
"Stairs",
|
|
"Double",
|
|
"Singlestream",
|
|
"Light_Jumpstream",
|
|
"Dense_Jumpstream",
|
|
"Light_Handstream",
|
|
"Dense_Handstream",
|
|
"Light_Quadstream",
|
|
"Quadstream",
|
|
},disp=function()return mode end,code=function(m)mode=m reset()end
|
|
}
|
|
local bgmSelector=WIDGET.newSelector{name='bgm',x=150,y=290,w=290,list=BGM.getList(),disp=function()return bgm end,code=function(i)bgm=i BGM.play(i)end}
|
|
local colorSelector=WIDGET.newSelector{name='color',x=150,y=360,w=290,
|
|
list={"black","dGray","gray","lGray","dRed","red","lRed","dFire","fire","lFire","dOrange","orange","lOrange","dYellow","yellow","lYellow","dLime","lime","lLime","dJade","jade","lJade","dGreen","green","lGreen","dAqua","aqua","lAqua","dCyan","cyan","lCyan","dNavy","navy","lNavy","dSea","sea","lSea","dBlue","blue","lBlue","dViolet","violet","lViolet","dPurple","purple","lPurple","dMagenta","magenta","lMagenta","dWine","wine","lWine"},
|
|
disp=function()return tileColor end,code=function(m)tileColor=m end
|
|
}
|
|
local arcadeSwitch=WIDGET.newSwitch{name='arcade',x=240,y=430,lim=200,font=40,disp=function()return arcade end,code=pressKey'e'}
|
|
local function freshSelectors()
|
|
local f=state~=0
|
|
modeSelector.hide=f
|
|
bgmSelector.hide=f
|
|
colorSelector.hide=f
|
|
arcadeSwitch.hide=f
|
|
end
|
|
|
|
local score
|
|
local pos,height
|
|
local diePos
|
|
|
|
local function get1(prev)
|
|
if prev<10 or prev>999 then
|
|
local r=rnd(3)
|
|
return r>=prev and r+1 or r
|
|
else
|
|
while true do
|
|
local r=rnd(4)
|
|
if not string.find(prev,r)then return r end
|
|
end
|
|
end
|
|
end
|
|
local function get2(prev)
|
|
while true do
|
|
local i=rnd(4)
|
|
local r=rnd(3)
|
|
if r>=i then r=r+1 end
|
|
if not(string.find(prev,r)or string.find(prev,i))then
|
|
return 10*i+r
|
|
end
|
|
end
|
|
end
|
|
local function get3(prev)
|
|
if prev==0 then prev=rnd(4)end
|
|
if prev==1 then return 234
|
|
elseif prev==2 then return 134
|
|
elseif prev==3 then return 124
|
|
elseif prev==4 then return 123
|
|
else error("wrong get3 usage: "..(prev or -1))
|
|
end
|
|
end
|
|
|
|
local generator={
|
|
Normal=function()
|
|
ins(pos,rnd(4))
|
|
end,
|
|
Split=function()
|
|
if #pos==0 then ins(pos,rnd(4))end
|
|
ins(pos,pos[#pos]<=2 and rnd(3,4)or rnd(2))
|
|
end,
|
|
Short=function()
|
|
if #pos<2 then ins(pos,rnd(4))ins(pos,rnd(4))end
|
|
local r
|
|
if pos[#pos]==pos[#pos-1]then
|
|
r=rnd(3)
|
|
if r>=pos[#pos]then r=r+1 end
|
|
ins(pos,r)
|
|
else
|
|
ins(pos,rnd(4))
|
|
end
|
|
end,
|
|
Stairs=function()
|
|
local r=get1(pos[#pos]or 0)
|
|
local dir=r==1 and 1 or r==4 and -1 or rnd()<.5 and 1 or -1
|
|
local count=rnd(3,5)
|
|
while count>0 do
|
|
ins(pos,r)
|
|
r=r+dir
|
|
if r==0 then
|
|
r,dir=2,1
|
|
elseif r==5 then
|
|
r,dir=3,-1
|
|
end
|
|
count=count-1
|
|
end
|
|
end,
|
|
Double=function()
|
|
local i=rnd(4)
|
|
local r=rnd(3)
|
|
if r>=i then r=r+1 end
|
|
r=10*i+r
|
|
ins(pos,r)
|
|
end,
|
|
Singlestream=function()
|
|
ins(pos,get1(pos[#pos]or 0))
|
|
end,
|
|
Light_Jumpstream=function()--2111
|
|
ins(pos,get2(pos[#pos]or 0))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
end,
|
|
Dense_Jumpstream=function()--2121
|
|
ins(pos,get2(pos[#pos]or 0))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get2(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
end,
|
|
Light_Handstream=function()--3111
|
|
ins(pos,get3(pos[#pos]or 0))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
end,
|
|
Dense_Handstream=function()--3121
|
|
ins(pos,get3(pos[#pos]or 0))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get2(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
end,
|
|
Light_Quadstream=function()--4111
|
|
ins(pos,1234)
|
|
ins(pos,get1(pos[#pos-1]or 0))
|
|
ins(pos,get1(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
end,
|
|
Quadstream=function()--4121
|
|
ins(pos,1234)
|
|
ins(pos,get1(pos[#pos-1]or 0))
|
|
ins(pos,get2(pos[#pos]))
|
|
ins(pos,get1(pos[#pos]))
|
|
end,
|
|
}
|
|
|
|
function reset()
|
|
keyTime={}for i=1,40 do keyTime[i]=-1e99 end
|
|
speed,maxSpeed=0,0
|
|
progress={}
|
|
state=0
|
|
freshSelectors()
|
|
time=0
|
|
score=0
|
|
|
|
local t=love.system.getClipboardText()
|
|
if type(t)=='string'then
|
|
t=t:lower():match("^s=(.+)")
|
|
t=t and tonumber(t)and tonumber(t)*2
|
|
t=t and tonumber(t)>=0 and tonumber(t)<=60 and t
|
|
end
|
|
rollSpeed=type(t)=='number'and t or 6.26
|
|
|
|
pos={}
|
|
while #pos<7 do generator[mode]()end
|
|
height=0
|
|
diePos=false
|
|
end
|
|
|
|
local scene={}
|
|
|
|
function scene.sceneInit()
|
|
reset()
|
|
BG.set('gray')
|
|
BGM.play(bgm)
|
|
end
|
|
|
|
local function touch(n)
|
|
if state==0 then
|
|
state=1
|
|
freshSelectors()
|
|
startTime=TIME()
|
|
end
|
|
local t=tostring(pos[1])
|
|
local p=string.find(t,n)
|
|
if p then
|
|
t=t:sub(1,p-1)..t:sub(p+1)
|
|
if #t>0 then
|
|
pos[1]=tonumber(t)
|
|
SFX.play('lock')
|
|
else
|
|
rem(pos,1)
|
|
while #pos<7 do generator[mode]()end
|
|
ins(keyTime,1,TIME())
|
|
keyTime[21]=nil
|
|
score=score+1
|
|
if not arcade and targets[score]then
|
|
ins(progress,("%s - %.3fs"):format(score,TIME()-startTime))
|
|
if score==2600 then
|
|
for i=1,#pos do
|
|
pos[i]=626
|
|
end
|
|
time=TIME()-startTime
|
|
state=2
|
|
SFX.play('win')
|
|
else
|
|
SFX.play('reach',.5)
|
|
end
|
|
end
|
|
height=height+120
|
|
SFX.play('lock')
|
|
end
|
|
else
|
|
time=TIME()-startTime
|
|
state=2
|
|
diePos=n
|
|
SFX.play('clear_2')
|
|
end
|
|
end
|
|
function scene.keyDown(key,isRep)
|
|
if isRep then return end
|
|
if key=='r'or key=='space'then reset()
|
|
elseif key=='escape'then SCN.back()
|
|
elseif state~=2 then
|
|
if key=='d'or key=='c'then touch(1)
|
|
elseif key=='f'or key=='v'then touch(2)
|
|
elseif key=='j'or key=='n'then touch(3)
|
|
elseif key=='k'or key=='m'then touch(4)
|
|
elseif state==0 then
|
|
if key=='tab'then
|
|
local mode1=mode
|
|
modeSelector:scroll(love.keyboard.isDown('lshift','rshift')and -1 or 1)
|
|
if mode1~=mode then reset()end
|
|
elseif key=='q'then
|
|
bgmSelector:scroll(love.keyboard.isDown('lshift','rshift')and -1 or 1)
|
|
elseif key=='w'then
|
|
colorSelector:scroll(love.keyboard.isDown('lshift','rshift')and -1 or 1)
|
|
elseif key=='e'then
|
|
arcade=not arcade
|
|
end
|
|
end
|
|
end
|
|
end
|
|
function scene.mouseDown(x)
|
|
scene.touchDown(x)
|
|
end
|
|
function scene.touchDown(x)
|
|
if state==2 then return end
|
|
x=int((x-300)/170+1)
|
|
if x>=1 and x<=4 then
|
|
touch(x)
|
|
end
|
|
end
|
|
|
|
function scene.update()
|
|
if state==1 then
|
|
local t=TIME()
|
|
time=t-startTime
|
|
local v=0
|
|
for i=2,20 do v=v+i*(i-1)*.3/(t-keyTime[i])end
|
|
speed=speed*.99+v*.01
|
|
if speed>maxSpeed then maxSpeed=speed end
|
|
|
|
if arcade then
|
|
height=height-rollSpeed
|
|
rollSpeed=rollSpeed+.00355
|
|
if height<-120 then
|
|
state=2
|
|
SFX.play('clear_2')
|
|
end
|
|
else
|
|
height=height*.6
|
|
end
|
|
end
|
|
end
|
|
|
|
local function boardStencil()gc.rectangle('fill',300,0,680,720)end
|
|
function scene.draw()
|
|
setFont(50)
|
|
if arcade then
|
|
--Draw rolling speed
|
|
mStr(("%.2f/s"):format(rollSpeed/2),155,490)
|
|
else
|
|
--Draw speed
|
|
setFont(45)
|
|
gc.setColor(1,.6,.6)
|
|
mStr(("%.2f"):format(maxSpeed/60),155,460)
|
|
gc.setColor(COLOR.Z)
|
|
mStr(("%.2f"):format(speed/60),155,520)
|
|
|
|
--Progress time list
|
|
setFont(30)
|
|
gc.setColor(.6,.6,.6)
|
|
for i=1,#progress do
|
|
gc.print(progress[i],1030,120+25*i)
|
|
end
|
|
|
|
--Draw time
|
|
gc.setColor(COLOR.Z)
|
|
setFont(45)
|
|
gc.print(("%.3f"):format(time),1030,70)
|
|
end
|
|
|
|
--Draw mode
|
|
if state~=0 then
|
|
gc.setColor(COLOR.Z)
|
|
setFont(30)mStr(mode,155,212)
|
|
end
|
|
|
|
--Draw tiles
|
|
gc.stencil(boardStencil)
|
|
gc.setStencilTest('equal',1)
|
|
gc.rectangle('fill',300,0,680,720)
|
|
gc.setColor(COLOR[tileColor])
|
|
gc.push('transform')
|
|
gc.translate(0,720-height+8)
|
|
for i=1,7 do
|
|
local t=pos[i]
|
|
while t>0 do
|
|
gc.rectangle('fill',130+170*(t%10)+8,-i*120,170-16,120-16)
|
|
t=(t-t%10)/10
|
|
end
|
|
end
|
|
gc.pop()
|
|
gc.setStencilTest()
|
|
--Draw track line
|
|
gc.setColor(COLOR.D)
|
|
gc.setLineWidth(2)
|
|
for x=1,5 do
|
|
x=130+170*x
|
|
gc.line(x,0,x,720)
|
|
end
|
|
for y=0,6 do
|
|
y=720-120*y-height%120
|
|
gc.line(300,y,980,y)
|
|
end
|
|
|
|
--Draw red tile
|
|
if diePos then
|
|
gc.setColor(1,.2,.2)
|
|
gc.rectangle('fill',130+170*diePos+8,600-height+8,170-16,120-16)
|
|
end
|
|
|
|
--Draw score
|
|
setFont(100)
|
|
gc.push('transform')
|
|
gc.translate(640,26)
|
|
gc.scale(1.6)
|
|
gc.setColor(.5,.5,.5,.6)
|
|
mStr(score,0,0)
|
|
gc.pop()
|
|
end
|
|
|
|
scene.widgetList={
|
|
WIDGET.newButton{name='reset',x=155,y=100,w=180,h=100,color='lG',font=50,fText=CHAR.icon.retry_spin,code=pressKey'r'},
|
|
modeSelector,bgmSelector,colorSelector,
|
|
arcadeSwitch,
|
|
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,font=60,sound='back',fText=CHAR.icon.back,code=backScene},
|
|
}
|
|
|
|
return scene
|