Pseudo motion blur using the extended palette + dithering with fillp
.
The crux of making this happen is:
local defaultFills = { 0b0000000000000000, -- solid 0b0000000000000001.1, -- single pixel missing 0b0000010100000101.1, -- 4 pixels missing 0b0101101001011010.1, -- half pixels missing 0b1111101011111010.1, -- 4 pixels rendered 0b1111111111111110.1, -- 1 pixel rendered } -- Derived from https://stackoverflow.com/a/10086034/473961 function resizeAndFill(input, outputLength) assert(outputLength >= 2, "behaviour not defined for n<2") local step = (#input-1)/(outputLength-1) local result = {} for x=1,outputLength do result[x] = input[ceil(0.5 + (x-1)*step)] end return result end function createTrailSystem(shapes) local longestTrail = 0 foreach(shapes, function(shape) shape.trailPositions = shape.trailPositions or {} shape.trails = shape.trails or 1 shape.framesPerTrail = shape.framesPerTrail or 1 -- Normalise the length of .fills to match number of trails shape.fills = resizeAndFill(shape.fills or defaultFills, shape.trails + 1) -- Normalise the length of .colors to match number of trails shape.colors = resizeAndFill(shape.colors or { shape.color }, shape.trails + 1) longestTrail = max(longestTrail, shape.trails) end) return { update=function() foreach(shapes, function(shape) if (#shape.trailPositions > (shape.trails * shape.framesPerTrail)) then -- Remove the oldest / now stale trail deli(shape.trailPositions, 1) end -- Add a new trail at the last position add(shape.trailPositions, { x=shape.x, y=shape.y }) end) end, draw=function() -- Draw all the trail layers at the same time to avoid weird overlay -- artefacts for trail=longestTrail,1,-1 do foreach(shapes, function(shape) if (shape.trails < trail) then return end local frame = ((shape.trails - trail) * shape.framesPerTrail) + 1 if (not shape.trailPositions[frame]) then return end -- +1 for 1-index in lua -- +1 for the actual shape itself local color = shape.colors[shape.trails - trail + 2] local fill = shape.fills[trail + 1] pal(shape.colors[1], color) shape.draw( shape.trailPositions[frame].x, shape.trailPositions[frame].y, shape.colors[1], fill ) end) end foreach(shapes, function(shape) pal(shape.colors[1], shape.colors[1]) shape.draw(shape.x, shape.y, shape.colors[1], shape.fills[1]) end) end } end |
And it's used like so:
local trails local shape = { colors={1,2,3,4}, -- Force no dithering fills={0b0000000000000000}, x=64, y=64, trails=4, framesPerTrail=7, draw=function(x, y, color, fill) fillp(fill) circfill(x, y, 8, color) end } function _init() -- Setup the palettes in use -- Colors figured out thanks to http://kometbomb.net/pico8/fadegen.html pal(1, 12, 1) pal(2, 129, 1) pal(3, 131, 1) pal(4, 140, 1) -- Initialise the shapes ready for motion trail trails = createTrailSystem({ shape }) end function _update60() if (btn(0)) then shape.x -= 2 end -- Left if (btn(1)) then shape.x += 2 end -- Right if (btn(2)) then shape.y -= 2 end --Up if (btn(3)) then shape.y += 2 end --Down trails.update() end function _draw() cls(0) trails.draw() end |
[Please log in to post a comment]