BeeEngine logo BeeEngine JAVASCRIPT 2D ENGINE

Debug Canvas JS: Overlay, Hitbox e Freeze con Tasti F2-F4

Documentazione – BeeEngine
v2.8.0

BeeLadybug — Documentazione Tecnica

Occhio del motore: F2 overlay, F3 slow-mo, F4 freeze, hitbox in spazio mondo

📁 Panoramica

BeeLadybug è l’occhio del motore, non una classe di gameplay. Vive in src/debug/BeeLadybug.js e il barrel la re-esporta con BEE_LADYBUG_DEFAULTS. Disegna hitbox AABB (e OBB se c’è una transform) dentro la camera, e un pannello HUD dopo ctx.restore(), in spazio schermo. Non usa F12 (DevTools) né la tilde: sui layout italiani la tilde non è un tasto unico.

Quello che non è: il collision system, un profiler, un logger. Il rosso sulle hitbox è overlap AABB dei draw-bounds, calcolato con un BeeSpatialHash privato. Non è collisions.run() e non è engine.spatial.

BeeEngine crea subito this.debug = new BeeLadybug(this) e chiama attach(). L’overlay parte spento (enabled = false). F2 lo accende. enableLadybug() fa configure + attach + show: visibile al primo frame.

import { BeeEngine } from ‘beeengine’; const gioco = new BeeEngine(‘testCanvas’, 800, 600); gioco.enableLadybug(); // visibile; F2 la nasconde // oppure: gioco.debug.toggle(); gioco.start();

📁 Due pass di disegno

Il loop ufficiale chiama Ladybug in tre punti. L’ordine conta: le hitbox devono vedere la camera, l’HUD no, i click arrivano prima di input.endFrame().

Dentro BeeEngine.loop. drawWorld gira solo se enabled. drawOverlay e poll vengono chiamati sempre (early-return se l’overlay è spento).

  1. 1. mondoScene, layer, render. Poi, se enabled, debug.drawWorld prima di restore.
  2. 2. schermoctx.restore, layer screen, UI, touch. Poi debug.drawOverlay con setTransform(1,0,0,1,0,0).
  3. 3. clickdebug.poll sui tre pulsanti, poi input.endFrame.

📁 Tasti e pulsanti

Il listener è su window keydown, confronta event.code (quindi 'F2', non event.key e non 'f2'). Ignora event.repeat e fa preventDefault sui tre tasti. F2 funziona anche a overlay spento. F3 e F4 solo se enabled.

Ingresso Metodo Effetto reale
F2 / toggle() toggle / show / hide Accende o spegne enabled. Non tocca timeScale né la pausa.
F3 / bottone SLOW applySlowMo() Se time.paused, prima resume. Poi alterna timeScale tra slowScale (default 0.25) e 1, via engine.setTimeScale.
F4 / bottone STOP toggleFreeze() time.togglePause(). Il mondo vede dt = 0, il rAF e il draw continuano: ispezioni le hitbox da fermo.
bottone 1x LIVE restoreRealtime() Resume se in pausa, poi setTimeScale(1).

I tre rettangoli sull’HUD (268×168, angolo overlayX/Y default 12,12) fanno le stesse tre azioni. Si accendono in rosso se lo stato corrente li riguarda (slow e non frozen, frozen, live 1×).

📁 Chi viene disegnato

drawWorld ricalcola la lista ogni frame. Visita, con un Set anti-duplicato e i figli ricorsivi: engine.entities, engine.scenes.currentScene.entities (fallback engine.currentScene), i bucket di engine.collisions.groups, e engine.physics.bodies[i].entity.

Salta destroyed. L’AABB viene da engine.getEntityDrawBounds: prima entity.getWorldAABB(), poi il rect del collider, altrimenti worldX/Y (o x/y) + width/height. Senza size positiva non c’è box.

Poi il tratto: se c’è entity.body.drawDebug lo chiama (forma del body, non solo il rettangolo). Altrimenti, se la transform ha transformPoint, traccia l’OBB locale (0,0)→(w,h). Altrimenti strokeRect sull’AABB.

