Pixel art by KnoblePersona, used in accordance with Creative-Commons. See attribution here
This demonstrates how 3d parallax effects were done on many retro game systems. These systems would rasterize graphics to CRT televisions, paiting each pixel from the top to bottom, going left to right across each scanline. At any point while the screen was rendering, the main cpu would still run in parallel. When it knew the time was right (through various methods, typically interrupts) the cpu could change the scroll position of the graphics chip, arbitrarily moving the rest of the screen. By doing this multiple times, a pseudo-3d effect is produced.
const ra = require('raster');
ra.setSize(210, 216);
ra.setZoom(2);
// draw ocean image to its own field, larger than display
let field = new ra.Field();
let img = ra.loadImage('/img/Ocean.png');
img.then(function() {
field.paste(img);
});
ra.useField(field);
// static lookup table controlling speed for each split
let SPEEDS = [0.02, 0.05, 0.11, 0.23, 0.30, 0.42, 0.68, 0.92, 1.14, 1.38];
// mutable data holding scroll for each split
let splits = new Array(SPEEDS.length);
splits.fill(0);
ra.useInterrupts([
{ scanline: 0, irq:()=>{ ra.setScrollX(splits[0]) } },
{ scanline: 82, irq:()=>{ ra.setScrollX(splits[1]) } },
{ scanline: 103, irq:()=>{ ra.setScrollX(splits[2]) } },
{ scanline: 125, irq:()=>{ ra.setScrollX(splits[3]) } },
{ scanline: 130, irq:()=>{ ra.setScrollX(splits[4]) } },
{ scanline: 134, irq:()=>{ ra.setScrollX(splits[5]) } },
{ scanline: 140, irq:()=>{ ra.setScrollX(splits[6]) } },
{ scanline: 148, irq:()=>{ ra.setScrollX(splits[7]) } },
{ scanline: 159, irq:()=>{ ra.setScrollX(splits[8]) } },
{ scanline: 176, irq:()=>{ ra.setScrollX(splits[9]) } },
]);
function draw() {
// nothing is drawn to field, but splits change their scroll a bit
for (let i = 0; i < splits.length; i++) {
splits[i] += SPEEDS[i];
}
}
ra.run(draw);