initial commit.
This commit is contained in:
commit
2f38abe0d4
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Kistaro's tic-80 compositor
|
||||
|
||||
TIC-80 port of my Pico-8 compositor, including a lot of Pico-8 camera and clip behaviors that aren't available in TIC-80.
|
255
kistaro-compositor.lua
Normal file
255
kistaro-compositor.lua
Normal file
@ -0,0 +1,255 @@
|
||||
-- title: kistaro-compositor
|
||||
-- author: Kistaro Windrider (kistaro@gmail.com)
|
||||
-- desc: Rendering compositor library. Includes Pico-8 camera features.
|
||||
-- site: https://dragon.style/@kistaro
|
||||
-- license: MIT License
|
||||
-- version: 0.1
|
||||
-- script: lua
|
||||
|
||||
|
||||
function BOOT()
|
||||
end
|
||||
|
||||
function TIC()
|
||||
end
|
||||
|
||||
--stdlib--
|
||||
|
||||
-- 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
|
||||
-- mutable items.
|
||||
function MkNew(tt, more)
|
||||
local mt = {__index=tt}
|
||||
-- check "more" only once ever
|
||||
if more then
|
||||
tt.new = function(ret)
|
||||
ret = ret or {}
|
||||
more(ret)
|
||||
setmetatable(ret, mt)
|
||||
return ret
|
||||
end
|
||||
else
|
||||
tt.new = function(ret)
|
||||
ret = ret or {}
|
||||
setmetatable(ret, mt)
|
||||
return ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--Window compositor--
|
||||
|
||||
CamCtl = {
|
||||
XOff = 0,
|
||||
YOff = 0,
|
||||
XAbsClip = 0,
|
||||
YAbsClip = 0,
|
||||
W = 240,
|
||||
H = 136,
|
||||
OriginStack = {},
|
||||
ClipStack = {},
|
||||
}
|
||||
|
||||
-- Overwrite current camera origin.
|
||||
-- (0, 0) is now this pixel coordinate.
|
||||
function CamCtl:SetAbsOrigin(x, y)
|
||||
self.XOff, self.YOff = x, y
|
||||
end
|
||||
|
||||
-- Push current camera origin onto
|
||||
-- the history stack and set the
|
||||
-- new origin.
|
||||
function CamCtl:PushAbsOrigin(x, y)
|
||||
table.insert(self.OriginStack, {self.XOff, self.YOff})
|
||||
self.XOff, self.YOff = x, y
|
||||
end
|
||||
|
||||
function CamCtl:SetRelOrigin(x, y)
|
||||
self.XOff = self.XOff + x
|
||||
self.YOff = self.Yoff + y
|
||||
end
|
||||
|
||||
function CamCtl:PushRelOrigin(x, y)
|
||||
table.insert(self.OriginStack, {self.XOff, self.YOff})
|
||||
self.XOff = self.XOff + x
|
||||
self.YOff = self.YOff + Y
|
||||
end
|
||||
|
||||
function CamCtl:SetAbsCam(x, y)
|
||||
self.XOff, self.YOff = -x, -y
|
||||
end
|
||||
|
||||
function CamCtl:PushAbsCam(x, y)
|
||||
table.insert(self.OriginStack, {self.XOff, self.YOff})
|
||||
self.XOff, self.YOff = -x, -y
|
||||
end
|
||||
|
||||
function CamCtl:SetRelCam(x, y)
|
||||
self.XOff = self.XOff - x
|
||||
self.YOff = self.YOff - y
|
||||
end
|
||||
|
||||
function CamCtl:PushRelCam(x, y)
|
||||
table.insert(self.OriginStack, {self.XOff, self.YOff})
|
||||
self.XOff = self.XOff - x
|
||||
self.YOff = self.YOff - y
|
||||
end
|
||||
|
||||
function CamCtl:PopOrigin()
|
||||
if #self.OriginStack == 0 then
|
||||
self.XOff, self.YOff = 0, 0
|
||||
return
|
||||
end
|
||||
self.XOff, self.YOff = unpack(table.Remove(self.OriginStack))
|
||||
end
|
||||
CamCtl.PopCam = CamCtl.PopOrigin
|
||||
|
||||
function CamCtl:SetNewClip(x, y, w, h)
|
||||
if x then
|
||||
self.XAbsClip = self.XOff + x
|
||||
self.YAbsClip = self.YOff + y
|
||||
self.W, self.H = w, h
|
||||
clip(self.XAbsClip, self.YAbsClip, self.W, self.H)
|
||||
return
|
||||
end
|
||||
self.XAbsClip, self.YAbsClip, self.W, self.H = 0,0,240,136
|
||||
clip()
|
||||
end
|
||||
|
||||
function CamCtl:PushNewClip(x, y, w, h)
|
||||
table.insert(self.ClipStack, {self.XAbsClip, self.YAbsClip, self.W, self.H}
|
||||
self:SetNewClip(x, y, w, h)
|
||||
end
|
||||
|
||||
function CamCtl:SetReClip(x,y,w,h)
|
||||
if not x then
|
||||
return
|
||||
end
|
||||
|
||||
x = x + self.XOff
|
||||
local x2 = math.min(x + w, self.XAbsClip + self.W)
|
||||
self.XAbsClip = math.max(x, self.XAbsClip)
|
||||
self.W = max(0, x2 - self.XAbsClip)
|
||||
|
||||
y = y + self.YOff
|
||||
local y2 = math.min(y+h, self.YAbsClip + self.H)
|
||||
self.YAbsClip = math.max(y, self.YAbsClip)
|
||||
self.H = max(0, y2 - self.YAbsClip)
|
||||
|
||||
clip(self.XAbsClip, self.YAbsClip, self.W, self.H)
|
||||
end
|
||||
|
||||
function CamCtl:PushReClip(x,y,w,h)
|
||||
table.insert(self.ClipStack, {self.XAbsClip, self.YAbsClip, self.W, self.H}
|
||||
self.SetReClip(x,y,w,h)
|
||||
end
|
||||
|
||||
function CamCtl:PopClip()
|
||||
if #self.ClipStack == 0 then
|
||||
self.XAbsClip, self.YAbsClip, self.W, self.H = 0,0,240,136
|
||||
clip()
|
||||
return
|
||||
end
|
||||
local x,y,w,h = unpack(table.remove(self.ClipStack)))
|
||||
self.XAbsClip, self.YAbsClip, self.W, self.H = x,y,w,h
|
||||
clip(x,y,w,h)
|
||||
end
|
||||
-- Install
|
||||
-- (swizzle all drawing functions!)
|
||||
|
||||
function CamCtl:Install()
|
||||
local adjust_leading_2 = {
|
||||
"circ", "circb",
|
||||
"elli", "ellib",
|
||||
"pix",
|
||||
"rect", "rectb",
|
||||
}
|
||||
for _, fn in ipairs(adjust_leading_2) do
|
||||
local f_orig = _G[fn]
|
||||
_G[fn] = function(x, y, ...)
|
||||
return f_orig(x + self.XOff, y + self.YOff, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local keep_first_adjust_2_opt = {
|
||||
"spr", "font", "print"
|
||||
}
|
||||
for _, fn in ipairs(keep_first_adjust_2_opt) do
|
||||
local f_orig = _G[fn]
|
||||
_G[fn] = function(v, x, y, ...)
|
||||
if x then
|
||||
x = x + self.XOff
|
||||
end
|
||||
if y then
|
||||
y = y + self.YOff
|
||||
end
|
||||
return f_orig(v, x, y, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local tri_family = {"tri", "trib", "textri"}
|
||||
|
||||
for _, fn in ipairs(tri_family) do
|
||||
local f_orig = _G[fn]
|
||||
_G[fn] = function(x1, y1, x2, y2, x3, y3, ...)
|
||||
return f_orig(
|
||||
x1 + self.XOff, y1 + self.YOff,
|
||||
x2 + self.XOff, y2 + self.YOff,
|
||||
x3 + self.XOff, y3 + self.YOff,
|
||||
...
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local map_orig = map
|
||||
map = function(mx, my, w, h, sx, sy, ...)
|
||||
XXX(kistaro): implement!
|
||||
-- if called with no args, calculate new map
|
||||
-- coordinates, clipping at 0, to respect
|
||||
-- camera movement! this will require full tile
|
||||
-- movement to be reflected in mx/my, w and h to
|
||||
-- stay 30 x 17 unless they go to 31 x 18 for
|
||||
-- partial tiles at edges, and sx and sy to become
|
||||
-- offsets. If sx and sy are provided, do the
|
||||
-- obvious thing instead, which is much easier.
|
||||
end
|
||||
|
||||
local line_orig = line
|
||||
line = function(x0, y0, x1, y1, color)
|
||||
return line_orig(
|
||||
x0 + self.XOff, y0 + self.YOff,
|
||||
x1 + self.XOff, y1 + self.YOff,
|
||||
color
|
||||
)
|
||||
end
|
||||
end
|
||||
-- <SPRITES>
|
||||
-- 000:0222220021111110212121102122211021121110211111100111110000000000
|
||||
-- 001:0bbbbb00b9999980b999b980b99bb980b9bbb980b99999800888880000000000
|
||||
-- 002:0555550056666670565566705655567056655670566666700777770000000000
|
||||
-- 003:0444440043333320433433204344432043434320433333200222220000000000
|
||||
-- 004:0ddddd00deeeeef0dededef0deedeef0dededef0deeeeef00fffff0000000000
|
||||
-- </SPRITES>
|
||||
|
||||
-- <WAVES>
|
||||
-- 000:00000000ffffffff00000000ffffffff
|
||||
-- 001:0123456789abcdeffedcba9876543210
|
||||
-- 002:0123456789abcdef0123456789abcdef
|
||||
-- </WAVES>
|
||||
|
||||
-- <SFX>
|
||||
-- 000:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000304000000000
|
||||
-- </SFX>
|
||||
|
||||
-- <TRACKS>
|
||||
-- 000:100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
-- </TRACKS>
|
||||
|
||||
-- <PALETTE>
|
||||
-- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f4be69ce61309940205d
|
||||
-- </PALETTE>
|
||||
|
BIN
kistaro-compositor.tic
Normal file
BIN
kistaro-compositor.tic
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user