From 60ed2d4de4dee31dc8519e6b5c7fd61dd3876f1c Mon Sep 17 00:00:00 2001 From: arudaev Date: Sun, 25 Oct 2026 10:12:46 +0100 Subject: [PATCH 1/2] =?UTF-8?q?refactor(combat):=20one=20timing=20source?= =?UTF-8?q?=20=E2=80=93=20clip=20speeds=20from=20the=20boards'=20anims.jso?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #156: the chair's moves (sweeps, overhead, low sweep, guard and its push) and the rover, crab and drone timed their frames as n / 12. Each model now takes its board's anims.json (combat/clips.ts: frameTime, frameCount, clipTime, frameAt); the chair and the enemy row pass the loaded tables, and without one the authored 12 fps stays. The unused lifePose / paintLife (generic white tint) are gone. Refs #156 --- game/src/combat/chair.ts | 15 +++++++++++---- game/src/combat/clips.ts | 19 +++++++++++++++++++ game/src/combat/guard.ts | 26 +++++++++++++++++--------- game/src/combat/life-visuals.ts | 15 --------------- game/src/combat/lowSweep.ts | 11 +++++++---- game/src/combat/overhead.ts | 17 +++++++++++------ game/src/combat/sweeps.ts | 10 +++++++--- game/src/enemies/crab.ts | 19 ++++++++++++------- game/src/enemies/drone.ts | 12 +++++++----- game/src/enemies/rover.ts | 13 ++++++++----- game/src/enemies/rovers.ts | 6 +++--- game/src/player/player.ts | 3 ++- 12 files changed, 104 insertions(+), 62 deletions(-) create mode 100644 game/src/combat/clips.ts diff --git a/game/src/combat/chair.ts b/game/src/combat/chair.ts index 693cbac..0a6057b 100644 --- a/game/src/combat/chair.ts +++ b/game/src/combat/chair.ts @@ -4,6 +4,7 @@ import type { Player } from '../player/player'; import { sound } from '../fx/sound/Audio'; import { HitStop, Sweeps, SWEEP_CONTACT, type Damageable, type Rect } from './sweeps'; import { Overhead, SLAM_SPEED } from './overhead'; +import type { Clips } from './clips'; import { Guard } from './guard'; import { BODY_HEIGHT, BODY_WIDTH } from '../player/body'; import { actionEdges, attackClick, AttackBuffer } from './action-input'; @@ -19,12 +20,12 @@ const FIXTURE_KNOCK = 8; // docs/02: development fixture displacement, not real const GRAIN = 2; // docs/09: two-pixel grain; retain this overlap after the fixture moves. export class ChairCombat { - readonly sweeps = new Sweeps(); + readonly sweeps: Sweeps; readonly pause = new HitStop(); - readonly overhead = new Overhead(); - readonly guard = new Guard(); + readonly overhead: Overhead; + readonly guard: Guard; /** ↓ + Act on the ground: the chair along the floor (lowSweep.ts). */ - readonly low = new LowSweep(); + readonly low: LowSweep; private targets = new Map(); private key: Phaser.Input.Keyboard.Key; /** The second attack bind (playtest 24 Oct): X, for players on the arrow keys. */ @@ -46,6 +47,12 @@ export class ChairCombat { private visible = false; enabled: boolean; constructor(private scene: Phaser.Scene, private player: Player, _region: string) { + // Every move's timing from its board's anims.json (#156: one timing source). + const clips = (board: string) => scene.cache.json.get(`${board}.anims`) as Clips | undefined; + this.sweeps = new Sweeps(clips('chair-side')); + this.overhead = new Overhead(clips('chair-overhead')); + this.low = new LowSweep(clips('chair-overhead')); + this.guard = new Guard(clips('chair-block')); // Armed once the hero picked the chair up (chairPickup.ts), in every region after that. this.enabled = carriesChair(scene); this.key = scene.input.keyboard!.addKey('J'); diff --git a/game/src/combat/clips.ts b/game/src/combat/clips.ts new file mode 100644 index 0000000..68b71ca --- /dev/null +++ b/game/src/combat/clips.ts @@ -0,0 +1,19 @@ +import type { AnimationTable } from '../stage/assets'; + +/** + * One timing source for the chair's moves (#156): each clip's speed and length come from its board's + * `anims.json` (export_atlas.py), never from numbers in the gameplay code. A model built without a table (tests, + * a board not loaded yet) uses the boards' authored defaults: 12 fps and the frame counts it names. + */ +export type Clips = Partial; +export const DEFAULT_FPS = 12; + +/** Seconds per frame of a clip. */ +export const frameTime = (clips: Clips | undefined, name: string) => 1 / (clips?.[name]?.fps ?? DEFAULT_FPS); +/** A clip's frame count, or the authored one. */ +export const frameCount = (clips: Clips | undefined, name: string, authored: number) => clips?.[name]?.frames ?? authored; +/** Seconds for `frames` frames of a clip. */ +export const clipTime = (clips: Clips | undefined, name: string, frames: number) => frames * frameTime(clips, name); +/** The frame a clip shows `elapsed` seconds in (not clamped). */ +export const frameAt = (clips: Clips | undefined, name: string, elapsed: number) => + Math.floor((elapsed + 1e-9) / frameTime(clips, name)); diff --git a/game/src/combat/guard.ts b/game/src/combat/guard.ts index 69ec78c..08e1d0c 100644 --- a/game/src/combat/guard.ts +++ b/game/src/combat/guard.ts @@ -1,6 +1,9 @@ import { BODY_WIDTH } from '../player/body'; +import { clipTime, frameAt, type Clips } from './clips'; export const GUARD_DISTANCE = BODY_WIDTH / 2; // docs/02: small push = half the 28 px body. -export const GUARD_PUSH_TIME = 3 / 12; // docs/02: three authored frames, kinematic collision retained. +/** docs/02: the push lasts the impact's first three frames (0.25 s at 12 fps); kinematic collision retained. */ +export const guardPushTime = (clips?: Clips) => clipTime(clips, 'guard-impact', 3); +export const GUARD_PUSH_TIME = guardPushTime(); type Phase = 'idle' | 'up' | 'hold' | 'impact' | 'break'; export class Guard { @@ -10,7 +13,9 @@ export class Guard { private elapsed = 0; private consumed = false; private engaged = false; - get active() { return this.phase === 'hold' || this.phase === 'impact' || this.phase === 'up' && this.elapsed + 1e-9 >= 2 / 12; } + /** `clips`: chair-block.anims.json (guard-up, guard-hold, guard-impact, guard-break). */ + constructor(private clips?: Clips) {} + get active() { return this.phase === 'hold' || this.phase === 'impact' || this.phase === 'up' && this.elapsed + 1e-9 >= clipTime(this.clips, 'guard-up', 2); } press(direction: -1 | 1) { if (this.phase !== 'idle') return false; this.direction = direction; this.phase = 'up'; this.elapsed = 0; this.blocks = 0; @@ -25,9 +30,10 @@ export class Guard { step(dt: number) { this.elapsed += dt; if (this.active) this.engaged = true; - if ((this.phase === 'up' || this.phase === 'impact') && this.elapsed + 1e-9 >= 4 / 12) { - this.phase = 'hold'; this.elapsed = Math.max(0, this.elapsed - 4 / 12); - } else if (this.phase === 'break' && this.elapsed + 1e-9 >= 4 / 12) this.cancel(); + const length = clipTime(this.clips, `guard-${this.phase}`, 4); + if ((this.phase === 'up' || this.phase === 'impact') && this.elapsed + 1e-9 >= length) { + this.phase = 'hold'; this.elapsed = Math.max(0, this.elapsed - length); + } else if (this.phase === 'break' && this.elapsed + 1e-9 >= length) this.cancel(); } receive(damage: number, sourceX: number, playerX: number) { if (!Number.isInteger(damage) || damage <= 0) throw new Error('Damage must be a positive integer'); @@ -41,8 +47,8 @@ export class Guard { } get pose() { if (this.phase === 'idle') return undefined; - const clip = this.phase === 'up' ? 'guard-up' : `guard-${this.phase}`; - const frame = Math.floor((this.elapsed + 1e-9) * 12); + const clip = `guard-${this.phase}`; + const frame = frameAt(this.clips, clip, this.elapsed); return `${clip}-${String(this.phase === 'hold' ? frame % 3 : Math.min(3, frame)).padStart(2, '0')}`; } } @@ -50,11 +56,13 @@ export class Guard { export class GuardPush { remaining = 0; private direction = 1; - start(direction: number) { this.remaining = GUARD_PUSH_TIME; this.direction = direction < 0 ? -1 : 1; } + private readonly time: number; + constructor(clips?: Clips) { this.time = guardPushTime(clips); } + start(direction: number) { this.remaining = this.time; this.direction = direction < 0 ? -1 : 1; } cancel() { this.remaining = 0; } step(dt: number) { const active = Math.min(dt, this.remaining); this.remaining = Math.max(0, this.remaining - active); if (this.remaining < 1e-9) this.remaining = 0; - return this.direction * GUARD_DISTANCE / GUARD_PUSH_TIME * active; + return this.direction * GUARD_DISTANCE / this.time * active; } } diff --git a/game/src/combat/life-visuals.ts b/game/src/combat/life-visuals.ts index c448514..e59a768 100644 --- a/game/src/combat/life-visuals.ts +++ b/game/src/combat/life-visuals.ts @@ -1,21 +1,6 @@ import type Phaser from 'phaser'; import type { Position } from '../core/events'; -import type { Life } from './life'; -export function lifePose(life: Life) { - if (life.dead > 0) return { board: 'hero-death', frame: `death-${String(Math.min(11, Math.floor((1 - life.dead) * 12))).padStart(2, '0')}` }; - if (life.knock > 0) { - const time = 1 - life.invulnerable; - return { board: 'hero-hurt', frame: time < 0.08 ? 'hit-00' - : `knockback-${String(Math.min(2, Math.floor((time - 0.08) * 12))).padStart(2, '0')}` }; - } - return null; -} -export function paintLife(sprite: Phaser.GameObjects.Sprite, life: Life, time: number) { - if (life.dead === 0 && life.invulnerable > 0.92) sprite.setTintFill(0xffffff); - else sprite.clearTint(); - sprite.setAlpha(life.dead === 0 && life.invulnerable > 0 && Math.floor(time / 80) % 2 ? 0.35 : 1); -} /** Small game particles; no raster assets or changes to the approved art. */ export function deathDust(scene: Phaser.Scene, position: Position) { for (let i = 0; i < 18; i++) { diff --git a/game/src/combat/lowSweep.ts b/game/src/combat/lowSweep.ts index 22f9ae5..b85a4ae 100644 --- a/game/src/combat/lowSweep.ts +++ b/game/src/combat/lowSweep.ts @@ -1,9 +1,10 @@ import { intersects, type Damageable, type Rect } from './sweeps'; +import { frameTime, type Clips } from './clips'; /** * The low sweep (playtest 24 Oct: rovers and crabs crawl under a chest-high swing): ↓ + Act on the ground drives the * chair down along the floor. No new art – it plays the slam's own floor poses from `chair-overhead` (02 the chair - * coming down, 03 planted on the floor with its dust, 04 the follow-through), five poses at 12 fps. + * coming down, 03 planted on the floor with its dust, 04 the follow-through), five poses at the slam's own speed. * Measured on the 1.5x slam-03 (cell 160×187, feet 80,187): seat and legs run 12…56 px ahead, the dust to ~60 px, * the seat 51 px up – a floor-level box that reaches a little further than the side swing (50 px). */ @@ -11,7 +12,6 @@ export const LOW_CONTACT = { inner: 12, reach: 75, top: 51, bottom: 0 } as const export const LOW_POSES = ['slam-02', 'slam-03', 'slam-03', 'slam-04', 'slam-04'] as const; /** The poses with the chair on the floor. */ export const LOW_HIT_FRAMES: readonly number[] = [1, 2]; -const FRAME = 1 / 12; export class LowSweep { active = false; @@ -19,6 +19,8 @@ export class LowSweep { direction: -1 | 1 = 1; private elapsed = 0; private struck = new Set(); + /** `clips`: chair-overhead.anims.json – the poses are the slam's. */ + constructor(private clips?: Clips) {} begin(direction: -1 | 1) { if (this.active) return false; this.active = true; this.direction = direction; this.frame = 0; this.elapsed = 0; this.struck.clear(); @@ -28,8 +30,9 @@ export class LowSweep { step(dt: number) { if (!this.active) return; this.elapsed += dt; - while (this.active && this.elapsed + 1e-9 >= FRAME) { - this.elapsed = Math.max(0, this.elapsed - FRAME); this.frame++; + const frame = frameTime(this.clips, 'slam'); + while (this.active && this.elapsed + 1e-9 >= frame) { + this.elapsed = Math.max(0, this.elapsed - frame); this.frame++; if (this.frame >= LOW_POSES.length) this.cancel(); } } diff --git a/game/src/combat/overhead.ts b/game/src/combat/overhead.ts index 4bed37c..1af5c5f 100644 --- a/game/src/combat/overhead.ts +++ b/game/src/combat/overhead.ts @@ -1,6 +1,7 @@ import { intersects, type Damageable, type Rect } from './sweeps'; import type { Position } from '../core/events'; import { RUN_SPEED } from '../player/movement'; +import { clipTime, frameAt, frameCount, type Clips } from './clips'; /** * docs/02: measured on the 1.5x chair-overhead frames (24 Oct), cell 160×187, foot pivot (80,187). In up-02/03 the @@ -18,6 +19,8 @@ export class Overhead { private elapsed = 0; private queued?: { kind: 'up' | 'slam'; direction: -1 | 1 }; private struck = new Set(); + /** `clips`: chair-overhead.anims.json (up, slam, pogo). */ + constructor(private clips?: Clips) {} begin(kind: 'up' | 'slam', direction: -1 | 1) { if (this.phase === 'pogo' || this.phase === 'descend') { this.queued = { kind, direction }; return true; } if (this.phase !== 'idle') return false; @@ -27,10 +30,12 @@ export class Overhead { cancel() { this.enter('idle'); this.struck.clear(); this.queued = undefined; } step(dt: number) { this.elapsed += dt; - if (this.phase === 'windup' && this.elapsed + 1e-9 >= 3 / 12) this.enter('descend'); - else if (this.phase === 'up' && this.elapsed + 1e-9 >= 6 / 12 - || this.phase === 'land' && this.elapsed + 1e-9 >= 3 / 12 - || this.phase === 'pogo' && this.elapsed + 1e-9 >= 4 / 12) { + const done = (clip: string, frames: number) => this.elapsed + 1e-9 >= clipTime(this.clips, clip, frames); + // slam: 00–02 the windup, 03 the descent (held until the floor), 04–06 the landing + if (this.phase === 'windup' && done('slam', 3)) this.enter('descend'); + else if (this.phase === 'up' && done('up', frameCount(this.clips, 'up', 6)) + || this.phase === 'land' && done('slam', 3) + || this.phase === 'pogo' && done('pogo', frameCount(this.clips, 'pogo', 4))) { const queued = this.phase === 'pogo' ? this.queued : undefined; this.cancel(); if (queued) this.begin(queued.kind, queued.direction); } @@ -38,8 +43,8 @@ export class Overhead { land(grounded: boolean) { if (grounded && this.phase === 'descend') this.enter('land'); } get pose() { if (this.phase === 'idle') return undefined; - const frame = Math.floor((this.elapsed + 1e-9) * 12); const clip = this.phase === 'up' ? 'up' : this.phase === 'pogo' ? 'pogo' : 'slam'; + const frame = frameAt(this.clips, clip, this.elapsed); const index = this.phase === 'descend' ? 3 : this.phase === 'land' ? Math.min(6, 4 + frame) : this.phase === 'windup' ? Math.min(2, frame) : Math.min(clip === 'up' ? 5 : 3, frame); return `${clip}-${String(index).padStart(2, '0')}`; @@ -48,7 +53,7 @@ export class Overhead { return { x: position.x + (this.direction > 0 ? left : -right), y, w: right - left, h }; } box(position: Position, previousY: number): Rect | undefined { - const frame = Math.floor((this.elapsed + 1e-9) * 12); + const frame = frameAt(this.clips, 'up', this.elapsed); if (this.phase === 'up' && (frame === 2 || frame === 3)) { const c = UP_CONTACT; return this.rect(position, c.left, c.right, position.y - c.top, c.top - c.bottom); } diff --git a/game/src/combat/sweeps.ts b/game/src/combat/sweeps.ts index 4af3dbc..dee55a9 100644 --- a/game/src/combat/sweeps.ts +++ b/game/src/combat/sweeps.ts @@ -1,3 +1,5 @@ +import { frameCount, frameTime, type Clips } from './clips'; + export interface Rect { x: number; y: number; w: number; h: number } export interface ChairHit { damage: number; direction: -1 | 1; position: { x: number; y: number }; kind: 'sweep' | 'up' | 'slam' } export interface Damageable { id: string; active?(): boolean; bounds(): Rect; hit(hit: ChairHit): boolean } @@ -32,6 +34,8 @@ export class Sweeps { private elapsed = 0; private queued: -1 | 1 | null = null; private struck = new Set(); + /** `clips`: chair-side.anims.json (sweep-a, sweep-b, recoil). */ + constructor(private clips?: Clips) {} private begin(direction: -1 | 1) { this.phase = this.nextB ? 'sweep-b' : 'sweep-a'; this.nextB = !this.nextB; this.direction = direction; this.frame = 0; this.elapsed = 0; this.struck.clear(); @@ -44,9 +48,9 @@ export class Sweeps { step(dt: number) { if (this.phase === 'idle') return; this.elapsed += dt; - while (this.elapsed + 1e-9 >= 1 / 12 && this.phase !== 'idle') { - this.elapsed = Math.max(0, this.elapsed - 1 / 12); this.frame++; - if (this.frame < (this.phase === 'recoil' ? 2 : 8)) continue; + while (this.phase !== 'idle' && this.elapsed + 1e-9 >= frameTime(this.clips, this.phase)) { + this.elapsed = Math.max(0, this.elapsed - frameTime(this.clips, this.phase)); this.frame++; + if (this.frame < frameCount(this.clips, this.phase, this.phase === 'recoil' ? 2 : 8)) continue; if (this.phase !== 'recoil') { this.phase = 'recoil'; this.frame = 0; } else { this.phase = 'idle'; this.frame = 0; diff --git a/game/src/enemies/crab.ts b/game/src/enemies/crab.ts index cfbb1bf..954313b 100644 --- a/game/src/enemies/crab.ts +++ b/game/src/enemies/crab.ts @@ -1,3 +1,4 @@ +import { clipTime, frameAt, frameCount, type Clips } from '../combat/clips'; import { BODY_HEIGHT, BODY_WIDTH } from '../player/body'; import { TURN_SECONDS } from './rover'; import { WALK_SPEED } from '../player/movement'; @@ -20,7 +21,7 @@ export const STAB_REACH = 52; * half-width (less a 4 px bite). Further off – up to CRAB_SPOT – it creeps toward the hero instead of stabbing air. */ export const CRAB_STRIKE = CRAB_WIDTH / 2 + STAB_REACH + BODY_WIDTH / 2 - 4; -const STAB_SECONDS = 5 / 12, COLLAPSE_SECONDS = 5 / 12, HIT_SECONDS = 3 / 12, RECOVER = 0.5; +const RECOVER = 0.5; export type CrabPhase = 'walk' | 'tell' | 'stab' | 'recover' | 'hit' | 'collapse' | 'dead'; export class Crab { @@ -35,13 +36,15 @@ export class Crab { turning = 0; /** Whether it moved in the last step (its legs walk only then). */ private moving = true; - constructor(readonly spawn: Position, readonly patrol: [number, number]) { this.x = spawn.x; this.y = spawn.y; } + /** `clips`: enemy-crab.anims.json (idle, walk, stab, collapse). */ + constructor(readonly spawn: Position, readonly patrol: [number, number], private clips?: Clips) { this.x = spawn.x; this.y = spawn.y; } + private seconds(clip: string, authored: number) { return clipTime(this.clips, clip, frameCount(this.clips, clip, authored)); } private enter(phase: CrabPhase) { this.phase = phase; this.elapsed = 0; this.turning = 0; this.moving = true; } reset() { this.x = this.spawn.x; this.health = CRAB_HEALTH; this.direction = -1; this.enter('walk'); } get bounds(): Rect { return { x: this.x - CRAB_WIDTH / 2, y: this.y - CRAB_HEIGHT, w: CRAB_WIDTH, h: CRAB_HEIGHT }; } /** The stab's reach while its legs are out (frames 2–3 of 5), else undefined. */ get attack(): Rect | undefined { - if (this.phase !== 'stab' || this.elapsed < 2 / 12 || this.elapsed >= 4 / 12) return undefined; + if (this.phase !== 'stab' || this.elapsed < clipTime(this.clips, 'stab', 2) || this.elapsed >= clipTime(this.clips, 'stab', 4)) return undefined; const front = this.x + this.direction * CRAB_WIDTH / 2; return { x: this.direction > 0 ? front : front - STAB_REACH, y: this.y - CRAB_HEIGHT, w: STAB_REACH, h: CRAB_HEIGHT }; } @@ -81,19 +84,21 @@ export class Crab { break; } case 'tell': if (this.elapsed >= CRAB_TELL) this.enter('stab'); break; - case 'stab': if (this.elapsed >= STAB_SECONDS) this.enter('recover'); break; + case 'stab': if (this.elapsed >= this.seconds('stab', 5)) this.enter('recover'); break; case 'recover': if (this.elapsed >= RECOVER) this.enter('walk'); break; case 'hit': this.x = Math.max(this.patrol[0], Math.min(this.patrol[1], this.x + this.hitDirection * 40 * dt)); - if (this.elapsed >= HIT_SECONDS) this.enter('recover'); + if (this.elapsed >= clipTime(this.clips, 'idle', 3)) this.enter('recover'); break; - case 'collapse': if (this.elapsed >= COLLAPSE_SECONDS) { this.enter('dead'); defeated = true; } break; + case 'collapse': if (this.elapsed >= this.seconds('collapse', 5)) { this.enter('dead'); defeated = true; } break; } } return defeated; } get pose() { - const n = Math.floor((this.elapsed + 1e-9) * 12); + const clip = this.phase === 'walk' && this.moving ? 'walk' : this.phase === 'tell' || this.phase === 'stab' ? 'stab' + : this.phase === 'collapse' ? 'collapse' : 'idle'; + const n = frameAt(this.clips, clip, this.elapsed); const f = (clip: string, i: number) => `${clip}-${String(i).padStart(2, '0')}`; switch (this.phase) { case 'walk': return this.moving ? f('walk', n % 8) : f('idle', n % 4); diff --git a/game/src/enemies/drone.ts b/game/src/enemies/drone.ts index 0f36448..d2ce3f2 100644 --- a/game/src/enemies/drone.ts +++ b/game/src/enemies/drone.ts @@ -1,3 +1,4 @@ +import { clipTime, frameAt, frameCount, type Clips } from '../combat/clips'; import type { Position } from '../core/events'; import type { Rect } from '../combat/sweeps'; @@ -15,7 +16,7 @@ export const DRONE_WIDTH = 77, DRONE_HEIGHT = 77, DRONE_HEALTH = 8; export const DRONE_SPEED = 70, DRONE_TELL = 0.5, DIVE_SPEED = 380, CLIMB_SPEED = 160; /** It dives when the hero is this close beneath it (px, horizontally). */ export const DRONE_SPOT = 50; -const CRASH_SECONDS = 5 / 12, HIT_SECONDS = 3 / 12, DIVE_MAX = 0.6; +const DIVE_MAX = 0.6; export type DronePhase = 'hover' | 'tell' | 'dive' | 'climb' | 'hit' | 'crash' | 'dead'; export class Drone { @@ -26,7 +27,8 @@ export class Drone { direction: -1 | 1 = 1; elapsed = 0; private target = 0; - constructor(readonly spawn: Position, readonly patrol: [number, number]) { this.x = spawn.x; this.y = spawn.y; } + /** `clips`: enemy-drone.anims.json (hover, dive, crash, screw). */ + constructor(readonly spawn: Position, readonly patrol: [number, number], private clips?: Clips) { this.x = spawn.x; this.y = spawn.y; } private enter(phase: DronePhase) { this.phase = phase; this.elapsed = 0; } reset() { this.x = this.spawn.x; this.y = this.spawn.y; this.health = DRONE_HEALTH; this.enter('hover'); } get bounds(): Rect { return { x: this.x - DRONE_WIDTH / 2, y: this.y - DRONE_HEIGHT, w: DRONE_WIDTH, h: DRONE_HEIGHT }; } @@ -57,18 +59,18 @@ export class Drone { break; case 'climb': case 'hit': this.y = Math.max(this.spawn.y, this.y - CLIMB_SPEED * dt); - if (this.phase === 'hit' ? this.elapsed >= HIT_SECONDS : this.y <= this.spawn.y) this.enter(this.y <= this.spawn.y ? 'hover' : 'climb'); + if (this.phase === 'hit' ? this.elapsed >= clipTime(this.clips, 'hover', 3) : this.y <= this.spawn.y) this.enter(this.y <= this.spawn.y ? 'hover' : 'climb'); break; case 'crash': this.y += 200 * dt; - if (this.elapsed >= CRASH_SECONDS) { this.enter('dead'); defeated = true; } + if (this.elapsed >= clipTime(this.clips, 'crash', frameCount(this.clips, 'crash', 5))) { this.enter('dead'); defeated = true; } break; } } return defeated; } get pose() { - const n = Math.floor((this.elapsed + 1e-9) * 12); + const n = frameAt(this.clips, this.phase === 'tell' || this.phase === 'dive' ? 'dive' : this.phase === 'crash' ? 'crash' : 'hover', this.elapsed); const f = (clip: string, i: number) => `${clip}-${String(i).padStart(2, '0')}`; if (this.phase === 'tell' || this.phase === 'dive') return f('dive', Math.min(2, n)); if (this.phase === 'crash') return f('crash', Math.min(4, n)); diff --git a/game/src/enemies/rover.ts b/game/src/enemies/rover.ts index c8cf6fd..9ea4c6e 100644 --- a/game/src/enemies/rover.ts +++ b/game/src/enemies/rover.ts @@ -1,6 +1,7 @@ import { WALK_SPEED, RUN_SPEED } from '../player/movement'; import { BODY_HEIGHT } from '../player/body'; import type { Position } from '../core/events'; +import { clipTime, frameAt, frameCount, type Clips } from '../combat/clips'; // docs/05: measured idle-00 alpha bounds and controller tuning. // 3x since 24 Oct (Lex: the small robots were barely visible next to the 114 px hero): 75 px drawn. @@ -21,7 +22,8 @@ export class Rover { private hitDirection = 1; /** Seconds left idling at a patrol end before it turns. */ turning = 0; - constructor(readonly spawn: Position, readonly patrol: [number, number]) { + /** `clips`: enemy-rover.anims.json (idle, drive, charge, wreck). */ + constructor(readonly spawn: Position, readonly patrol: [number, number], private clips?: Clips) { this.x = spawn.x; this.y = spawn.y; } private enter(phase: RoverPhase) { this.phase = phase; this.elapsed = 0; this.turning = 0; } @@ -66,16 +68,17 @@ export class Rover { break; case 'recover': if (this.elapsed + 1e-9 >= TELL_SECONDS) this.enter('patrol'); break; case 'hit': - this.x = Math.max(this.patrol[0], Math.min(this.patrol[1], this.x + this.hitDirection * ROVER_WIDTH / 2 / (3 / 12) * dt)); - if (this.elapsed + 1e-9 >= 3 / 12) this.enter('patrol'); + // knocked back half its width over three frames of its idle clip, flashing + this.x = Math.max(this.patrol[0], Math.min(this.patrol[1], this.x + this.hitDirection * ROVER_WIDTH / 2 / clipTime(this.clips, 'idle', 3) * dt)); + if (this.elapsed + 1e-9 >= clipTime(this.clips, 'idle', 3)) this.enter('patrol'); break; - case 'wreck': if (this.elapsed + 1e-9 >= 5 / 12) { this.enter('dead'); defeated = true; } break; + case 'wreck': if (this.elapsed + 1e-9 >= clipTime(this.clips, 'wreck', frameCount(this.clips, 'wreck', 5))) { this.enter('dead'); defeated = true; } break; } } return defeated; } get pose() { - const frame = Math.floor((this.elapsed + 1e-9) * 12); + const frame = frameAt(this.clips, this.phase === 'patrol' && !this.turning ? 'drive' : this.phase === 'wreck' ? 'wreck' : this.phase === 'charge' ? 'charge' : 'idle', this.elapsed); if (this.phase === 'wreck' || this.phase === 'dead') return `wreck-${String(this.phase === 'dead' ? 4 : Math.min(4, frame)).padStart(2, '0')}`; if (this.phase === 'hit') return 'idle-00'; // The renderer flashes the living body white. if (this.phase === 'tell') return `charge-0${this.elapsed + 1e-9 < TELL_SECONDS / 2 ? 0 : 1}`; diff --git a/game/src/enemies/rovers.ts b/game/src/enemies/rovers.ts index 4fcb342..c366651 100644 --- a/game/src/enemies/rovers.ts +++ b/game/src/enemies/rovers.ts @@ -72,13 +72,13 @@ export class Rovers { const at = { x: spawn.x, y: spawn.y }; let row: Omit; if (kind === 'rover') { - const model = new Rover(at, patrol); + const model = new Rover(at, patrol, scene.cache.json.get('enemy-rover.anims')); row = { model, harmful: () => harmfulPhase('rover', model.phase), onBlocked: () => model.deflect(model.x >= this.player.body.x ? 1 : -1) }; } else if (kind === 'crab') { - const model = new Crab(at, patrol); + const model = new Crab(at, patrol, scene.cache.json.get('enemy-crab.anims')); row = { model, harmful: () => harmfulPhase('crab', model.phase), attack: () => model.attack }; } else { - const model = new Drone(at, patrol); + const model = new Drone(at, patrol, scene.cache.json.get('enemy-drone.anims')); row = { model, harmful: () => harmfulPhase('drone', model.phase) }; } const model = row.model; diff --git a/game/src/player/player.ts b/game/src/player/player.ts index 7b4bb2a..c4c5d91 100644 --- a/game/src/player/player.ts +++ b/game/src/player/player.ts @@ -36,7 +36,7 @@ export class Player { onHealthChanged: (health: number) => void = () => {}; onHazards: (boxes: Box[]) => boolean = () => false; onGuard: (damage: number, sourceX: number) => boolean = () => false; - private guardPush = new GuardPush(); + private guardPush: GuardPush; /** The dodge-dash (dodge.ts); `dodgeWas` is last frame's button, `ghost` the time to the next after-image. */ readonly dodge = new Dodge(); private dodgeWas = false; @@ -102,6 +102,7 @@ export class Player { scene.events.once('shutdown', () => scene.events.off('postupdate', settle)); this.keys = scene.input.keyboard!.addKeys('A,D,W,S,LEFT,RIGHT,UP,DOWN,SPACE,K,Z,J,X,L,C,SHIFT') as Record; this.physical = physicalKeys(scene); + this.guardPush = new GuardPush(scene.cache.json.get('chair-block.anims')); this.debug = scene.add.graphics().setDepth(10001); this.label = scene.add.text(20, 135, '', { fontFamily: 'monospace', fontSize: '18px', backgroundColor: '#17242d' }) .setScrollFactor(0).setDepth(10002).setVisible(false); From 4774f015352856244e395addbe026500e6910875 Mon Sep 17 00:00:00 2001 From: arudaev Date: Sun, 25 Oct 2026 10:35:46 +0100 Subject: [PATCH 2/2] fix(art): the platform board's girder reference lives in the repository The arena-platform board named tmp/girder-ref.png as an input; tmp/ is not in Git, so check_docs failed in CI. The crop of the maze girder is committed next to the arena plate. Refs #72 --- art/sprites/arena-platform.md | 2 +- art/sprites/boards.json | 2 +- .../rusty-creek/arena/girder-reference.png | Bin 0 -> 59049 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 art/stages/rusty-creek/arena/girder-reference.png diff --git a/art/sprites/arena-platform.md b/art/sprites/arena-platform.md index cb716f1..b838b24 100644 --- a/art/sprites/arena-platform.md +++ b/art/sprites/arena-platform.md @@ -15,7 +15,7 @@ On a flat, solid, pure magenta #FF00FF background (no paper colour, no ground sh ## Inputs - [coffee-machine-preview.png](images/coffee-machine-preview.png) -- [girder-ref.png](../../tmp/girder-ref.png) +- [girder-reference.png](../stages/rusty-creek/arena/girder-reference.png) - [style-master-preview.png](../direction/images/style-master-preview.png) Model `gpt-image-2.5-sunburst` · pixel factor 2 · source image `images/arena-platform.png` · rebuild: `python scripts/make_boards.py draw arena-platform --redo --config art/sprites/boards.json` diff --git a/art/sprites/boards.json b/art/sprites/boards.json index e95017f..27b0a3a 100644 --- a/art/sprites/boards.json +++ b/art/sprites/boards.json @@ -1188,7 +1188,7 @@ "factor": 2, "inputs": [ "repo:art/sprites/images/coffee-machine-preview.png", - "repo:tmp/girder-ref.png", + "repo:art/stages/rusty-creek/arena/girder-reference.png", "repo:art/direction/images/style-master-preview.png" ], "prompt": "On a flat, solid, pure magenta #FF00FF background (no paper colour, no ground shadows, no dust under the objects), with NO text at all - no titles, no captions, no frame numbers, no labels, no readable words or logos: Image 1 is an approved prop sheet from this game: draw in exactly that pixel-art look - solid three-dimensional objects drawn as detailed 2D pixel art with volume, the same pixel grain, palette and warm rim light. Image 2 shows the rusty steel girders of the level these props hang in: copy their material exactly - pale blue-grey painted steel eaten by orange rust, riveted flanges, a dark grated underside. Prop sprite sheet, 2 rows. Row 1, exactly 1 frame: ONE short girder PLATFORM segment hung like a stage rigging bar, seen from slightly below like image 2: a long flat box beam about FIVE times as long as it is tall, its front face with rivets, a lit top flange, a dark grated underside with depth, solid end caps showing its thickness; on top, near each end, a heavy steel eye-bolt with the lowest three links of a rusted chain rising straight up from it. Row 2, exactly 1 frame: ONE long straight vertical rusted steel CHAIN hanging perfectly straight up and down, many identical links, about as long as the platform in row 1, the same chain as on the platform. Both rows at the SAME pixel scale. Rows separated by a wide empty magenta band. No people, no scenery, no sky.", diff --git a/art/stages/rusty-creek/arena/girder-reference.png b/art/stages/rusty-creek/arena/girder-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..644ee24f58e77ae26d7a8d731b65470489f94cb1 GIT binary patch literal 59049 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