miaoda-game-fallblock-core
v0.3.0
Published
Engine-agnostic active-falling-block loop: the spine shared by Tetris, Dr. Mario, Puyo Puyo and Columns. A mobile piece that moves, rotates and soft/hard-drops against a well and locks into it, with a pluggable rotation + wall-kick system (ships the Guide
Maintainers
Readme
miaoda-game-fallblock-core
Engine-independent active-piece logic for Tetris-, Dr. Mario-, Puyo-, and Columns-like games. It handles piece motion, rotation, falling and lock timing, deterministic piece queues, row clearing, and loose-cell settling; rendering and input remain game-owned.
pnpm add miaoda-game-fallblock-core miaoda-game-grid-coreimport {Grid} from 'miaoda-game-grid-core';
import {LockDelay, PieceQueue, TETROMINOES, bagRandomizer, kicksFor, rotateWithKicks, spawnTetromino} from 'miaoda-game-fallblock-core';
const well = new Grid<string | null>({width: 10, height: 20});
const queue = new PieceQueue(bagRandomizer(TETROMINOES, rng), 5);
const lock = new LockDelay({delayFrames: 30, maxResets: 15});
const id = queue.take();
let piece = spawnTetromino(id, id, 3, 0);
piece = rotateWithKicks(well, piece, 1, kicksFor(id)) ?? piece;Use canPlace before accepting a spawn. tryMove, tryRotate, stepGravity, hardDrop, and lockPiece manage the mobile piece; the host decides game over when a spawn cannot be placed. Time in LockDelay is measured in logic frames, so call it once per fixed game tick.
For Tetris-style resolution use fullRows and clearRows, which move surviving rows rigidly. For color-match games, find matches with miaoda-game-match3-core and use settle/settleFully, where loose cells fall individually while anchored cells remain fixed. ghostPiece, ghostCells, and holdSwap provide common player assists.
bagRandomizer, historyRandomizer, uniformRandomizer, and PieceQueue are deterministic when supplied a deterministic RNG. Save the randomizer/queue snapshot and the separately owned RNG state together, then restore both before continuing:
const save = {rng: rng.state, queue: queue.snapshot()};
rng.state = save.rng;
queue.loadSnapshot(save.queue);Catalog identity/order and queue configuration must match when loading. LockDelay.snapshot contains grounded state, remaining frames, lock readiness, and reset budget.
