Field
Palette
rgb map
Tileset

Colorspace

Screen Splits

Dip Switches
Info
  Grid:
  Pixel (x,y):
  Tile (x,y):
  TileID:
  Field Value:
  Cell (x,y):
  Cspace Piece:
  Palette Index:
  Color:
  Scroll X:
  Scroll Y:
  Split Number:

This demo shows the algorithm for rendering a rotating 3d cube, all without a pre-existing 3d framework. The solution is to use a bunch of matrix multiplication and trigonometric functions. On retro systems, these functions would likely be pre-calculated and turned into a lookup table. Bby trading ROM space by cpu time, the cube can quickly be display. On more modern fantasy consoles, such as pico-8, this algorithm works as shown.


const ra = require('raster'); var angle = 0; ra.setSize({w:140, h:140}); ra.setZoom(3); ra.originAtCenter(); function draw() { ra.fillColor(0x00); ra.setColor(0x23); let points = [ [ 10, 10, 10], [ 10, -10, 10], [-10, -10, 10], [-10, 10, 10], [ 10, 10, -10], [ 10, -10, -10], [-10, -10, -10], [-10, 10, -10] ]; let distance = -50; rotateByZ(points, angle); rotateByY(points, angle); rotateByX(points, angle); projection(points, distance); angle += 0.01; for (let i = 0; i < 4; i++) { putLine(points[i ], points[(i + 1) % 4]); putLine(points[i + 4], points[(i + 1) % 4 + 4]); putLine(points[i], points[i + 4]); } } ra.run(draw); function projection(points, distance) { let scale = 180; for (let i = 0; i < points.length; i++) { let x = points[i][0]; let y = points[i][1]; let z = points[i][2]; let d = z - distance; let proj_x = x / d * scale; let proj_y = y / d * scale; points[i] = [proj_x, proj_y, 1]; } } function rotateByX(points, angle) { let mat = [[Math.cos(angle), -Math.sin(angle), 0], [Math.sin(angle), Math.cos(angle), 0], [ 0, 0, 1]]; applyMatrixToPoints(points, mat); } function rotateByY(points, angle) { let mat = [[Math.cos(angle), 0, -Math.sin(angle)], [ 0, 1, 0], [Math.sin(angle), 0, Math.cos(angle)]]; applyMatrixToPoints(points, mat); } function rotateByZ(points, angle) { let mat = [[1 , 0, 0], [0, Math.cos(angle), -Math.sin(angle)], [0, Math.sin(angle), Math.cos(angle)]]; applyMatrixToPoints(points, mat); } function applyMatrixToPoints(points, mat) { for (let i = 0; i < points.length; i++) { let p = points[i]; points[i] = matrixMult(mat, [p[0], p[1], p[2]]); } } function matrixMult(matrix, p) { let x = p[0]; let y = p[1]; let z = p[2]; let new_x = x * matrix[0][0] + y * matrix[0][1] + z * matrix[0][2]; let new_y = x * matrix[1][0] + y * matrix[1][1] + z * matrix[1][2]; let new_z = x * matrix[2][0] + y * matrix[2][1] + z * matrix[2][2]; return [new_x, new_y, new_z]; } function putLine(start, end) { ra.drawLine(start[0], start[1], end[0], end[1]); }