match-3/main.lua

1107 lines
23 KiB
Lua
Raw Normal View History

2023-04-12 11:11:12 +03:00
local ostype=love.system.getOS()
local mobile=ostype=="Android" or ostype=="iOS"
love.window.setMode(mobile and 400 or 800,mobile and 720 or 600,{resizable=true,fullscreen=mobile})
love.window.setTitle("m3")
love.window.maximize()
local fs=love.filesystem
fs.setIdentity(fs.getIdentity(),true)
2023-03-28 08:42:05 +03:00
local g=love.graphics
2023-04-12 11:11:12 +03:00
local bw,bh=8,8
local board={}
local cc=3
local tt=0
local bat=1
local batd=bat
local score=0
local taint=0
local taintd=taint
local tochar=0
local scored=score
local falltest=false
local playdbg=false
local dbg=false
local grabbed=nil
local dying=false
local running=false
local animc=0
local entc=0
local boomc=0
local sfxc=0
local slow=1
local accumdt=0
local tps=120
local rtps=0
local tpsl={}
local speeds={1,0.05,10}
local plchint=1
local toplchi=plchint
local yes=true
local font=g.newFont(9,"mono",1)
2023-03-28 08:42:05 +03:00
font:setFilter("nearest")
g.setFont(font)
2023-03-30 04:52:00 +03:00
local ltest=0
2023-04-12 11:11:12 +03:00
local hookdbg=true
2023-03-30 04:52:00 +03:00
if hookdbg then
debug.sethook(function()
ltest=ltest+1
if ltest>=1000 then
ltest=0
2023-04-12 11:11:12 +03:00
print("!! we are in a freezer !!",debug.traceback())
2023-03-30 04:52:00 +03:00
end
end,"",1000)
end
2023-03-28 08:42:05 +03:00
local colors={
function(a,b)
g.setColor(1,0,0,b*a)
g.polygon("fill",0.5,0, 1,0.5, 0.5,1, 0,0.5)
g.setColor(1,0,0,a)
g.polygon("line",0.5,0, 1,0.5, 0.5,1, 0,0.5)
end,
function(a,b)
local w=0.5^0.5
local p=(1-w)/2
g.setColor(1,1,0,b*a)
g.rectangle("fill",p,p,w,w)
g.setColor(1,1,0,a)
g.rectangle("line",p,p,w,w)
end,
function(a,b)
g.setColor(0,1,0,b*a)
g.circle("fill",0.5,0.5,0.45,8)
g.setColor(0,1,0,a)
g.circle("line",0.5,0.5,0.45,8)
end,
function(a,b)
g.translate(0,0.15)
g.translate(0.5,0.5)
g.rotate(math.pi/2*3)
g.translate(-0.5,-0.5)
g.setColor(0,1,1,b*a)
g.circle("fill",0.5,0.5,0.5,3)
g.setColor(0,1,1,a)
g.circle("line",0.5,0.5,0.5,3)
end,
function(a,b)
g.translate(0.5,0.5)
g.rotate(math.pi/2*3)
g.translate(-0.5,-0.5)
g.setColor(1,0,1,b*a)
g.circle("fill",0.5,0.5,0.45,6)
g.setColor(1,0,1,a)
g.circle("line",0.5,0.5,0.45,6)
end,
function(a,b)
g.setColor(0,0,1,b*a)
2023-04-12 11:11:12 +03:00
g.polygon("fill",
0.1,0.4, 0.5,0, 0.9,0.4,
0.9,1-0.4, 0.5,1-0, 0.1,1-0.4
)
g.setColor(1,0,0,a)
2023-03-28 08:42:05 +03:00
g.setColor(0,0,1,a)
g.line(0.1,0.4, 0.5,0, 0.9,0.4)
g.line(0.1,1-0.4, 0.5,1-0, 0.9,1-0.4)
2023-04-12 11:11:12 +03:00
g.line(0.4,0.5, 0.6,0.5)
2023-03-28 08:42:05 +03:00
end,
}
local gobjs={}
local cgobjs={}
local lgobjs={}
local mgobjs={}
for k,v in ipairs(colors) do
gobjs[k]={c=k}
cgobjs[k]={c=k,super="charge"}
lgobjs[k]={c=k,super="lines"}
mgobjs[k]={c=k,super="color"}
end
local function znoise(...)
return love.math.noise(...)*2-1
2023-03-29 12:31:42 +03:00
end
2023-04-12 11:11:12 +03:00
local soundgen=require"soundgen"
local sfx={}
do
local rate=44100
local len=1
local bfreq=700
local lacu,pers=1.5,0.5
local octas=4
local rta=0
local oofs={}
math.randomseed(os.time())
do
local pe=1
for n=1,octas do
oofs[n]=math.random()*2-1
rta=rta+(pe)
pe=pe*pers
end
end
local sd=love.sound.newSoundData(rate*len,rate,16,1)
local function gsample(t)
local arg=(bfreq*(t^((1+math.sin(t*3*math.pi)*0.1)*love.math.noise(t*0.1-0.05,5244,love.math.noise(t*1000,2949)*0.01-0.005))))
local nn=0
local pe=1/rta
local ao=1
for n=1,octas do
local nnn=znoise(arg*ao,n/5+oofs[n])*pe
--nn=math.max(-1,math.min(1,nn+nnn))
nn=nn+nnn
--print(n,nn,nnn,pe,ao)
pe=pe*pers
ao=ao*lacu
end
return (nn*(1-t)^5)*(math.min(1,math.max(t*100))^0.5)
end
for n=0,len*rate-1 do
local a=gsample(n/(rate))
sd:setSample(n,a)
end
sfx.boom=love.audio.newSource(sd)
end
do
local sg=soundgen
local wave=sg:noise():phase(math.random()*1000):freq(1000):amp(0.25)
:pm(sg:triangle():freq(50):am(sg:silence(1):fade(0,0.04),-1,1),-0.01,0.01)
:add(sg:sine():amp(0.55):freq(50):pm(sg:noise():freq(500):phase(0.834715384),-0.01,0.01))
wave=wave:fade(0,0.1)
wave=wave:fade(0.001,0)
sfx.fall=love.audio.newSource(wave:compile())
end
2023-03-29 12:31:42 +03:00
local function eudist(x,y)
return (x*x+y*y)^0.5
end
local function norm(x1,y1)
local d=eudist(x,y)
if d==0 then return 0,0 end
return x/d,y/d
end
local function dlbolt(x,y,x1,y1)
2023-03-28 08:42:05 +03:00
end
local function drawfig(n,a)
g.push("all")
g.scale(2-(a or 1))
g.translate(-0.5,-0.5)
g.translate(0.1,0.1)
g.scale(0.8)
colors[n.c](a or 1,n.super=="charge" and ((math.sin(tt*math.pi*2)*0.5+0.5)*0.4+0.1) or 0)
2023-04-12 11:11:12 +03:00
g.setLineWidth(g.getLineWidth()*0.5)
2023-03-28 08:42:05 +03:00
if n.super=="lines" then
local hps,vps={},{}
local det=10
for n=0,det do
local dmul=(det-math.abs(n-det/2))/det*4
hps[n*2+1],hps[n*2+2]=n/det,0.5+znoise(tt,583,-775,n)*0.1*dmul
vps[n*2+1],vps[n*2+2]=0.5+znoise(tt,-492,444,n)*0.1*dmul,n/det
end
g.line(hps)
g.line(vps)
elseif n.super=="color" then
local l={}
local det=100
for n=0,det do
l[n*2+1],l[n*2+2]=0.5+znoise(tt,55,51,n*math.pi/det*2),0.5+znoise(tt,44,25,n*math.pi/det*2)
end
g.setLineJoin("none")
g.polygon("line",l)
end
g.scale(0.02)
g.pop()
end
local function pti(x,y)
return y+(x-1)*bh
end
local trans=love.math.newTransform()
local anims={}
local falling={}
local booms={}
local function smtar(x,y,tx,ty)
local i=pti(x,y)
local anim
if not anims[i] then
if x==tx and y==ty then return end
anims[i]={
cx=x,cy=y,
tx=tx,ty=ty,
x=x,y=y
}
end
anim=anims[i]
anim.tx,anim.ty=tx,ty
end
local function setbsize(x,y,w,h)
trans:reset()
trans:translate(x,y)
trans:scale(w/bw,h/bh)
end
local gemrng
local function randgem()
2023-03-29 12:31:42 +03:00
tochar=tochar-1
local objl=gobjs
if tochar<=0 then
tochar=gemrng:random((bw*bh)*0.5,(bw*bh)*1.5)
objl=cgobjs
end
2023-03-28 08:42:05 +03:00
return objl[gemrng:random(math.floor(cc))]
end
local function nextgem(o)
local c=o.c%math.floor(cc)+1
return (o.super and cgobjs or gobjs)[c]
end
local function isgem(o)
return type(o)=="table" and colors[o.c]
end
local function eqgem(a,b)
return isgem(a) and isgem(b) and a.c==b.c
end
local function badboigemcheck(c,am,ac,rm)
c=isgem(c) and c.c
if not c then return end
if ac~=5 and ac~=4 then return end
local aa={}
2023-03-30 04:52:00 +03:00
for k,v in next,am do
2023-03-28 08:42:05 +03:00
local cc=board[v[1]][v[2]]
if isgem(cc) and (cc.super and cc.super~="charge") then
return
end
aa[#aa+1]=k
end
local e=aa[gemrng:random(#aa)]
local rc=ac==5 and mgobjs[c] or lgobjs[c]
rm[e][3]=rc
end
2023-03-29 12:31:42 +03:00
local function megascan(x,y,c,rm)
2023-03-28 08:42:05 +03:00
local ogc=c
rm=rm or {}
2023-03-29 12:31:42 +03:00
if not isgem(ogc) then return next(rm) and rm end
if ogc.super~="color" then return next(rm) and rm end
2023-03-28 08:42:05 +03:00
for x=1,bw do
for y=1,bh do
local i=pti(x,y)
local c=board[x][y]
if eqgem(c,ogc) then
rm[i]=rm[i] or {x,y}
end
end end
return next(rm) and rm
end
local function check(x,y,rm,oam,obm)
local c=board[x][y]
2023-03-29 12:31:42 +03:00
if not c then return rm,oam,obm end
2023-03-28 08:42:05 +03:00
local ac,bc=1,1
local am,bm={},{}
oam,obm=oam or {}, obm or {}
do
local i=pti(x,y)
local v={x,y}
am[i],bm[i]=v,v
end
rm=rm or {}
for d,v in ipairs{{-1,0},{1,0},{0,-1},{0,1}} do
local ox,oy=unpack(v)
local x,y=x+ox,y+oy
while x>=1 and x<=bw and y>=1 and y<=bh do
local i=pti(x,y)
if eqgem(board[x][y],c) then
if d>2 and not oam[i] then
ac=ac+1
am[i]={x,y}
oam[i]=true
elseif d<=2 and not obm[i] then
bc=bc+1
bm[i]={x,y}
obm[i]=true
end
else
break
end
x,y=x+ox,y+oy
end
end
if ac>=3 then
2023-03-30 04:52:00 +03:00
for k,v in next,am do rm[k]=v end
2023-03-28 08:42:05 +03:00
badboigemcheck(c,am,ac,rm)
end
if bc>=3 then
2023-03-30 04:52:00 +03:00
for k,v in next,bm do rm[k]=v end
2023-03-28 08:42:05 +03:00
badboigemcheck(c,bm,bc,rm)
end
return next(rm) and rm,oam,obm
end
local function drawboard(x,y,w,h)
g.push("all")
g.applyTransform(trans)
2023-04-12 11:11:12 +03:00
g.setLineJoin("bevel")
g.setLineWidth(0.15)
2023-03-28 08:42:05 +03:00
g.stencil(function()
g.rectangle("fill",0,0,bw,bh)
end)
2023-04-12 11:11:12 +03:00
do
g.push("all")
g.scale(bw/10,bh/10)
local bw,bh=10,10
g.translate(0.1,-1-0.05)
local bat=math.min(batd,1)
g.setColor((1-bat^2),bat^0.5,math.max(0,batd-1)^0.5)
g.rectangle("line",0,0,bw/2-0.1,0.8)
g.rectangle("fill",0.2,0.2,(bw/2-0.5)*bat,0.4)
g.rectangle("line",bw/2-0.09,0.2,0.2,0.4)
g.pop()
end
do
g.push("all")
g.scale(bw/10,bh/10)
local bw,bh=10,10
local sctext=("%.1i"):format(math.floor(scored+.5))
local xx,yy=trans:transformPoint(0,0)
local tty=0.8/font:getHeight()
local ttx=font:getWidth(sctext)*tty
g.translate(bw-ttx,-1.1)
g.scale(tty)
g.setColor(1,1-taintd,1-taintd)
g.print(sctext)
g.pop()
end
2023-03-28 08:42:05 +03:00
if not falltest then
g.setStencilTest("greater",0)
end
for x=1,bw do
for y=1,bh do
g.push()
local tx,ty=x,y
local anim=anims[pti(x,y)]
if anim then
tx,ty=anim.cx or x, anim.cy or y
end
g.translate(tx-0.5,ty-0.5)
if isgem(board[x][y]) then
drawfig(board[x][y])
end
g.pop()
end
end
for x,falling in ipairs(falling) do
2023-03-30 04:52:00 +03:00
for fall,_ in next,falling do
2023-03-28 08:42:05 +03:00
for i,c in ipairs(fall.figs) do
g.push("all")
local tx,ty=fall.x,fall.y-i+1
g.translate(tx-0.5,ty-0.5)
if isgem(c) then
drawfig(c)
end
g.pop()
end
end
end
2023-03-30 04:52:00 +03:00
for v,_ in next,booms do
2023-03-28 08:42:05 +03:00
g.push("all")
local tx,ty=v.x,v.y
g.translate(tx-0.5,ty-0.5)
drawfig(v.c,v.a)
g.pop()
end
g.setStencilTest()
g.setColor(0.2,0.2,0.2)
2023-04-12 11:11:12 +03:00
g.setLineWidth(g.getLineWidth()*0.5)
2023-03-28 08:42:05 +03:00
g.rectangle("line",0,0,bw,bh)
g.pop()
end
local function fall(l)
local cols={}
2023-03-30 04:52:00 +03:00
for k,v in next,l do
2023-03-28 08:42:05 +03:00
local x,y=unpack(v)
cols[x]=cols[x] or {l={},m={}}
cols.l[#cols+1]=y
cols.m[y]=true
end
end
local killall
local function kill(x,y,rc)
if not board[x][y] then print("Whar") return end
if board[x][y].super=="charge" then
bat=math.min(2,bat+0.1)
end
do
local tx,ty=x,y
local anim=anims[pti(x,y)]
if anim then
tx,ty=anim.cx,anim.cy
end
booms[{
x=tx,y=ty,
a=1,c=board[x][y] or mgobjs[4]
}]=true
end
if rc then
board[x][y]=rc
return true
end
board[x][y]=nil
local fall={}
for y=y-1,gem and 1 or (-bh+1),-1 do
if board[x][y] then
if not fall.figs then
fall.x,fall.y=x,y
fall.figs={}
fall.vel=0
falling[x][fall]=true
end
fall.figs[#fall.figs+1]=board[x][y]
board[x][y]=nil
elseif fall.figs then
fall={}
end
end
local my,mfall=math.huge
local unfell={}
local yls={}
local cx=x
for x=1,bw do
local yl
for y=bh,0,-1 do
if not board[x][y] then
yl=y
break
end
end
unfell[x]={}
local tt={}
2023-03-30 04:52:00 +03:00
for k,v in next,falling[x] do
2023-03-28 08:42:05 +03:00
tt[#tt+1]=k
end
table.sort(tt,function(a,b)
return a.y>b.y
end)
for _,fall in ipairs(tt) do
if cx==x and fall.y<my then
my=fall.y
mfall=fall
end
for k,v in ipairs(fall.figs) do
unfell[x][yl]={board[x][yl]}
board[x][yl]=v
yl=yl-1
end
end
yls[x]=yl
end
local yl=yls[x]
if not mfall then
mfall={x=x,y=0,vel=0,figs={}}
falling[x][mfall]=true
end
local ll=#mfall.figs+1
mfall.figs[ll]=randgem()
local aa={}
unfell[x][yls[x]]=unfell[x][yls[x]] or {board[x][yls[x]]}
board[x][yls[x]]=mfall.figs[ll]
local ccc=0
if love.keyboard.isDown("f6") then
2023-03-30 04:52:00 +03:00
for x,falling in next,falling do
for fall,_ in next,falling do
2023-03-28 08:42:05 +03:00
falling[fall]=nil
end
end
return
end
local occ=mfall.figs[ll]
while check(x,yls[x]) do
mfall.figs[ll]=nextgem(mfall.figs[ll])
board[x][yls[x]]=mfall.figs[ll]
if eqgem(mfall.figs[ll],occ) then break end
end
2023-03-30 04:52:00 +03:00
for x,uf in next,unfell do
for y,v in next,uf do
2023-03-28 08:42:05 +03:00
board[x][y]=v[1]
end
end
cc=math.min(#colors,cc+((0.1/(bw*bh))/((cc/3)^2)))
end
2023-04-12 11:11:12 +03:00
local sfxs={}
2023-03-28 08:42:05 +03:00
killall=function(kills,b,...)
if not kills then return end
if b then
2023-03-30 04:52:00 +03:00
for k,v in next,b do
2023-03-28 08:42:05 +03:00
kills[k]=v
end
return killall(kills,...)
end
local tt={}
2023-03-29 12:31:42 +03:00
local seen={}
local news=true
while news do
news=false
local ko
kills,ko={},kills
2023-03-30 04:52:00 +03:00
for k,v in next,ko do
2023-03-29 12:31:42 +03:00
kills[k]=v
if not seen[k] then
local x,y=unpack(v)
local c=board[v[1]][v[2]]
seen[k]=true
if isgem(c) and c.super=="lines" then
for x=1,bw do
local i=pti(x,y)
if board[x][y] and not kills[i] then
news=true
kills[i]={x,y}
end
end
for y=1,bh do
local i=pti(x,y)
if board[x][y] and not kills[i] then
news=true
kills[i]={x,y}
end
end
2023-03-28 08:42:05 +03:00
end
2023-03-29 12:31:42 +03:00
if isgem(c) then
local mks={}
megascan(x,y,c,mks)
2023-03-30 04:52:00 +03:00
for k,v in next,mks do
2023-03-29 12:31:42 +03:00
if not kills[k] then
kills[k]=v
news=true
end
end
2023-03-28 08:42:05 +03:00
end
end
end
end
2023-03-30 04:52:00 +03:00
for k,v in next,kills do
2023-03-28 08:42:05 +03:00
tt[#tt+1]=v
end
table.sort(tt,function(a,b)
return b[2]>a[2] or b[1]>b[1]
end)
local checks={}
for k,v in ipairs(tt) do
local a=kill(unpack(v))
if a then
checks[k]=v
end
end
local rm,oam,obm={},{},{}
2023-03-30 04:52:00 +03:00
for k,v in next,checks do
2023-03-28 08:42:05 +03:00
local x,y=unpack(v)
check(x,y,rm,oam,obm)
end
2023-04-12 11:11:12 +03:00
if #tt>0 then
local boom=sfx.boom:clone()
boom:setVolume(math.min(0.8,0.5+(#tt/10)*0.5))
boom:setPitch(1.2-math.min(1.2-0.5,#tt/30))
boom:play()
sfxs[boom]=true
end
2023-03-28 08:42:05 +03:00
if next(rm) then
killall(rm)
end
score=score+#tt
end
local function dropall(off,die)
for x=1,bw do
falling[x]=falling[x] or {}
local fall={
x=x,y=bh+(off or 0),
vel=0,
figs={}
}
falling[x][fall]=true
for y=bh,1,-1 do
fall.figs[#fall.figs+1]=board[x][y]
board[x][y]=nil
end
end
if die then
2023-03-30 04:52:00 +03:00
for x,falling in next,falling do
for fall,_ in next,falling do
2023-03-28 08:42:05 +03:00
fall.die=true
end
end
end
end
local function fillboard()
for x=1,bw do
board[x]={}
for y=1,bh do
local a=randgem()
board[x][y]=a
end
end
for n=1,math.huge do
local good=true
local rm={}
local kills
for x=1,bw do
for y=1,bh do
kills=check(x,y,rm) or kills
end
end
if not next(rm) then break end
2023-03-30 04:52:00 +03:00
for k,v in next,rm do
2023-03-28 08:42:05 +03:00
local x,y=unpack(v)
board[x][y]=randgem()
end
end
dropall(-bh)
end
2023-03-29 13:01:07 +03:00
local function resboard()
cc=3
score=0
bat=1
2023-03-30 04:52:00 +03:00
if not dbg then
taint=0
end
2023-03-29 13:01:07 +03:00
gemrng=love.math.newRandomGenerator(991)
tochar=bw*bh+gemrng:random(bw)
fillboard()
end
2023-03-28 08:42:05 +03:00
function love.load()
2023-03-29 13:01:07 +03:00
resboard()
2023-03-28 08:42:05 +03:00
end
function love.mousepressed(x,y,b)
x,y=trans:inverseTransformPoint(x,y)
x,y=x+1-0.5,y+1-0.5
local ix,iy=math.floor(x+.5),math.floor(y+.5)
if b==2 and dbg then
for ix=ix-50,iy+50 do
for iy=iy-50,iy+50 do
if board[ix] and board[ix][iy] and math.random()>0.1 then
kill(ix,iy)
end
end end
end
if b~=1 then return end
running=true
if ix<1 or ix>bw or
iy<1 or iy>bh
then
return
end
if grabbed then
return
end
grabbed={
ix,iy,
ix-x,iy-y,
}
end
function love.mousereleased(x,y,b)
if b~=1 then return end
if grabbed then
local ix,iy,ox,oy,px,py=unpack(grabbed)
if ix and px and (ix~=px or iy~=py) then
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
2023-03-29 12:31:42 +03:00
local kills=check(ix,iy,check(px,py))
if kills and board[ix][iy] and board[px][py] then
megascan(ix,iy,board[ix][iy],megascan(px,py,board[px][py],kills))
2023-03-28 08:42:05 +03:00
local ii,pi=pti(ix,iy),pti(px,py)
local ania,anib=anims[ii],anims[pi]
anims[ii],anims[pi]=anib,ania
ania=ania or {x=ix,y=iy}
anib=anib or {x=px,y=py}
ania.x,anib.x=anib.x,ania.x
ania.y,anib.y=anib.y,ania.y
grabbed=nil
killall(kills)
return
else
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
end
end
grabbed=nil
smtar(ix,iy,ix,iy)
if px then
smtar(px,py,px,py)
end
return
end
end
local gacc=50
-- i forgor how intersections work so here's a thingy to figure it out
-- A1-----A2
-- B1-----B2
--
-- B1-----B2
-- A1-----A2
local function inters(a1,a2,b1,b2)
return
(a1<=b1 and a2>=b1)
or (b1<=a1 and b2>=a1)
end
local function negdiff(a,b)
return math.abs(a-b)<0.01
end
local function sign(a)
return a>0 and 1 or (a<0 and -1 or 0)
end
local function interp(a,b,dt)
return a+sign(b-a)*math.min((b-a)*sign(b-a),math.max(dt,(b-a)*sign(b-a)*math.max(dt,0.01)*10))
end
2023-03-29 13:19:08 +03:00
function love.mousemoved()
if grabbed then
local x,y,ox,oy,px,py=unpack(grabbed)
local mx,my=love.mouse.getPosition()
mx,my=trans:inverseTransformPoint(mx,my)
mx,my=mx+1-0.5+ox,my+1-0.5+oy
mx,my=math.floor(mx+.5),math.floor(my+.5)
if math.abs(x-mx)>math.abs(y-my) then
mx,my=math.min(bw,math.max(1,x+sign(mx-x))),y
elseif math.abs(y-my)>0 then
my,mx=math.min(bh,math.max(1,y+sign(my-y))),x
end
if px then
smtar(px,py,px,py)
end
grabbed[5],grabbed[6]=mx,my
if not board[x][y] then
elseif board[mx][my] then
smtar(mx,my,x,y)
smtar(x,y,mx,my)
end
end
end
2023-04-12 11:11:12 +03:00
local ttt=0
2023-03-28 08:42:05 +03:00
function love.update(dt)
2023-03-30 04:52:00 +03:00
if hookdbg then
ltest=0
end
2023-04-12 11:11:12 +03:00
ttt=ttt+dt
2023-03-29 12:31:42 +03:00
dt=math.min(dt,0.2)*(speeds[slow])
2023-03-29 22:58:13 +03:00
accumdt=math.min(0.6,accumdt+dt)
2023-04-12 11:11:12 +03:00
local fdt=1/tps
while accumdt>=fdt do
local dt=fdt
2023-03-28 08:42:05 +03:00
accumdt=accumdt-dt
2023-04-12 11:11:12 +03:00
tpsl[#tpsl+1]=ttt
while ttt-tpsl[1]>1 do
table.remove(tpsl,1)
end
rtps=#tpsl
2023-03-29 12:31:42 +03:00
if running and playdbg then
2023-03-29 20:04:45 +03:00
local gc=0
local tc=0
for x=1,bw do
for y=1,bh do
gc=gc+(board[x][y] and 1 or 0)
tc=tc+1
end end
2023-03-29 22:58:13 +03:00
if gc/tc>0.4 then
2023-03-29 20:04:45 +03:00
local goods={}
for _=1,1000 do
2023-04-12 11:11:12 +03:00
local ix,iy=gemrng:random(1,bw),gemrng:random(1,bh)
2023-03-29 20:04:45 +03:00
local px,py=0,0
while px<1 or py<1 or px>bw or py>bh do
local ox,oy=unpack(({{1,0},{-1,0},{0,1},{0,-1}})[math.random(1,4)])
px,py=ix+ox,iy+oy
end
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
local kills=check(ix,iy,check(px,py))
local kc=0
2023-03-30 04:52:00 +03:00
for k,v in next,kills or {} do
2023-03-29 20:04:45 +03:00
if v[3] and v[3].super=="color" then
kc=kc+50
elseif v[3] then
kc=kc+20
end
kc=kc+1
end
if kills and board[ix][iy] and board[px][py] then
goods[#goods+1]={ix,iy,px,py,kills,kc}
end
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
2023-03-29 12:31:42 +03:00
end
2023-03-29 20:04:45 +03:00
table.sort(goods,function(a,b)
return a[6]>b[6]
end)
if #goods>0 then
local ix,iy,px,py,kills=unpack(goods[1])
2023-03-29 12:31:42 +03:00
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
2023-03-29 20:04:45 +03:00
megascan(ix,iy,board[ix][iy],megascan(px,py,board[px][py],kills))
killall(kills)
2023-03-29 12:31:42 +03:00
end
end
end
2023-03-28 08:42:05 +03:00
if running then
bat=math.max(0,bat-dt*0.015*(math.max(bat,0.0625)^0.5))
batd=interp(batd,bat,dt)
scored=interp(scored,score,dt)
2023-03-30 04:52:00 +03:00
taintd=interp(taintd,taint,dt)
2023-03-28 08:42:05 +03:00
end
if bat==0 and not dying then
dying=true
dropall(0,true)
end
animc=0
entc=0
boomc=0
2023-03-30 04:52:00 +03:00
for k,v in next,anims do
2023-03-28 08:42:05 +03:00
animc=animc+1
v.cx=interp(v.cx,v.tx,dt*2)
v.cy=interp(v.cy,v.ty,dt*2)
if negdiff(v.cx,v.x) and negdiff(v.cy,v.y) then
anims[k]=nil
end
end
2023-04-12 11:11:12 +03:00
sfxc=0
for k,_ in next,sfxs do
if k:isPlaying() then
sfxc=sfxc+1
else
sfxs[k]=nil
end
end
2023-03-28 08:42:05 +03:00
local tk={}
if running then
2023-04-12 11:11:12 +03:00
local unfallc=0
2023-03-28 08:42:05 +03:00
for x,falling in ipairs(falling) do
2023-03-30 04:52:00 +03:00
for fall,_ in next,falling do
2023-03-28 08:42:05 +03:00
entc=entc+1
fall.vel=fall.vel+dt*gacc
fall.y=fall.y+fall.vel*dt
local iy=math.floor(fall.y)
2023-03-30 04:52:00 +03:00
for fallb,_ in next,falling do
2023-03-28 08:42:05 +03:00
if fall~=fallb and inters(
fall.y-#fall.figs+1-0.5,fall.y+0.5,
fallb.y-#fallb.figs+1-0.5,fallb.y+0.5
) and fall.die==fallb.die then
local wa,wb=#fall.figs,#fallb.figs
fall.vel=(fall.vel*wa+fallb.vel*wb)/(wa+wb)
if fallb.y<fall.y then
local ff=#fall.figs
for i,fig in ipairs(fallb.figs) do
fall.figs[ff+i]=fig
end
else
local tt={}
for i,fig in ipairs(fall.figs) do
tt[i]=fig
end
for i,fig in ipairs(fallb.figs) do
fall.figs[i]=fig
end
local ff=#fallb.figs
for i,fig in ipairs(tt) do
fall.figs[ff+i]=fig
end
fall.y=fallb.y
end
falling[fallb]=nil
end
end
if board[x][iy+1] or (not fall.die and {iy>=bh} or {iy>=bh+#fall.figs})[1] then
falling[fall]=nil
if not fall.die then
2023-04-12 11:11:12 +03:00
unfallc=unfallc+#fall.figs*(fall.vel/30)
2023-03-28 08:42:05 +03:00
local off=math.min(iy,bh)
for i,fig in ipairs(fall.figs) do
while board[x][off] do
off=off-1
end
if off<=bh and off>=1 then
board[x][off]=fig
end
off=off-1
end
for i=off+1,off+#fall.figs do
tk[#tk+1]={x,i}
end
end
end
end
end
2023-04-12 11:11:12 +03:00
if unfallc>0 then
local fall=sfx.fall:clone()
fall:setVolume(math.min(1,unfallc/10))
fall:play()
end
2023-03-28 08:42:05 +03:00
end
if entc==0 and dying then
dying=false
running=false
2023-03-29 13:01:07 +03:00
resboard()
2023-03-29 13:09:02 +03:00
end
if entc==0 and running then
2023-03-29 13:01:07 +03:00
toplchi=toplchi-dt
if toplchi<0 then
toplchi=toplchi+plchint
local good=false
for ix=1,bw do
for iy=1,bh do
2023-03-30 04:52:00 +03:00
for _,a in next,{{1,0},{-1,0},{0,1},{0,-1}} do
2023-03-29 13:01:07 +03:00
local px,py=ix+a[1],iy+a[2]
if px>=1 and py>=1 and px<=bw and py<=bh then
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
good=good or check(ix,iy,check(px,py))
board[ix][iy],board[px][py]=
board[px][py],board[ix][iy]
end
end end end
if not good then dropall(0,true)fillboard() end
end
else
toplchi=plchint
2023-03-28 08:42:05 +03:00
end
local oam,obm,rm={},{},{}
2023-04-12 11:11:12 +03:00
local loopc=0
2023-03-30 04:52:00 +03:00
for k,v in next,tk do
2023-04-12 11:11:12 +03:00
--[[loopc=loopc+1
if loopc>1000 then
error("bai"..loopc)
end]]
2023-03-28 08:42:05 +03:00
local x,y=unpack(v)
check(x,y,rm,oam,obm)
end
killall(rm)
2023-03-30 04:52:00 +03:00
for v,_ in next,booms do
2023-03-28 08:42:05 +03:00
boomc=boomc+1
v.a=v.a-dt/math.abs(v.a)*4
if v.a<=0.01 then
booms[v]=nil
end
end
tt=tt+dt
end
end
function love.keypressed(k)
local x,y=love.mouse.getPosition()
x,y=trans:inverseTransformPoint(x,y)
x,y=math.floor(x)+1,math.floor(y)+1
x=math.max(1,math.min(bw,x))
y=math.max(1,math.min(bh,y))
2023-04-12 11:11:12 +03:00
local cheat=dbg or taint==1
if k=="escape" then
if not mobile then
love.event.quit()
end
end
2023-03-28 08:42:05 +03:00
if dbg and tonumber(k) then
print(gobjs[tonumber(k)],tonumber(k))
board[x][y]=gobjs[tonumber(k)] or board[x][y]
2023-03-30 04:52:00 +03:00
taint=1
2023-03-28 08:42:05 +03:00
end
if dbg and isgem(board[x][y]) then
local c=board[x][y].c
if k=="h" then
board[x][y]=cgobjs[c]
2023-03-30 04:52:00 +03:00
taint=1
2023-03-28 08:42:05 +03:00
elseif k=="j" then
board[x][y]=lgobjs[c]
2023-03-30 04:52:00 +03:00
taint=1
2023-03-28 08:42:05 +03:00
elseif k=="k" then
board[x][y]=mgobjs[c]
2023-03-30 04:52:00 +03:00
taint=1
2023-03-28 08:42:05 +03:00
end
end
2023-04-12 11:11:12 +03:00
if k=="f2" and cheat then
2023-03-28 08:42:05 +03:00
yes=not yes
elseif k=="f3" then
dbg=not dbg
2023-04-12 11:11:12 +03:00
elseif k=="f4" and cheat then
2023-03-28 08:42:05 +03:00
local unfell={}
local yls={}
local cx=x
for x=1,bw do
local yl
for y=bh,0,-1 do
if not board[x][y] then
yl=y
break
end
end
unfell[x]={}
local tt={}
2023-03-30 04:52:00 +03:00
for k,v in next,falling[x] do
2023-03-28 08:42:05 +03:00
tt[#tt+1]=k
end
table.sort(tt,function(a,b)
return a.y>b.y
end)
for _,fall in ipairs(tt) do
falling[x][fall]=nil
for k,v in ipairs(fall.figs) do
unfell[x][yl]={board[x][yl]}
board[x][yl]=v
yl=yl-1
end
end
yls[x]=yl
end
2023-03-30 04:52:00 +03:00
taint=1
2023-04-12 11:11:12 +03:00
elseif k=="f5" and cheat then
2023-03-29 12:31:42 +03:00
slow=slow%3+1
2023-03-30 04:52:00 +03:00
taint=1
2023-04-12 11:11:12 +03:00
elseif k=="f7" and cheat then
2023-03-28 08:42:05 +03:00
falltest=not falltest
2023-03-30 04:52:00 +03:00
taint=1
2023-04-12 11:11:12 +03:00
elseif k=="f8" and cheat then
2023-03-28 08:42:05 +03:00
bat=bat*0.25
2023-03-30 04:52:00 +03:00
taint=1
2023-04-12 11:11:12 +03:00
elseif k=="f9" and cheat then
2023-03-29 12:31:42 +03:00
bat=bat*2
2023-03-30 04:52:00 +03:00
taint=1
2023-04-12 11:11:12 +03:00
elseif k=="f10" and cheat then
2023-03-29 12:31:42 +03:00
playdbg=not playdbg
2023-03-30 04:52:00 +03:00
taint=1
2023-03-29 22:58:13 +03:00
elseif k=="f11" then
love.window.setFullscreen(not love.window.getFullscreen())
2023-03-28 08:42:05 +03:00
end
end
function love.draw()
local sw,sh=g.getDimensions()
local ww=math.min(sw,sh)
local y
if falltest then
ww=math.min(sw,sh)*0.5
y=(sh)/2
end
local x,y=(sw-ww)/2,y or (sh-ww)/2
2023-04-12 11:11:12 +03:00
setbsize(x+ww*0.1,y+ww*0.1+ww/10*0.3,ww*0.8,ww*0.8)
2023-03-28 08:42:05 +03:00
if yes then
drawboard()
end
2023-04-12 11:11:12 +03:00
if dbg then
g.push("all")
g.scale(2,2)
love.graphics.print(("FPS: %i; TPS: %i; dt: %.2f; speed: %f; anims: %i; fallings: %i; booms: %i; sounds counted: %i; sounds: %i"):format(
love.timer.getFPS(),
rtps,
math.floor(love.timer.getDelta()*100000)/100,
speeds[slow],
animc, entc, boomc, sfxc,
love.audio.getActiveSourceCount()
))
g.pop()
end
2023-03-28 08:42:05 +03:00
end