Compare commits

...

2 Commits

Author SHA1 Message Date
MrZ_26
f62613638e 0.190721α 2020-02-04 19:24:00 +08:00
MrZ_26
a9cf691247 0.190719α 2020-02-04 19:23:19 +08:00
8 changed files with 571 additions and 398 deletions

Binary file not shown.

6
ai.lua
View File

@@ -74,10 +74,10 @@ function getScore(field,cb,cx,cy)
end
end
return
-highest*10
-rough*10
-highest*5
-rough*15
-cy*15
+clear^1.5*15
+clear^2*3
-hole*20
end
--controlname:mL,mR,rR,rL,rF,hD,sD,H,LL,RR

View File

@@ -9,20 +9,25 @@ Buttons={
{x=500,y=540,w=320,h=60,rgb={.5,.5,.5},alpha=0,t="Quit",code=function()gotoScene("quit")end},
},
mode={
{x=350,y=200,w=220,h=70,rgb={1,1,1},alpha=0,t="Marathon",code=function()startGame("marathon")end},
{x=350,y=300,w=220,h=70,rgb={1,1,1},alpha=0,t="40 Lines",code=function()startGame("sprint")end},
{x=650,y=200,w=220,h=70,rgb={1,1,1},alpha=0,t="Zen",code=function()startGame("zen")end},
{x=650,y=300,w=220,h=70,rgb={1,1,1},alpha=0,t="Battle",code=function()startGame("battle")end},
{x=200,y=150,w=250,h=70,rgb={1,1,1},alpha=0,t="40 Lines",code=function()startGame("sprint")end},
{x=500,y=150,w=250,h=70,rgb={1,1,1},alpha=0,t="Zen",code=function()startGame("zen")end},
{x=800,y=150,w=250,h=70,rgb={1,1,1},alpha=0,t="GM Roll",code=function()startGame("gmroll")end},
{x=200,y=250,w=250,h=70,rgb={1,1,1},alpha=0,t="Marathon",code=function()startGame("marathon")end},
{x=200,y=350,w=250,h=70,rgb={1,1,1},alpha=0,t="Death",code=function()startGame("death")end},
{x=500,y=250,w=250,h=70,rgb={1,1,1},alpha=0,t="Tetris 25",code=function()startGame("tetris25")end},
{x=500,y=350,w=250,h=70,rgb={1,1,1},alpha=0,t="AI Solo",code=function()startGame("solo")end},
{x=800,y=250,w=250,h=70,rgb={1,1,1},alpha=0,t="Blind",code=function()startGame("blind")end},
{x=800,y=350,w=250,h=70,rgb={1,1,1},alpha=0,t="Asymmetry Solo",code=function()startGame("asymsolo")end},
{x=500,y=520,w=350,h=80,rgb={1,1,1},alpha=0,t="Back",code=function()gotoScene("main")end},
},
play={
{x=950,y=30,w=80,h=40,rgb={1,1,1},alpha=0,t="Back",code=function()gotoScene("mode")end},
},
setting={
{x=120,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="-",code=function()setting.das=(setting.das-1)%41 end,hold=true},
{x=280,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="+",code=function()setting.das=(setting.das+1)%41 end,hold=true},
{x=320,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="-",code=function()setting.arr=(setting.arr-1)%21 end,hold=true},
{x=480,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="+",code=function()setting.arr=(setting.arr+1)%21 end,hold=true},
{x=120,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="-",code=function()setting.das=(setting.das-1)%31 end,hold=true},
{x=280,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="+",code=function()setting.das=(setting.das+1)%31 end,hold=true},
{x=320,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="-",code=function()setting.arr=(setting.arr-1)%16 end,hold=true},
{x=480,y=80,w=30,h=30,rgb={1,1,1},alpha=0,t="+",code=function()setting.arr=(setting.arr+1)%16 end,hold=true},
{x=200,y=200,w=190,h=40,rgb={1,1,1},alpha=0,t=function()return setting.ghost and"Ghost ON"or"Ghost OFF"end,code=function()setting.ghost=not setting.ghost end},
{x=400,y=200,w=190,h=40,rgb={1,1,1},alpha=0,t=function()return setting.center and"Center ON"or"Center OFF"end,code=function()setting.center=not setting.center end},
@@ -53,8 +58,9 @@ Buttons={
{x=350,y=320,w=210,h=43,rgb={1,1,1},alpha=0,t=function()return setting.key[6]end,code=function()keysetting=6 end},
{x=350,y=370,w=210,h=43,rgb={1,1,1},alpha=0,t=function()return setting.key[7]end,code=function()keysetting=7 end},
{x=350,y=420,w=210,h=43,rgb={1,1,1},alpha=0,t=function()return setting.key[8]end,code=function()keysetting=8 end},
{x=320,y=500,w=130,h=43,rgb={1,1,1},alpha=0,t="Reset",code=function()setting.key={"left","right","x","z","c","up","down","space","LEFT","RIGHT"}end},
{x=500,y=500,w=100,h=50,rgb={1,1,1},alpha=0,t="Back",code=function()back()end},
{x=350,y=470,w=210,h=43,rgb={1,1,1},alpha=0,t=function()return setting.key[9]end,code=function()keysetting=9 end},
{x=320,y=550,w=130,h=43,rgb={1,1,1},alpha=0,t="Reset",code=function()setting.key={"left","right","x","z","c","up","down","space","r","LEFT","RIGHT"}end},
{x=500,y=550,w=100,h=50,rgb={1,1,1},alpha=0,t="Back",code=function()back()end},
},
help={
{x=500,y=500,w=200,h=60,rgb={1,1,1},alpha=0,t="Back",code=function()back()end},

716
main.lua
View File

@@ -132,38 +132,43 @@ FX={
gc.setColor(1,1,1,min((30-abs(t.t-30))*.05,1)*(#field>9 and .7 or 1))
mStr(t.text,150,250-t.font*.5+t.dy)
end,
fly=function(t)
setFont(t.font)
gc.setColor(1,1,1,min((30-abs(t.t-30))*.05,1)*(#field>9 and .7 or 1))
mStr(t.text,150+(t.t-15)^3*.005,250-t.font*.5+t.dy)
end,
stretch=function(t)
gc.push("transform")
setFont(t.font)
gc.translate(150,250)
gc.translate(150,250+t.dy)
gc.setColor(1,1,1,min((30-abs(t.t-30))*.1,1)*(#field>9 and .7 or 1))
if t.t<20 then gc.scale((20-t.t)*.015+1,1)end
mStr(t.text,0,-t.font*.5+t.dy)
mStr(t.text,0,-t.font*.5)
gc.pop()
end,
drive=function(t)
gc.push("transform")
setFont(t.font)
gc.translate(150,290)
gc.translate(150,290+t.dy)
gc.setColor(1,1,1,min((30-abs(t.t-30))*.1,1)*(#field>9 and .7 or 1))
if t.t<20 then gc.shear((20-t.t)*.03,0)end
mStr(t.text,0,-t.font*.5+t.dy)
if t.t<20 then gc.shear((20-t.t)*.05,0)end
mStr(t.text,0,-t.font*.5)
gc.pop()
end,
spin=function(t)
gc.push("transform")
setFont(t.font)
gc.translate(150,250)
gc.translate(150,250+t.dy)
gc.setColor(1,1,1,min((30-abs(t.t-30))*.1,1)*(#field>9 and .7 or 1))
if t.t<20 then
gc.scale((20-t.t)*.01+1,(20-t.t)*.015+1)
gc.rotate((20-t.t)^2*.0015)
end
mStr(t.text,0,-t.font*.5+t.dy)
mStr(t.text,0,-t.font*.5)
gc.pop()
end,
flicker=function(t)
setFont(t.font)
gc.setColor(1,1,1,min((30-abs(t.t-30))*.05,1)*(#field>9 and .7 or 1)*(rnd()+.5))
gc.setColor(1,1,1,min((30-abs(t.t-30))*.05,1)*(#field>9 and .8 or 1)*(rnd()+.5))
mStr(t.text,150,250-t.font*.5+t.dy)
end,
}
@@ -172,16 +177,17 @@ function stencil_field()
end
--System data
list={
blockName={"Z","S","L","J","T","O","I"},
clearname={"Single","Double","Triple"},
reason={[0]="Escape","Block out","Lock out","Finished","Top out"},
method={"Bag7","His4","Rnd"},
}
actName={"moveLeft","moveRight","rotRight","rotLeft","rotFlip","hardDrop","softDrop","hold","toLeft","toRight"}
actName_={"move left","move right","rotate right","rotate left","rotate flip","hard drop","soft drop","hold","toLeft","toRight"}
name={"Z","S","L","J","T","O","I"}
actName={"moveLeft","moveRight","rotRight","rotLeft","rotFlip","hardDrop","softDrop","hold","restart","toLeft","toRight"}
actName_={"move left","move right","rotate right","rotate left","rotate flip","hard drop","soft drop","hold","restart","toLeft","toRight"}
blockPos={4,4,4,4,4,5,4}
renATK={[0]=0,0,0,1,1,1,2,2,2,3,3,3}
require"SRS"
b2bATK={3,5,8}
require"SRS"--load bolck&SRS data
gameEnv0={
das=6,arr=1,
ghost=true,center=true,
@@ -190,9 +196,11 @@ gameEnv0={
next=6,hold=true,
sequence=1,visible=1,
_20G=false,target=9e99,
freshLimit=9e99,
color={1,5,2,8,10,3,7,13},
key={"left","right","x","z","c","up","down","space","LEFT","RIGHT"},
reach=function()end
spinList={true,true,true,true,true,false,false},
reach=function()end,--Called when reach row target
}
randomMethod={
function()
@@ -226,18 +234,6 @@ randomMethod={
end,
}
loadmode={
marathon=function()
modeEnv={
drop=60,
wait=1,
fall=20,
target=10,
reach=Event.marathon_reach,
}
createPlayer(1,190,20,.8)
curBG="game1"
BGM("way")
end,
sprint=function()
modeEnv={
wait=1,
@@ -262,51 +258,182 @@ loadmode={
curBG="game1"
BGM("reason")
end,
gm=function()
gmroll=function()
modeEnv={
drop=0,
lock=15,
wait=10,
fall=15,
_20G=true,
visible=0,
freshLimit=15,
arr=1,
}
createPlayer(1,190,20,.8)
curBG="game3"
BGM("push")
end,
marathon=function()
modeEnv={
drop=60,
wait=10,
fall=5,
target=100,
reach=Event.gm_reach,
wait=1,
fall=20,
target=10,
reach=Event.marathon_reach,
freshLimit=15,
}
createPlayer(1,190,20,.8)
curBG="game1"
BGM("way")
end,
death=function()
modeEnv={
_20G=true,
drop=0,
lock=10,
wait=6,
fall=10,
target=50,
reach=Event.death_reach,
freshLimit=15,
arr=1,
}
createPlayer(1,190,20,.8)
curBG="game2"
BGM("push")
end,
battle=function()
tetris25=function()
modeEnv={
wait=1,
fall=1,
}
createPlayer(1,240,30,.8)--Player
-- createPlayer(2,580,25,.38,true)
-- createPlayer(3,580,315,.38,true)
--Triple
-- createPlayer(2,580,140,.6,true)
--Solo
local n=2
for i=1,3 do
for j=1,7 do
createPlayer(n,75*i-65,80*j-55,.1,true)
for i=1,2 do
for j=1,5 do
createPlayer(n,100*i-65,110*j-75,.15,rnd(4)+1)
n=n+1
end
end
for i=11,13 do
for j=1,7 do
createPlayer(n,75*i-65,80*j-55,.1,true)
for i=9,10 do
for j=1,5 do
createPlayer(n,100*i-130,110*j-75,.14,rnd(4)+1)
n=n+1
end
end
end--AIs
curBG="game2"
BGM("race")
end,
solo=function()
modeEnv={
wait=1,
fall=1,
}
createPlayer(1,40,30,.8)--Player
createPlayer(2,560,100,.7,2)--AI
curBG="game2"
BGM("race")
end,
blind=function()
modeEnv={
drop=15,
lock=30,
wait=1,
fall=1,
visible=0,
freshLimit=8,
}
createPlayer(1,190,20,.8)
curBG="game1"
BGM("push")
end,
asymsolo=function()
modeEnv={
wait=1,
fall=1,
visible=2,
}
createPlayer(1,40,30,.8)--Player
createPlayer(2,560,100,.7,2)--AI
curBG="game2"
BGM("race")
end,
}
Event={
gameover={
win=function()
P.alive=false
P.control=false
P.waiting=1e99
gameover=0
for i=1,#visTime do for j=1,10 do
P.visTime[i][j]=1e99
end end--Make all visible
P.control=false
ins(task,Event.task.win)
end,
lose=function()
P.alive=false
P.control=false
P.waiting=1e99
gameover=0
for i=1,#visTime do for j=1,10 do
P.visTime[i][j]=1e99
end end--Make all visible
for i=1,#players.alive do
if players.alive[i]==P.id then
rem(players.alive,i)
break
end
end
for i=1,#P.atkBuffer do
P.atkBuffer[i].sent=true
P.atkBuffer[i].time=0
end
ins(task,Event.task.lose)
end,
},
marathon_reach=function()
local s=int(P.cstat.row*.1)
if s>=20 then
Event.gameover.win()
else
gameEnv.drop=Data.marathon_drop[s]
if s==18 then gameEnv._20G=true end
gameEnv.target=s*10+10
end
end,
death_reach=function()
if gameEnv.target==50 then
gameEnv.lock=9
gameEnv.wait=5
gameEnv.fall=8
showText("STAGE 2","fly",80,-100)
elseif gameEnv.target==100 then
gameEnv.lock=8
gameEnv.wait=4
gameEnv.fall=6
showText("STAGE 3","fly",80,-100)
elseif gameEnv.target==150 then
gameEnv.lock=7
gameEnv.wait=3
gameEnv.fall=5
showText("STAGE 4","fly",80,-100)
elseif gameEnv.target==200 then
gameEnv.lock=6
gameEnv.wait=2
gameEnv.fall=4
showText("STAGE 5","fly",80,-100)
gameEnv.target=250
end
gameEnv.target=gameEnv.target+50
SFX("reach")
end,
task={
win=function()
gameover=gameover+1
@@ -338,65 +465,15 @@ Event={
end
end,
},
gameover={
win=function()
P.control=false
P.waiting=1e99
gameover=0
for i=1,#visTime do for j=1,10 do
P.visTime[i][j]=1e99
end end--Make all visible
P.control=false
ins(task,Event.task.win)
end,
lose=function()
P.control=false
P.waiting=1e99
gameover=0
for i=1,#visTime do for j=1,10 do
P.visTime[i][j]=1e99
end end--Make all visible
P.control=false
for i=1,#players.alive do
if players.alive[i]==P.id then
rem(players.alive,i)
break
end
end
for i=1,#P.atkBuffer do
P.atkBuffer[i].sent=true
P.atkBuffer[i].time=0
end
ins(task,Event.task.lose)
end,
},
marathon_reach=function()
local s=int(P.cstat.row*.1)
if s>=20 then
Event.gameover.win()
else
gameEnv.drop=Data.marathon_drop[s]
gameEnv.target=s*10+10
end
end,
gm_reach=function()
end
}
Data={
marathon_drop={[0]=60,50,40,30,25,20,18,16,14,12,10,8,7,6,5,4,3,2,1,1},
marathon_drop={[0]=60,48,40,30,24,18,15,12,10,8,7,6,5,4,3,2,1,1,0,0},
shirase_drop={[0]=0},
shirase_lock={[0]=0},
shirase_are={[0]=0},
shirase_lare={[0]=0},
}
mesDisp={
marathon=function()
gc.setColor(1,1,1)
setFont(40)
gc.print(format("%0.2f",time),-130,530)
mStr(P.cstat.row.."/"..gameEnv.target,-80,250)
end,
sprint=function()
gc.setColor(1,1,1)
setFont(40)
@@ -411,8 +488,41 @@ mesDisp={
setFont(75)
mStr(max(200-P.cstat.row,0),-80,280)
end,
gm=function()end,
battle=function()end,
gmroll=function()
gc.setColor(1,1,1)
setFont(40)
gc.print(format("%0.2f",time),-130,530)
setFont(35)
gc.print("Tetris",-120,390)
setFont(80)
mStr(cstat.tetris,-77,420)
end,
marathon=function()
gc.setColor(1,1,1)
setFont(40)
gc.print(format("%0.2f",time),-130,530)
mStr(P.cstat.row.."/"..gameEnv.target,-80,250)
end,
death=function()
gc.setColor(1,1,1)
setFont(40)
gc.print(format("%0.2f",time),-130,530)
mStr(P.cstat.row.."/"..gameEnv.target,-80,250)
end,
tetris25=function()
gc.setColor(1,1,1)
setFont(40)
gc.print("Remain",-142,510)
gc.print("Attack",-132,365)
setFont(80)
mStr(#players.alive,-77,440)
mStr(cstat.atk,-77,300)
end,
blind=function()
gc.setColor(1,1,1)
setFont(80)
mStr(P.cstat.row,-80,250)
end,
}
--Game system Data
@@ -422,7 +532,7 @@ setting={
lang="eng",
das=5,arr=0,
ghost=true,center=true,
key={"left","right","x","z","c","up","down","space","LEFT","RIGHT"},
key={"left","right","x","z","c","up","down","space","r","LEFT","RIGHT"},
color={1,5,2,8,10,3,7,13},
}
stat={
@@ -526,24 +636,25 @@ function gotoScene(s,style)
}
end
end
function createPlayer(id,x,y,size,ifAI,data)
function createPlayer(id,x,y,size,AIspeed,data)
players[id]={id=id}
ins(players.alive,id)
local P=players[id]
P.index={__index=P}
P.x,P.y,P.size=x,y,size
if ifAI then
if AIspeed then
P.ai={
controls={},
controlDelay=2,
controlDelay0=2,
controlDelay=60,
controlDelay0=AIspeed,
}
end
P.alive=true
P.control=false
P.time=0
P.cstat={piece=0,row=0,atk=0}--Current gamestat
P.cstat={piece=0,row=0,atk=0,tetris=0}--Current gamestat
P.keyTime={}for i=1,10 do P.keyTime[i]=-1e5 end P.keySpeed=0
P.dropTime={}for i=1,10 do P.dropTime[i]=-1e5 end P.dropSpeed=0
@@ -564,6 +675,8 @@ function createPlayer(id,x,y,size,ifAI,data)
P.hn,P.hb,P.holded=0,{{}},false
P.nxt,P.nb={},{}
P.dropDelay,P.lockDelay=P.gameEnv.drop,P.gameEnv.lock
P.freshTime=0
P.lastSpin=false
local bag1={1,2,3,4,5,6,7}
for i=1,7 do
@@ -598,6 +711,7 @@ function startGame(mode)
frame=0
count=179
FX.beam={}
for i=1,#PTC.dust do PTC.dust[i]:release()end
for i=1,#players do
PTC.dust[i]=PTC.dust[0]:clone()
@@ -689,10 +803,17 @@ function freshgho()
else
while not ifoverlap(cb,cx,cy-1)do
P.cy=P.cy-1
P.spinLast=false
end
P.y_img=P.cy
end
end
function freshLockDelay()
if P.lockDelay<gameEnv.lock and P.freshTime<=gameEnv.freshLimit then
P.lockDelay=gameEnv.lock
P.freshTime=P.freshTime+1
end
end
function ifoverlap(bk,x,y)
if x<1 or x+#bk[1]>11 or y<1 then return true end
if y>#field then return nil end
@@ -700,174 +821,6 @@ function ifoverlap(bk,x,y)
if field[y+i-1]and bk[i][j]>0 and field[y+i-1][x+j-1]>0 then return true end
end end
end
function resetblock()
P.holded=false
P.freshNext()
P.sc={scs[bn][1],scs[bn][2]}P.dir=0
P.r,P.c=#cb,#cb[1]
P.cx,P.cy=blockPos[bn],21+ceil(fieldBeneath/30)
freshgho()
P.dropDelay,P.lockDelay=gameEnv.drop,gameEnv.lock
if keyPressing[8]then hold(true)end
if keyPressing[3]then spin(1,true)end
if keyPressing[4]then spin(-1,true)end
if keyPressing[5]then spin(2,true)end
if ifoverlap(cb,cx,cy)then Event.gameover.lose()end
if keyPressing[6]then act.hardDrop()P.keyPressing[6]=false end
end
function pressKey(i,player)
P=player or players[1]
setmetatable(_G,P.index)
if control then
P.keyPressing[i]=true
if waiting<=0 then
act[actName[i]]()
if i>2 and i<6 then keyPressing[i]=false end
elseif i==1 then
P.moving=-1
elseif i==2 then
P.moving=1
end
P.cstat.key=stat.key+1;ins(keyTime,1,frame)rem(keyTime,11)
-- if playmode=="recording"then ins(rec,{i,frame})end
stat.key=stat.key+1
end
end
function releaseKey(i,player)
P=player or players[1]
setmetatable(_G,P.index)
P.keyPressing[i]=false
-- if playmode=="recording"then ins(rec,{-i,frame})end
end
function spin(d,ifpre)
if bn==6 then return nil end
local icb=blocks[bn][(dir+d)%4]
local isc=d==1 and{c-sc[2]+1,sc[1]}or d==-1 and{sc[2],r-sc[1]+1}or{r-sc[1]+1,c-sc[2]+1}
local ir,ic=#icb,#icb[1]
local ix,iy=cx+sc[2]-isc[2],cy+sc[1]-isc[1]
local t=false
local iki=SRS[bn][dir*10+(dir+d)%4]
for i=1,#iki do
if not ifoverlap(icb,ix+iki[i][1],iy+iki[i][2])then
ix,iy=ix+iki[i][1],iy+iki[i][2]
t=true
break
end
end
if t then
P.cx,P.cy=ix,iy
P.sc,P.cb=isc,icb
P.r,P.c=ir,ic
P.dir=(dir+d)%4
freshgho()
P.lockDelay=gameEnv.lock
SFX(ifpre and"prerotate"or ifoverlap(cb,cx,cy+1)and ifoverlap(cb,cx-1,cy)and ifoverlap(cb,cx+1,cy)and"rotatekick"or"rotate")
stat.rotate=stat.rotate+1
end
end
function hold(ifpre)
if not holded and waiting<=0 and gameEnv.hold then
P.hn,P.bn=bn,hn
P.hb,P.cb=blocks[hn][0],hb
if bn==0 then freshNext()end
P.sc={scs[bn][1],scs[bn][2]}P.dir=0
P.r,P.c=#cb,#cb[1]
P.cx,P.cy=blockPos[bn],21
freshgho()
P.dropDelay,P.lockDelay=gameEnv.drop,gameEnv.lock
if ifoverlap(cb,cx,cy) then Event.gameover.lose()end
P.holded=true
SFX(ifpre and"prehold"or"hold")
stat.hold=stat.hold+1
end
end
function drop()
if cy==y_img then
P.waiting=gameEnv.wait
local dospin=ifoverlap(cb,cx,cy+1)and ifoverlap(cb,cx-1,cy)and ifoverlap(cb,cx+1,cy)
ins(dropTime,1,frame)rem(dropTime,11)
lock()
local cc,csend=checkrow(cy,r),0--Currect clear&send
P.combo=P.combo+1--combo=0 is under
if cc==4 then
if b2b then
showText("Tetris B2B","drive",70)
csend=5
else
showText("Tetris","stretch",80)
csend=4
P.b2b=true
end
elseif cc>0 then
if dospin then
if b2b then
showText(name[bn].." spin "..list.clearname[cc].." B2B","spin",40)
csend=2*cc+1
else
showText(name[bn].." spin "..list.clearname[cc],"spin",50)
csend=2*cc
P.b2b=true
end
SFX("spin_"..cc)
stat.spin=stat.spin+1
else
P.b2b=false
showText(list.clearname[cc],"appear",50)
csend=cc-1
end
else
P.combo=0
if dospin then
showText(name[bn].." spin","appear",50)
SFX("spin_0")
end
end
if cc>0 and #clearing==#field then
showText("Perfect Clear","flicker",70,-60)
csend=csend+5
SFX("perfectclear")
end
csend=csend+(renATK[combo]or 4)
if cc>0 then
SFX("clear_"..cc)
SFX("ren_"..min(combo,11))
end
if csend>0 then
while csend>0 and P.atkBuffer[1]do
csend=csend-1
P.atkBuffer[1].amount=P.atkBuffer[1].amount-1
if P.atkBuffer[1].amount==0 then
rem(P.atkBuffer,1)
end
end
if csend>0 and #players.alive>1 then garbageSend(P.id,csend,120)end
elseif cc==0 then
garbageRelease()
end--Send attack
stat.piece,stat.row,stat.atk=stat.piece+1,stat.row+cc,stat.atk+csend
P.cstat.piece,P.cstat.row,P.cstat.atk=P.cstat.piece+1,P.cstat.row+cc,P.cstat.atk+csend
if P.cstat.row>=gameEnv.target then
gameEnv.reach()
if control then SFX("reach")end
end
else
if cy>y_img then P.cy=cy-1 end
end
end
function lock()
for i=1,r do
local y=cy+i-1
if not P.field[y]then P.field[y],P.visTime[y]={0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0}end
for j=1,c do
if cb[i][j]~=0 then
P.field[y][cx+j-1]=P.gameEnv.color[bn]
P.visTime[y][cx+j-1]=P.showTime
end
end
end
end
function ckfull(i)
for j=1,10 do if field[i][j]==0 then return nil end end
return true
@@ -885,6 +838,210 @@ function checkrow(s,num)--(cy,r)
end end
return c
end
function solid(x,y)
if x<1 or x>10 or y<1 then return true end
if y>#field then return false end
return field[y][x]>0
end
function resetblock()
P.holded=false
P.spinLast=false
P.freshNext()
P.sc={scs[bn][1],scs[bn][2]}P.dir=0
P.r,P.c=#cb,#cb[1]
P.cx,P.cy=blockPos[bn],21+ceil(fieldBeneath/30)
P.dropDelay,P.lockDelay,P.freshTime=gameEnv.drop,gameEnv.lock,0
if keyPressing[8]then hold(true)end
if keyPressing[3]then spin(1,true)end
if keyPressing[4]then spin(-1,true)end
if keyPressing[5]then spin(2,true)end
freshgho()
if ifoverlap(cb,cx,cy)then Event.gameover.lose()end
if keyPressing[6]then act.hardDrop()P.keyPressing[6]=false end
end
function pressKey(i,player)
P=player or players[1]
setmetatable(_G,P.index)
P.keyPressing[i]=true
if i==9 then
act.restart()
elseif alive then
if control and waiting<=0 then
act[actName[i]]()
if i>2 and i<6 then keyPressing[i]=false end
elseif i==1 then
P.moving=-1
elseif i==2 then
P.moving=1
end
P.cstat.key=stat.key+1;ins(keyTime,1,frame)rem(keyTime,11)
stat.key=stat.key+1
end
-- if playmode=="recording"then ins(rec,{i,frame})end
end
function releaseKey(i,player)
P=player or players[1]
setmetatable(_G,P.index)
P.keyPressing[i]=false
-- if playmode=="recording"then ins(rec,{-i,frame})end
end
function spin(d,ifpre)
-- if bn==6 then return nil end--Ignore O spin
local icb=blocks[bn][(dir+d)%4]
local isc=d==1 and{c-sc[2]+1,sc[1]}or d==-1 and{sc[2],r-sc[1]+1}or{r-sc[1]+1,c-sc[2]+1}
local ir,ic=#icb,#icb[1]
local ix,iy=cx+sc[2]-isc[2],cy+sc[1]-isc[1]
local t=false--if spin available
local iki=SRS[bn][dir*10+(dir+d)%4]
for i=1,#iki do
if not ifoverlap(icb,ix+iki[i][1],iy+iki[i][2])then
ix,iy=ix+iki[i][1],iy+iki[i][2]
t=true
break
end
end
if t then
P.cx,P.cy=ix,iy
P.sc,P.cb=isc,icb
P.r,P.c=ir,ic
P.dir=(dir+d)%4
P.spinLast=true
freshgho()--May cancel spinLast
freshLockDelay()
SFX(ifpre and"prerotate"or ifoverlap(cb,cx,cy+1)and ifoverlap(cb,cx-1,cy)and ifoverlap(cb,cx+1,cy)and"rotatekick"or"rotate")
stat.rotate=stat.rotate+1
end
end
function hold(ifpre)
if not holded and waiting<=0 and gameEnv.hold then
P.hn,P.bn=bn,hn
P.hb,P.cb=blocks[hn][0],hb
if bn==0 then freshNext()end
P.sc={scs[bn][1],scs[bn][2]}P.dir=0
P.r,P.c=#cb,#cb[1]
P.cx,P.cy=blockPos[bn],21
freshgho()
P.dropDelay,P.lockDelay,P.freshTime=gameEnv.drop,gameEnv.lock,0
if ifoverlap(cb,cx,cy) then Event.gameover.lose()end
P.holded=true
SFX(ifpre and"prehold"or"hold")
stat.hold=stat.hold+1
end
end
function drop()
if cy==y_img then
ins(dropTime,1,frame)rem(dropTime,11)--update speed dial
P.waiting=gameEnv.wait
local canSpin=gameEnv.spinList[bn]
local dospin=canSpin and ifoverlap(cb,cx-1,cy)and ifoverlap(cb,cx+1,cy)and ifoverlap(cb,cx,cy+1)
if canSpin and not dospin and bn<6 and spinLast then
local x,y=cx+sc[2]-1,cy+sc[1]-1
local c=0
if solid(x-1,y+1)then c=c+1 end
if solid(x+1,y+1)then c=c+1 end
if c>0 then
if solid(x-1,y-1)then c=c+1 end
if solid(x+1,y-1)then c=c+1 end
if c>2 then
dospin=true
end
end
end--Triangle spin system
lock()
local cc,csend=checkrow(cy,r),0--Currect clear&send
local mini=dospin and cc<r
P.combo=P.combo+1--combo=0 is under
if cc==4 then
if b2b then
showText("Tetris B2B","drive",70)
csend=5
else
showText("Tetris","stretch",80)
csend=4
P.b2b=true
end
P.cstat.tetris=P.cstat.tetris+1
elseif cc>0 then
if dospin then
local t=list.blockName[bn].." spin "..list.clearname[cc]
if mini then showText("Mini","drive",40,10)end
if b2b then
t=t.." B2B"
showText(t,"spin",40)
csend=b2bATK[cc]
else
showText(t,"spin",50)
csend=2*cc
P.b2b=true
end
SFX("spin_"..cc)
stat.spin=stat.spin+1
else
P.b2b=false
showText(list.clearname[cc],"appear",50)
csend=cc-1
end
else
P.combo=0
if dospin then
showText(list.blockName[bn].." spin","appear",50)
SFX("spin_0")
end
end
if cc>0 and #clearing==#field then
showText("Perfect Clear","flicker",70,-60)
csend=csend+5
SFX("perfectclear")
end
csend=csend+(renATK[combo]or 4)
if cc>0 then
SFX("clear_"..cc)
SFX("ren_"..min(combo,11))
end
if csend>0 then
if mini then csend=int(csend*.7)end
--mini attack decrease
stat.atk=stat.atk+csend
P.cstat.atk=P.cstat.atk+csend
--ATK statistics
while csend>0 and P.atkBuffer[1]do
csend=csend-1
P.atkBuffer[1].amount=P.atkBuffer[1].amount-1
if P.atkBuffer[1].amount==0 then
rem(P.atkBuffer,1)
end
end
if csend>0 and #players.alive>1 then garbageSend(P.id,csend,120)end
elseif cc==0 then
garbageRelease()
end--Send attack
stat.piece,stat.row=stat.piece+1,stat.row+cc
P.cstat.piece,P.cstat.row=P.cstat.piece+1,P.cstat.row+cc
if P.cstat.row>=gameEnv.target then
gameEnv.reach()
if control then SFX("reach")end
end
else
P.cy=cy-1
P.spinLast=false
end
end
function lock()
for i=1,r do
local y=cy+i-1
if not P.field[y]then P.field[y],P.visTime[y]={0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0}end
for j=1,c do
if cb[i][j]~=0 then
P.field[y][cx+j-1]=P.gameEnv.color[bn]
P.visTime[y][cx+j-1]=P.showTime
end
end
end
end
function garbageSend(sender,send,time)
local pos,r=rnd(10)
repeat
@@ -924,7 +1081,7 @@ mouseDown={}
keyDown={}
function keyDown.play(key)
local k=players[1].gameEnv.key
for i=1,10 do
for i=1,11 do
if key==k[i]then
pressKey(i,players[1])
break
@@ -992,8 +1149,8 @@ function love.draw()
setFont(35)
drawButton()
if mouseShow then
gc.setColor(1,0,0,.6)
gc.circle("fill",mx,my,4)
gc.setColor(1,.5,0,.7)
gc.circle("fill",mx,my,6)
end
if sceneSwaping then sceneSwaping.draw()end
@@ -1006,8 +1163,8 @@ function love.draw()
gc.rectangle("fill",1000,0,(ww*600/wh-1000)*.5,600)
end--Draw black side
--numFont(10)gc.setColor(1,1,1)
--gc.print(tm.getFPS(),0,590)
numFont(10)gc.setColor(1,1,1)
gc.print(tm.getFPS(),0,590)
--if gcinfo()>500 then collectgarbage()end
end
function love.resize(x,y)
@@ -1034,6 +1191,7 @@ function love.focus(f)
end
end
function love.run()
local frameT=Timer()
tm.step()
love.resize(1000,600)
game.load()--Launch
@@ -1055,6 +1213,8 @@ function love.run()
gc.present()
end
end
while Timer()-frameT<1/60 do end
frameT=Timer()
end
end
--System callbacks

View File

@@ -20,18 +20,8 @@ function Pnt.BG.game2()
gc.draw(background[1],500,300,Timer()*.15,nil,nil,600,600)
end
function Pnt.BG.game3()
gc.push("transform")
gc.translate(500,300)
gc.scale(1,.6)
gc.setColor(1,.9,.9)
gc.setLineWidth(30)
local t=(Timer()%1)*60
for x=0,8 do
local d=60*x+t
gc.rectangle("line",-d,-d,2*d,2*d)
end
gc.setLineWidth(2)
gc.pop()
gc.setColor(.5,.7,1)
gc.draw(background[1],500,300,Timer()*.15,nil,nil,600,600)
end
function Pnt.BG.game4()
local t=215+sin(Timer()*6)*40
@@ -75,7 +65,7 @@ function Pnt.play()
setmetatable(_G,P.index)
gc.push("transform")
gc.translate(x,y)gc.scale(size)--Scale
gc.setColor(0,0,0,.7)gc.rectangle("fill",0,0,620,690)--Back
gc.setColor(0,0,0,.8)gc.rectangle("fill",0,0,620,690)--Black Background
gc.setLineWidth(3)
gc.setColor(1,1,1)gc.rectangle("line",0,0,620,690)--Big frame
gc.translate(160,70)
@@ -98,15 +88,26 @@ function Pnt.play()
if gameEnv.ghost then
for i=1,r do for j=1,c do
if cb[i][j]>0 then
drawPixel(i+y_img-1,j+cx-1,gameEnv.color[bn],.4)
drawPixel(i+y_img-1,j+cx-1,gameEnv.color[bn],.3)
end
end end
end--Ghost
gc.setColor(1,1,1,lockDelay/gameEnv.lock)
for i=1,r do for j=1,c do
if cb[i][j]>0 then
gc.rectangle("fill",30*(j+cx-1)-35,595-30*(i+cy-1),40,40)
end
end end--BlockShade(lockdelay indicator)
for i=1,r do for j=1,c do
if cb[i][j]>0 then
drawPixel(i+cy-1,j+cx-1,gameEnv.color[bn],1)
end
end end--Block
if gameEnv.center then
local x=30*(cx+sc[2]-1)-30+15
gc.circle("fill",x,600-30*(cy+sc[1]-1)+15,4)
gc.circle("fill",x,600-30*(y_img+sc[1]-1)+15,4)
end
end
gc.draw(PTC.dust[p])--Draw game field
love.graphics.setStencilTest()--In-field mask
@@ -142,7 +143,7 @@ function Pnt.play()
h=h+bar
if h>600 then break end
end--Buffer line
setFont(40)
if gameEnv.hold then
gc.setColor(1,1,1)
@@ -179,7 +180,7 @@ function Pnt.play()
for i=1,#bonus do
bonus[i]:draw()
end--Effects
mesDisp[gamemode]()--Draw message
if mesDisp[gamemode]then mesDisp[gamemode]()end--Draw message
setFont(45)
gc.translate(380,550)
gc.setColor(1,1,1)
@@ -200,7 +201,7 @@ function Pnt.play()
gc.setLineWidth(3)
for i=1,#FX.beam do
local b=FX.beam[i]
local t=b.t/45
local t=b.t/30
if t<.25 then
t=t*4
gc.setColor(1,1,1,4*t)
@@ -225,7 +226,7 @@ end
function Pnt.setting2()
setFont(30)
gc.setColor(1,1,1)
for i=1,8 do
for i=1,9 do
gc.printf(actName_[i]..":",80,5+50*i,150,"right")
end
if keysetting then

View File

@@ -1,2 +0,0 @@
1.缓冲条位置
2.

168
timer.lua
View File

@@ -60,108 +60,110 @@ function Tmr.play(dt)
for p=1,#players do
P=players[p]
setmetatable(_G,P.index)
if control then P.time=time+dt end
if alive then
if control then P.time=time+dt end
local v=0
for i=2,10 do v=v+i*(i-1)*7.2/(frame-keyTime[i])end P.keySpeed=keySpeed*.99+v*.1
v=0 for i=2,10 do v=v+i*(i-1)*7.2/(frame-dropTime[i])end P.dropSpeed=dropSpeed*.99+v*.1
--Update speeds
local v=0
for i=2,10 do v=v+i*(i-1)*7.2/(frame-keyTime[i])end P.keySpeed=keySpeed*.99+v*.1
v=0 for i=2,10 do v=v+i*(i-1)*7.2/(frame-dropTime[i])end P.dropSpeed=dropSpeed*.99+v*.1
--Update speeds
if P.ai then
P.ai.controlDelay=P.ai.controlDelay-1
if P.ai.controlDelay==0 then
if #P.ai.controls>0 then
pressKey(P.ai.controls[1],P)
releaseKey(P.ai.controls[1],P)
rem(P.ai.controls,1)
P.ai.controlDelay=P.ai.controlDelay0
else
AI_getControls(P.ai.controls)
P.ai.controlDelay=2*P.ai.controlDelay0
end
end
end
for j=1,#field do for i=1,10 do
if visTime[j][i]>0 then P.visTime[j][i]=visTime[j][i]-1 end
end end
--Fresh visible time
if keyPressing[1]or keyPressing[2]then
P.moving=moving+sgn(moving)
local d=abs(moving)-gameEnv.das
if d>1 then
if gameEnv.arr>0 then
if d%gameEnv.arr==0 then
act[moving>0 and"moveRight"or"moveLeft"](true)
if P.ai then
P.ai.controlDelay=P.ai.controlDelay-1
if P.ai.controlDelay==0 then
if #P.ai.controls>0 then
pressKey(P.ai.controls[1],P)
releaseKey(P.ai.controls[1],P)
rem(P.ai.controls,1)
P.ai.controlDelay=P.ai.controlDelay0+rnd(3)
else
AI_getControls(P.ai.controls)
P.ai.controlDelay=2*P.ai.controlDelay0
end
else
act[moving>0 and"toRight"or"toLeft"]()
end
end
else
P.moving=0
end
if keyPressing[7]then
act.softDrop()
P.downing=downing+1
else
P.downing=0
end
if falling>0 then
P.falling=falling-1
if falling<=0 then
if #field>clearing[1]then SFX("fall")end
for i=1,#clearing do
rem(field,clearing[i])
rem(visTime,clearing[i])
end
P.clearing={}
end
elseif waiting>0 then
P.waiting=waiting-1
if waiting<=0 then
resetblock()
end
else
if cy~=y_img then
if dropDelay>1 then
P.dropDelay=dropDelay-1
else
drop()
P.dropDelay,P.lockDelay=gameEnv.drop,gameEnv.lock
for j=1,#field do for i=1,10 do
if visTime[j][i]>0 then P.visTime[j][i]=visTime[j][i]-1 end
end end
--Fresh visible time
if keyPressing[1]or keyPressing[2]then
P.moving=moving+sgn(moving)
local d=abs(moving)-gameEnv.das
if d>1 then
if gameEnv.arr>0 then
if d%gameEnv.arr==0 then
act[moving>0 and"moveRight"or"moveLeft"](true)
end
else
act[moving>0 and"toRight"or"toLeft"]()
end
end
else
if lockDelay>0 then P.lockDelay=lockDelay-1
else drop()
P.moving=0
end
if keyPressing[7]then
act.softDrop()
P.downing=downing+1
else
P.downing=0
end
if falling>0 then
P.falling=falling-1
if falling<=0 then
if #field>clearing[1]then SFX("fall")end
for i=1,#clearing do
rem(field,clearing[i])
rem(visTime,clearing[i])
end
P.clearing={}
end
elseif waiting>0 then
P.waiting=waiting-1
if waiting<=0 then
resetblock()
end
else
if cy~=y_img then
if dropDelay>1 then
P.dropDelay=dropDelay-1
else
drop()
P.dropDelay,P.lockDelay=gameEnv.drop,gameEnv.lock
end
else
if lockDelay>0 then P.lockDelay=lockDelay-1
else drop()
end
end
end
end
end--If alive
for i=#bonus,1,-1 do
bonus[i].t=bonus[i].t+1
if bonus[i].t>60 then rem(bonus,i)end
end
for i=#task,1,-1 do
if task[i]()then rem(task,i)end
end
for i=#atkBuffer,1,-1 do
local atk=atkBuffer[i]
atk.time=atk.time+1
if not atk.sent then
if atk.countdown>0 then
atk.countdown=atk.countdown-1
end
else
if atk.time>20 then
rem(atkBuffer,i)
end
end
end
if fieldBeneath>0 then P.fieldBeneath=fieldBeneath-1 end
end
for i=#atkBuffer,1,-1 do
local atk=atkBuffer[i]
atk.time=atk.time+1
if not atk.sent then
if atk.countdown>0 then
atk.countdown=atk.countdown-1
end
else
if atk.time>20 then
rem(atkBuffer,i)
end
end
end
if fieldBeneath>0 then P.fieldBeneath=fieldBeneath-2 end
PTC.dust[p]:update(dt)
end
for i=#FX.beam,1,-1 do
FX.beam[i].t=FX.beam[i].t+1
if FX.beam[i].t>45 then
if FX.beam[i].t>30 then
rem(FX.beam,i)
end
end

View File

@@ -4,8 +4,9 @@ act={
if not ifoverlap(cb,cx-1,cy)then
P.cx=cx-1
freshgho()
P.lockDelay=gameEnv.lock
freshLockDelay()
if cy==y_img then SFX("move")end
P.spinLast=false
end
end,
moveRight=function(auto)
@@ -13,14 +14,16 @@ act={
if not ifoverlap(cb,cx+1,cy)then
P.cx=cx+1
freshgho()
P.lockDelay=gameEnv.lock
freshLockDelay()
if cy==y_img then SFX("move")end
P.spinLast=false
end
end,
hardDrop=function()
if P.waiting<=0 then
if cy~=y_img then
P.cy=y_img
P.spinLast=false
SFX("drop")
end
drop()
@@ -36,10 +39,13 @@ act={
rotFlip=function()spin(2)end,
hold=hold,
--Player movements
restart=function()
startGame(gamemode)
count=60+26--Althour'z neim
end,
down1=function()drop()end,
down4=function()for i=1,4 do if cy~=y_img then drop()else break end end end,
toDown=function()P.cy,P.lockDelay=y_img,gameEnv.lock end,
toDown=function()if cy~= y_img then P.cy,P.lockDelay,P.spinLast=y_img,gameEnv.lock,false end end,
toLeft=function()while not ifoverlap(cb,cx-1,cy)do P.cx,P.lockDelay=cx-1,gameEnv.lock;freshgho()end end,
toRight=function()while not ifoverlap(cb,cx+1,cy)do P.cx,P.lockDelay=cx+1,gameEnv.lock;freshgho()end end,
quit=function()Event.gameover.lose()end,