miaoda-game-frame-action-core
v0.3.0
Published
Engine-agnostic deterministic frame-action timelines: immutable action definitions, timed steps, poses, tags, payloads, entry events, interruption, and JSON-safe runtime snapshots.
Maintainers
Readme
miaoda-game-frame-action-core
Use this engine-independent runner for deterministic integer-frame timelines: attacks, interactions, doors, traps, boss moves, and other gameplay sequences whose timing must not depend on an animation player.
Install
pnpm add miaoda-game-frame-action-coreDefine and run an action
import { FrameActionRunner } from 'miaoda-game-frame-action-core';
const runner = new FrameActionRunner([
{
id: 'slash',
steps: [
{ id: 'startup', duration: 6, pose: 'slash-start', tags: ['lock:move'] },
{ id: 'active', duration: 2, pose: 'slash-hit', tags: ['hitbox:sword'], events: ['slash'] },
{ id: 'recovery', duration: 8, pose: 'slash-end', tags: ['lock:move'] },
],
},
]);
runner.start('slash');
for (let frame = runner.tick(); frame.sample; frame = runner.tick()) {
if (frame.sample.tags.includes('hitbox:sword')) enableHitbox();
for (const event of frame.events) playSound(event);
if (frame.justEnded) break;
}duration is a positive integer count of simulation ticks. sample describes the frame just processed. events is emitted only on the first tick of its step. enteredStepId identifies the step that will be current on the next tick; justEnded means the final frame was processed and the runner is idle.
Control edges
start(id)works only while idle and returnsfalsewhen another action runs.forceStart(id)replaces the current action immediately.interrupt()stops without processing another frame and returns the interrupted ID.currentandhasTag(tag)expose the state waiting for the next tick.
Tags, poses, payloads, and event names are game data. The runner does not play animation, apply damage, resolve hitboxes, or poll input. Use the unique sample.instanceId as the attack/run identity when connecting to combat or effects.
Save and restore
const saved = JSON.parse(JSON.stringify(runner.snapshot));
const resumed = new FrameActionRunner(definitions).restore(saved);Snapshots contain control state and the action run sequence, but not definition payloads. Restore with the same definitions. Invalid snapshots are rejected atomically. The snapshot is a persistence format, not an authentication or anti-cheat boundary.
Public API
FrameActionRunner, FrameActionDefinition, FrameActionStep, FrameActionSample, FrameActionTick, and FrameActionSnapshot are exported. For input buffering, explicit cancellation, priorities, cooldowns, and movement constraints, compose miaoda-game-action-runtime-core.