📁 Colori: verde / rosso / grigio

Verde = active !== false e niente overlap. Grigio = inattiva. Rosso = la sua AABB si sovrappone a un’altra AABB della stessa lista. Broadphase: hash a celle da 64px (default di BeeSpatialHash), poi test AABB-AABB. L’overlay scrive verde=ok rosso=collide: collide qui vuol dire “i rettangoli di disegno si toccano”, non “il gruppo player/enemy ha sparato un evento”.

L’HUD legge la lista dell’ultimo drawWorld: FPS da time.fps, ciclo da unscaledDt * 1000, scala, RUN/FREEZE, conteggio attive / in memoria. Se chiami solo drawOverlay a mano, i numeri restano quelli (o zero) del frame precedente.

📁 Dove è facile sbagliare

Il rosso non è collisions.run(). Ladybug ha il suo hash. Due sprite che si coprono diventano rosse anche se non sono nello stesso gruppo e anche se la scena non chiama mai il collision system.

F3 da freeze scongela. applySlowMo fa resume prima di toccare la scala. F3 non è “slow anche in pausa”.

Il click sull’HUD arriva anche al gioco. poll legge input.mouse.wasPressed (coordinate canvas, spazio schermo) e non lo consuma. Lo stesso frame può far partire un impulso, uno spawn, un UI click. I tasti F* invece fanno preventDefault.

Le chiavi sono event.code. Default 'F2' / 'F3' / 'F4' coincidono col code dei function key. Se rinomini con configure({ toggleKey: 'KeyD' }) va. Con 'd' o 'D' no.

F3/F4 muti a overlay spento. F2 è l’unico tasto vivo quando enabled è false. Il costruttore del motore ha già fatto attach(): non serve riattaccare il listener a ogni start.

📁 Esempio: accendi, configura, ispeziona

import { BeeEngine } from ‘beeengine’; const gioco = new BeeEngine(‘testCanvas’, 800, 600); gioco.enableLadybug({ slowScale: 0.1, overlayX: 16, overlayY: 16 }); // F2 nasconde. F3 = 0.1x / 1x. F4 = freeze. // Da codice, stessa cosa: gioco.debug.applySlowMo(); gioco.debug.toggleFreeze(); gioco.debug.restoreRealtime(); gioco.start();

📁 Riepilogo API

Fluent: configure, attach, detach, show, hide, toggle, applySlowMo, toggleFreeze, restoreRealtime ritornano this. Default frozen: BEE_LADYBUG_DEFAULTS.

Membro Ritorna Scopo
BEE_LADYBUG_DEFAULTS oggetto frozen toggleKey F2 · slowKey F3 · freezeKey F4 · slowScale 0.25 · colori active/colliding/inactive · overlay 12,12.
new BeeLadybug(engine, options?) BeeLadybug Parte enabled: false, listener non attaccato. Il motore lo costruisce e fa attach() da solo.
configure(options) this Merge sui default. Non tocca enabled né il listener.
attach() / detach() this keydown su window. Seconda attach è no-op.
show / hide / toggle this Flag enabled. Non stacca i tasti.
applySlowMo() this Resume se paused, poi toggle scala slowScale ↔ 1.
toggleFreeze() this time.togglePause(). No-op senza engine.time.
restoreRealtime() this Resume + scala 1.
drawWorld(ctx) — Raccoglie entity, refresh overlap, fill+stroke hitbox. Chiamare dentro la camera.
drawOverlay(ctx) — HUD 268×168, reset transform, pulsanti. Dopo restore.
poll() — Hit-test mouse canvas sui tre bottoni. Prima di endFrame. Non consuma wasPressed.
destroy() — detach, enabled = false, svuota liste/Set/bottoni. Il motore lo chiama in BeeEngine.destroy.
gioco.debug / gioco.enableLadybug(options?) istanza Stessa coccinella. enableLadybug configura, attacca e show.