BeeEngine logo BeeEngine JAVASCRIPT 2D ENGINE

State Machine per animazioni in JavaScript: transizioni 2D

Documentazione – BeeEngine
v2.9.2

BeeAnimator — Documentazione Tecnica

Grafo di stati: when / lock / exitTo, onComplete una volta

📁 Panoramica

BeeAnimator decide quale clip e quando. Non disegna. Lo sprite (BeeAnimatedSprite) riproduce. Vive in src/graphics/BeeAnimator.js. Factory: gioco.createAnimator(sprite). BeeEntity.update ticka entity.animator (e allora non riticka entity.sprite).

In #enter chiama sprite.play(clip, { restart: true, loop: next.loop }): sul loop, quando c’è l’animator, vince lo stato (add(..., { loop }), default true), non il flag del clip.

const animator = gioco.createAnimator(sprite); animator .add(‘idle’, { clip: ‘idle’, initial: true }) .add(‘run’, { clip: ‘run’, priority: 1 }) .add(‘attack’, { clip: ‘attack’, loop: false, lock: true, priority: 10, exitTo: ‘idle’ }) .when(‘idle’, ‘run’, (actor) => Math.abs(actor.vx) > 1) .when(‘*’, ‘attack’, (actor) => actor.wantsAttack) .start(); hero.sprite = sprite; hero.animator = animator;

📁 Update

Il contesto è il secondo argomento di update, oppure options.context(). L’entity passa sé stessa (o animatorContext()).

  1. 1. clipsprite.update(dt) (dt 0 in pausa).
  2. 2. fineSe finished: onComplete una volta per visita, poi queued || exitTo.
  3. 3. whenAnche in lock. Score when.priority + dest.priority > lock: interrompe. ≤ : coda. force rompe sempre.

📁 Dove è facile sbagliare

Spegni wantsAttack. when('*', 'attack', a => a.wantsAttack) senza consumeAttack() (o onEnter che azzera il flag): dopo exitTo: 'idle' al frame dopo rientri in attack.

Lo score del lock è when.priority + dest.priority. Un when('*', 'hurt', …, { priority: 100 }) verso uno stato a 0, contro un attack lockato a 10, interrompe (100 > 10). Tra due when vince lo score più alto. set('hurt') invece guarda solo la priorità dello stato: hurt a 0 non rompe un lock a 10, a meno di { force: true }.

Senza sprite, o play === false. console.warn una volta e il lock non si applica: locked è false, when / set possono uscire. Non è più un vicolo cieco.

Il primo add() è initial se non segni initial: true su un altro. Senza start() current è null. #queued è un solo nome (l’ultimo vince). set('sconosciuto') tace.

📁 Esempio: lock rotto da hurt

animator .add(‘attack’, { clip: ‘attack’, loop: false, lock: true }) .add(‘hurt’, { clip: ‘hurt’ }) .when(‘*’, ‘hurt’, (a) => a.stunned, { priority: 100 }) .start(‘attack’);

📁 Riepilogo API

play sull’animator è set (cambia stato). Non è BeeAnimatedSprite.play.

Membro Ritorna Scopo
new BeeAnimator(sprite?, { context }?) BeeAnimator Sprite opzionale. context() se update non passa il ctx.
add(name, spec?) this clip / animation o il name. loop default true. lock, priority, exitTo, onEnter / onExit / onComplete.
when(from, to, pred, { priority }?) this from stringa, array o '*'. Predicato: (ctx, animator) => boolean. Score lock: priority + dest.priority.
start(name?) / set / play this start usa initial. { restart, force } su set/play.
update(dt, context?) this Avanza clip, complete, exit, then when.
current / locked / queued / timeInState string / bool / string / number Stato; lock solo se il clip è partito e non è finished; coda; tempo nello stato.
gioco.createAnimator(sprite, opts) istanza Factory sul motore.