diff --git a/panel_extreme.p8 b/panel_extreme.p8 new file mode 100644 index 0000000..e251e46 --- /dev/null +++ b/panel_extreme.p8 @@ -0,0 +1,337 @@ +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. +------------------------------- + +-- 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]) + mode = init_title() +end + +function _update60() + mode:update() +end + +function _draw() + mode:draw() +end + +-- for each object in t, invoke +-- t:mname(), converting mname +-- from string to method name. +-- if there is no method by that +-- name, quietly skip it. +function subeach_opt(t, mname) + 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) + +title = {fidx=1} +mknew(title) + +function init_title() + g_animator = animator.new() + return view.of{ + bg.new(), + {update=boomer}, + g_animator, + titleframe(), + titleframe(), + titleframe(), + titleframe(), + titleframe(), +} +end + +boom = {} +mknew(boom) + +function boom:update() + self.r += 1 + return self.r > 128 +end + +function boom:draw() + circ(self.x, self.y, self.r, rnd(4)\1+7) +end + +function boomer(self) + if rnd() < 0.1 then + g_animator:push_over( + boom.new{ + x=rnd(128), y=rnd(128), r=0 + }) + end +end + +function titleframe() + local tx = title.new{fidx=rnd(#titleglow)\1+1} + local v = view.new{ + x=rnd(63), + y=rnd(121), + w=53, + h=7, + views={bg.new{c=rnd(64)\1,fp=rnd(32768)*2\1},tx} + } + v.update = function(self) + self.x += rnd() - 0.5 + self.y += rnd() - 0.5 + local b = btn() + if (b & 0x1 > 0) self.x -= 0.25 + if (b & 0x2 > 0) self.x += 0.25 + if (b & 0x4 > 0) self.y -= 0.25 + if (b & 0x8 > 0) self.y += 0.25 + if b & 0x10 > 0 then + self.x -= (self.x-42.5)/10 + self.y -= (self.y-60.5)/10 + end + if b & 0x20 > 0 then + self.x += (self.x-42.5)/10 + self.y += (self.y-60.5)/10 + end + view.update(v) + end + return v +end + +-- obnoxious flicker effect +titleglow = split"5,6,7,7,7,7,6,5,1,2,8,9,10,7,10,9,4,5,3,3,11,11,7,11,11,7,11,3,3,1,1,1,1,13,13,13,12,12,7,12,13,1" + +function title:update() + self.fidx += 0.2 + if (self.fidx>#titleglow) self.fidx=1 + self.fcol=titleglow[self.fidx\1] +end + +function title:draw() + rect(0,0,52,6,8) + print("panel extreme", 1, 1, self.fcol) +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() + subeach_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) + subeach_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 +-- board + +__gfx__ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000011010101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000001d5151515d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000151010101510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000010000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000151000000510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000010000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000151000000510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000010000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000151000000510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +000000000000001d5151515d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +00000000000000011010101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +__map__ +0102020202020203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +1112121212121213000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +2122222222222223000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000