529 lines
14 KiB
Lua
529 lines
14 KiB
Lua
pico-8 cartridge // http://www.pico-8.com
|
|
version 41
|
|
__lua__
|
|
-- panel extreme
|
|
-- by kistaro windrider
|
|
-------------------------------
|
|
|
|
-- bsd 0-clause license
|
|
-------------------------------
|
|
-- copyright 2023 kistaro windrider
|
|
--
|
|
-- permission to use, copy,
|
|
-- modify, and/or distribute
|
|
-- this software for any
|
|
-- purpose with or without fee
|
|
-- is hereby granted.
|
|
--
|
|
-- the software is provided
|
|
-- "as is" and the author
|
|
-- disclaims all warranties
|
|
-- with regard to this software
|
|
-- including all implied
|
|
-- warranties of merchantability
|
|
-- and fitness. in no event
|
|
-- shall the author be liable
|
|
-- for any special, direct,
|
|
-- indirect, or consequential
|
|
-- damages or any damages
|
|
-- whatsoever resulting from
|
|
-- loss of use, data or profits,
|
|
-- whether in an action of
|
|
-- contract, negligence or
|
|
-- other tortious action,
|
|
-- arising out of or in
|
|
-- connection with the use or
|
|
-- performance of this software.
|
|
-------------------------------
|
|
|
|
-------------------------------
|
|
-- credits -
|
|
-------------------------------
|
|
-- wysiwyg p8scii control -
|
|
-- code editor (used for all -
|
|
-- fancy text) -- eeooty -
|
|
-- https://www.lexaloffle.com/bbs/?tid=52315
|
|
-------------------------------
|
|
|
|
-- major, release, revision
|
|
-- change major version to break
|
|
-- save compatibility
|
|
version={0,0,1}
|
|
|
|
-------------------------------
|
|
-- globals
|
|
-------------------------------
|
|
-- mode: table
|
|
-- {:update(), :draw()}.
|
|
-- receives frame callbacks.
|
|
-- version: [3]int constant.
|
|
-- major, minor, release.
|
|
-- change major version to
|
|
-- break save compatibility.
|
|
-- constant.
|
|
-------------------------------
|
|
|
|
function _init()
|
|
cartdata("panel_extreme"..version[1])
|
|
|
|
-- hi-color mode: 15 is bg
|
|
-- set color 15 to gradient background
|
|
poke(0x5f5f,0x3f)
|
|
--blend lines
|
|
memset(0x5f70,0xaa,16)
|
|
|
|
mode = init_title()
|
|
end
|
|
|
|
function _update60()
|
|
mode:update()
|
|
end
|
|
|
|
function _draw()
|
|
mode:draw()
|
|
end
|
|
|
|
-- if t[mname] is a thing,
|
|
-- invoke it as a method. else,
|
|
-- try each object in t
|
|
function outer_or_each_opt(t, mname)
|
|
local fun = t[mname]
|
|
if fun then
|
|
fun(t)
|
|
return
|
|
end
|
|
foreach(t, function(o)
|
|
local f = o[mname]
|
|
if(f) f(o)
|
|
end)
|
|
end
|
|
|
|
-- generate standard "overlay"
|
|
-- constructor for type tt.
|
|
-- if more is defined, generated
|
|
-- new calls more(ret) after
|
|
-- ret is definitely not nil
|
|
-- before calling setmetatable.
|
|
-- use to initialize mutables.
|
|
function mknew(tt, more)
|
|
local mt = {__index=tt}
|
|
-- check "more" only once ever
|
|
if more then
|
|
tt.new = function(ret)
|
|
if (not ret) ret = {}
|
|
more(ret)
|
|
setmetatable(ret, mt)
|
|
return ret
|
|
end
|
|
else
|
|
tt.new=function(ret)
|
|
if (not ret) ret = {}
|
|
setmetatable(ret, mt)
|
|
return ret
|
|
end
|
|
end
|
|
end
|
|
|
|
-->8
|
|
-- title
|
|
-- (currently a placeholder)
|
|
|
|
function init_title()
|
|
|
|
pal({[0]=0x82,0x82,0x84,0x84,4,4,0x89,0x89,0x8e,0x8e,0x8f,0x8f,15,15,0x87,0x87},2)
|
|
local antbar = ants.new{
|
|
progress=-0.5,
|
|
bgcolor=8,
|
|
fgcolor=10,
|
|
trcolor=9,
|
|
speed=1/15,
|
|
w=128,h=2}
|
|
|
|
return view.of{
|
|
bg.new{c=15},
|
|
view.new{
|
|
views=printz"⁶j30⁵ii⁶w⁶tᶜ9a e\n⁶j00⁵ijᶜcp n l\n⁶j04³iᶜ2extreme\n⁶j04³i⁶=ᶜeextreme\n⁶j04³hᶜ8extreme\n\0",
|
|
update = function(self)
|
|
self.y=20+8*sin(time()/2.1)
|
|
self.x=32+6*cos(time()/3.7)
|
|
end,
|
|
},
|
|
{update = function()
|
|
local p = antbar.progress + 0.003
|
|
if p > 1.5 then
|
|
p = -0.5
|
|
antbar.speed += 1/30
|
|
end
|
|
antbar.progress = p
|
|
end},
|
|
view.new{
|
|
views=antbar,
|
|
y=50,h=2,
|
|
},
|
|
}
|
|
end
|
|
|
|
-->8
|
|
-- window manager
|
|
|
|
-------------------------------
|
|
-- view
|
|
-------------------------------
|
|
-- composits drawable items.
|
|
-- add items to .views to
|
|
-- composit them. x and y are
|
|
-- relative reverse camera
|
|
-- offsets. drawable items will
|
|
-- observe appropriate incoming
|
|
-- camera and clip state.
|
|
-- clipping respects existing
|
|
-- clipping so stacked views
|
|
-- intersect.
|
|
-------------------------------
|
|
view = {
|
|
x=0,
|
|
y=0,
|
|
w=128,
|
|
h=128,
|
|
}
|
|
mknew(view, function(x)
|
|
if (not x.views) x.views = {}
|
|
end)
|
|
|
|
function view.of(subviews)
|
|
return view.new{views=subviews}
|
|
end
|
|
|
|
function view:update()
|
|
outer_or_each_opt(self.views, "update")
|
|
end
|
|
|
|
function view:draw()
|
|
local oldcam, oldclip = $0x5f28, $0x5f20
|
|
poke2(0x5f28, %0x5f28-self.x)
|
|
poke2(0x5f2a, %0x5f2a-self.y)
|
|
clip(-%0x5f28, -%0x5f2a, self.w, self.h, true)
|
|
local v = self.views
|
|
outer_or_each_opt(self.views, "draw")
|
|
poke4(0x5f20, oldclip)
|
|
poke4(0x5f28, oldcam)
|
|
end
|
|
|
|
-- draws opaque rectangles.
|
|
-- default bg is equivalent to
|
|
-- clip-aware cls.
|
|
-- restores prior fill palette.
|
|
bg = {
|
|
x=0,y=0,w=128,h=128,fp=0,c=0
|
|
}
|
|
mknew(bg)
|
|
|
|
function bg:draw()
|
|
local oldfp=fillp(self.fp)
|
|
rectfill(self.x,self.y,self.x+self.w,self.y+self.h,self.c)
|
|
fillp(oldfp)
|
|
end
|
|
|
|
-------------------------------
|
|
-- animator
|
|
-------------------------------
|
|
-- animator is a drawable item
|
|
-- that manages a linked list of
|
|
-- temporary drawables. a
|
|
-- temporary drawable is dropped
|
|
-- when its :update returns
|
|
-- a non-false value.
|
|
-------------------------------
|
|
animator = {}
|
|
mknew(animator)
|
|
|
|
function animator:update()
|
|
local p,n=self, self.next
|
|
while n do
|
|
if n.item:update() then
|
|
local nn = n.next
|
|
if (not nn) self.tail = p
|
|
p.next = n.next
|
|
else
|
|
p = n
|
|
end
|
|
n = p.next
|
|
end
|
|
end
|
|
|
|
function animator:draw()
|
|
local n = self.next
|
|
while n do
|
|
n.item:draw()
|
|
n = n.next
|
|
end
|
|
end
|
|
|
|
-- add a new drawable under all
|
|
-- existing other items.
|
|
-- (it draws first)
|
|
function animator:push_under(i)
|
|
self.next={next=self.next, item=i}
|
|
end
|
|
|
|
-- add a new drawable over all
|
|
-- existing other items.
|
|
-- (it draws last)
|
|
function animator:push_over(i)
|
|
local target, node = self.tail or self, {item=i}
|
|
target.next=node
|
|
self.tail=node
|
|
end
|
|
|
|
|
|
-->8
|
|
-- panel drawing
|
|
|
|
-- empty panel placeholder
|
|
nopanel = {}
|
|
|
|
-- panel in ordinary state
|
|
panel = {
|
|
-- plt: palette as table
|
|
-- sx, sy: ulc of emblem on
|
|
-- sprite sheet
|
|
-- ey: y offset for emblem;
|
|
-- usually 2, can wiggle
|
|
-- as: animation state
|
|
-- 0 == plain
|
|
-- negative == mid-fall
|
|
-- positive == bounce
|
|
-- frames left
|
|
}
|
|
mknew(panel)
|
|
|
|
jiggle = split"3,3,3,2,2,2,3,3,2,2,1,1,2,2,3,3,2,1"
|
|
|
|
-- palettes for blocks:
|
|
-- lit, bg, shadow, emblem.
|
|
-- declared separately to
|
|
-- avoid reconstructiong for
|
|
-- every panel spawned
|
|
redblkp = {9,8,3,7}
|
|
ylwblkp = {10,9,4,7}
|
|
grnblkp = {6,11,3,7}
|
|
blublkp = {7,12,13,7}
|
|
prpblkp = {14,13,2,7}
|
|
|
|
newblock = {
|
|
function()
|
|
return panel.new{
|
|
plt=redblkp,
|
|
sx=83,sy=1,
|
|
ey=2, as=0,
|
|
}
|
|
end,
|
|
function()
|
|
return panel.new{
|
|
plt=ylwblkp,
|
|
sx=83,sy=11,
|
|
ey=2,as=0,
|
|
}
|
|
end,
|
|
function()
|
|
return panel.new{
|
|
plt=grnblkp,
|
|
sx=78,sy=11,
|
|
ey=2,as=0,
|
|
}
|
|
end,
|
|
function()
|
|
return panel.new{
|
|
plt=blublkp,
|
|
sx=83,sy=6,
|
|
ey=2,as=0,
|
|
}
|
|
end,
|
|
function()
|
|
return panel.new{
|
|
plt=prpblkp,
|
|
sx=73,sy=11,
|
|
ey=2,as=0,
|
|
}
|
|
end,
|
|
}
|
|
|
|
function panel:update()
|
|
local dat_as = self.as
|
|
if (dat_as < 0) self.ey = 1
|
|
if (dat_as == 0) self.ey = 2
|
|
if dat_as > 0 then
|
|
self.ey = jiggle[dat_as]
|
|
self.as -= 1
|
|
end
|
|
end
|
|
|
|
function panel:draw()
|
|
pal(self.plt)
|
|
sspr(72,0,9,9)
|
|
sspr(self.sx,self.sy,
|
|
5,5,
|
|
2,self.ey)
|
|
end
|
|
-->8
|
|
-- general drawing
|
|
function printz(str)
|
|
return {draw=function()
|
|
print(str, 0, 0)
|
|
end}
|
|
end
|
|
|
|
-- horizontal marching ants
|
|
ants = {
|
|
w=60, h=1,
|
|
stride=10,
|
|
|
|
-- bgcolor=0, --nil: transparent
|
|
ldcolor=7,
|
|
fgcolor=6,
|
|
-- trcolor=5, --nil: no trailer
|
|
|
|
speed=2/60,
|
|
offset=0,
|
|
|
|
progress=0.0,
|
|
}
|
|
mknew(ants)
|
|
|
|
function ants:update()
|
|
local stride = self.stride
|
|
local off = self.offset + self.speed * stride
|
|
if (off > stride) off -= stride
|
|
self.offset = off
|
|
end
|
|
|
|
function ants:draw()
|
|
local w,h,s,p,bg=self.w, self.h, self.stride,self.progress,self.bgcolor
|
|
if (bg) rectfill(0,0,w,h,bg)
|
|
if (p<=0) return
|
|
local x0 = (self.offset-s)&-1
|
|
local bw = (p*s)&-1
|
|
if bw > 1 then
|
|
local bwm2,c = bw-2,self.fgcolor
|
|
for x=x0,w,s do
|
|
rectfill(x,0,x+bwm2,h,c)
|
|
end
|
|
end
|
|
if bw > 0 then
|
|
local c = self.ldcolor
|
|
for x=x0+bw-1,w,s do
|
|
rectfill(x,0,x,h,c)
|
|
end
|
|
end
|
|
local c = self.trcolor
|
|
if p < 1 and c then
|
|
for x = x0-1+s,w,s do
|
|
rectfill(x,0,x,h,c)
|
|
end
|
|
end
|
|
end
|
|
|
|
-->8
|
|
-- gameplay logic
|
|
|
|
game={
|
|
incoming_frac = 0
|
|
speed = 0
|
|
gravity_lag = 30
|
|
pop_lag = 20
|
|
|
|
stop_frames = 0
|
|
stop_max = 1
|
|
life = 180
|
|
life_max = 180
|
|
}
|
|
|
|
mknew(game, function(ret)
|
|
local board = {}
|
|
for i=1,12 do
|
|
board[i] = {
|
|
nopanel, nopanel, nopanel, nopanel, nopanel, nopanel,
|
|
}
|
|
ret.board = board
|
|
ret.garbage_queue = {}
|
|
ret.garbage_source = source.new()
|
|
ret.floor_source = source.new()
|
|
end
|
|
end)
|
|
|
|
function game:update()
|
|
end
|
|
|
|
function game:draw()
|
|
end
|
|
|
|
function shuffle(tbl)
|
|
local n = #tbl
|
|
for i=1,n-1 do
|
|
local idx = (rnd(n-i+1)&-1)+i
|
|
if (idx != i) tbl[idx], tbl[i] = tbl[i], tbl[idx]
|
|
end
|
|
end
|
|
|
|
source={
|
|
lumps = 3
|
|
metalumps = 3
|
|
metalumpiness = 2
|
|
}
|
|
mknew(source, function(ret)
|
|
ret.bucket = {}
|
|
ret.lumpqueue = {}
|
|
ret.rejects = {}
|
|
end)
|
|
|
|
function source:pick()
|
|
local lq, b := self.lumpqueue, bucket
|
|
for i=#lq/self.metalumpiness,self.metalumps do
|
|
local p := rnd(newblock)
|
|
for i=1,self.metalumpiness do
|
|
add(lq, p)
|
|
end
|
|
-- todo: draw individual panels
|
|
-- note: individual panels
|
|
-- must derive from the prototypes.
|
|
-- still not sure what the best
|
|
-- bag algorithm is; I think this
|
|
-- algorithm fills too much.
|
|
-- todo: rewrite to only redraw
|
|
-- when only one bag remains.
|
|
|
|
-- todo: actual pick algorithm
|
|
-- todo: rejection and redraw algorithm
|
|
end
|
|
end
|
|
|
|
|
|
__gfx__
|
|
0000000000111000011011000000000009999900066666000eeeee00077777000aaaaa0001111111000000000000000000000000000000000000000000000000
|
|
00000000012221001221221000000000988888206bbbbb30eddddd207cccccd0a999994012222222300040400000000000000000000000000000000000000000
|
|
00700700121110000112110000000000987878206b77bb30edd7dd207c7cccd0a979794012222222300444440000000000000000000000000000000000000000
|
|
00077000121000000012100000000000987778206b777b30ed777d207c77ccd0a997994012222222300444440000000000000000000000000000000000000000
|
|
00077000121000000001000000000000988788206bb77b30edd7dd207c777cd0a979794012222222300044400000000000000000000000000000000000000000
|
|
00700700010000000001000000000000988888206bbbbb30eddddd207cccccd0a999994012222222300004000000000000000000000000000000000000000000
|
|
000000000000000000121000000000000222220003333300022222000ddddd000444440012222222300444440000000000000000000000000000000000000000
|
|
00000000000000000001000000000000000000000000000000000000000000000000000012222222300444400000000000000000000000000000000000000000
|
|
00000000000000000000000000000000011111004040440004000400000000000000000003333333000444000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000122222304440444044404440000000000000000000000000000440000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000122222300400044040400400007070000000000000000000000400000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000122222300000000000000000007070000000000000040004440004000000000000000000000000000000000000000000
|
|
00000000000000000000000000000000122222304040400004004440000000000000000000444044444044400000000000000000000000000000000000000000
|
|
00000000000000000000000000000000122222300400440040404040007770000000000004444444444044400000000000000000000000000000000000000000
|
|
00000000000000000000000000000000033333004040444004004440000000000000000000444044444444440000000000000000000000000000000000000000
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000040004440444440000000000000000000000000000000000000000
|
|
__map__
|
|
0102020202020203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
2122222222222223000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|