Mouvement continu, limites de scène et priorité d'animation (jeu 2D)
Répond au manque signalé par l'utilisateur : le déclencheur "clavier"
existant (keydown) ne se déclenche qu'UNE FOIS par appui, insuffisant
pour "maintenir une touche fait avancer/sauter le personnage en continu".
- Deux nouveaux déclencheurs (screens/flow/constants.py,
screens/scenes/flow_palette.py) : "Tant qu'une touche est maintenue"
(se répète ~20 fois/seconde tant que la touche reste enfoncée,
runScreenHeldKeyTriggers() dans triggers.js — même patron PAR ÉCRAN que
"minuteur", arrêté au changement d'écran) et "Au relâchement d'une
touche" (un seul déclenchement, scan global comme "clavier"). Combinés
à l'action existante "Modifier un objet de scène → Déplacer de... px
(relatif)", ça permet un vrai déplacement continu.
- preventDefault() sur toute touche que le jeu écoute réellement
(isGameKey(), triggers.js) : Espace/Flèches font défiler la page par
défaut, et Espace réactive en plus le bouton actuellement focus (souvent
le bouton "Jouer" qui garde le focus après l'ouverture de l'aperçu) —
ça pouvait donner l'impression qu'une touche du jeu ne faisait rien.
- Le personnage pouvait sortir du cadre de la scène en se déplaçant :
applyObjectProperty()/clampSceneObjectPosition() (static/js/play/actions.js)
bornent maintenant toute position (absolue ou relative) à
[0, scene_width/height − la taille de l'objet].
- Vitesse d'animation par défaut adaptée au nombre d'images : la valeur
fixe (8 i/s) venait d'un formulaire pensé pour les cycles Kenney (8
images) — un cycle CraftPix (walk=30 images) au même 8 i/s prenait
~4 secondes, "très lent". Le choix d'une animation dans la galerie
calcule maintenant une vitesse par défaut proportionnelle à son nombre
d'images (flow-editor.js, animation-timeline.js).
- Priorité d'animation (bug : "je ne peux pas me déplacer et sauter") :
un déclencheur de déplacement (touche maintenue) redemande "marche" à
chaque tick, écrasant aussitôt une animation ponctuelle ("sauter")
démarrée entre-temps avant qu'elle ait pu s'afficher. runSpriteAnimation()
(actions.js) laisse maintenant une animation NON BOUCLÉE en cours
(même à une seule frame, ex. une pose Kenney figée) aller jusqu'au bout
avant qu'une autre demande puisse l'interrompre.
Nouveaux tests : static/js/play/__tests__/{actions,triggers}.test.js
(idempotence + priorité d'animation, bornage aux limites de la scène,
isGameKey) ; tests/test_scene_edit_view.py (persistance d'un nœud
"touche_maintenue").
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c240181518
commit
727af55a5e
@@ -90,6 +90,26 @@ def test_flow_node_targets_scene_object(client, tmp_game_slug_cleanup):
|
||||
assert node["target_element_id"] is None
|
||||
|
||||
|
||||
def test_held_key_trigger_persists_and_is_in_scene_palette(client, tmp_game_slug_cleanup):
|
||||
"""Mouvement continu (touche maintenue) — répond au manque signalé par
|
||||
l'utilisateur : "clavier" (keydown) ne se déclenche qu'une fois par
|
||||
appui, insuffisant pour faire avancer un personnage en continu tant
|
||||
qu'une touche reste enfoncée. Voir runScreenHeldKeyTriggers()
|
||||
(static/js/play/triggers.js) et TRIGGER_EVENTS (screens/flow/constants.py)."""
|
||||
slug, screen_id = _create_jeu2d_game(client, tmp_game_slug_cleanup)
|
||||
assert "touche_maintenue" in dict(screens.TRIGGER_EVENTS_2D)
|
||||
assert "touche_relachee" in dict(screens.TRIGGER_EVENTS_2D)
|
||||
resp = client.post(
|
||||
f"/game/{slug}/screens/{screen_id}/flow/nodes/add",
|
||||
data=json.dumps({"node_type": "trigger", "trigger_event": "touche_maintenue", "trigger_key": "ArrowRight"}),
|
||||
content_type="application/json",
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
node = screens.get_flow_node(slug, resp.get_json()["id"])
|
||||
assert node["trigger_event"] == "touche_maintenue"
|
||||
assert node["trigger_key"] == "ArrowRight"
|
||||
|
||||
|
||||
def test_flow_node_collision_condition_targets_scene_objects(client, tmp_game_slug_cleanup):
|
||||
slug, screen_id = _create_jeu2d_game(client, tmp_game_slug_cleanup)
|
||||
obj_a = screens.add_scene_object(slug, screen_id)
|
||||
@@ -127,6 +147,19 @@ def test_play_html_renders_fixed_size_scene(client, tmp_game_slug_cleanup):
|
||||
assert f"width:{db.game_meta(slug)['name'] and 960}px" in html or "width:960px" in html
|
||||
|
||||
|
||||
def test_render_scene_object_carries_data_anim_target(client, tmp_game_slug_cleanup):
|
||||
"""Bug remonté par l'utilisateur : "les animations ne se jouent pas
|
||||
dans l'aperçu" — applyAnimationClip() (static/js/play/screens.js) et
|
||||
animation-timeline.js sélectionnent TOUJOURS leur cible via
|
||||
[data-anim-target=...], jamais data-element-id/data-object-id. Sans cet
|
||||
attribut sur l'objet de scène, AUCUN clip de Timeline (sprite, Animate.css
|
||||
ou personnalisé) ne trouvait jamais sa cible."""
|
||||
slug, screen_id = _create_jeu2d_game(client, tmp_game_slug_cleanup)
|
||||
obj_id = screens.add_scene_object(slug, screen_id)
|
||||
html = screens.render_scene_object(screens.get_scene_object(slug, obj_id))
|
||||
assert f'data-anim-target="{obj_id}"' in html
|
||||
|
||||
|
||||
def test_screen_edit_js_bundle_contains_scene_flow_helpers():
|
||||
js = screen_edit_js_bundle()
|
||||
assert "FLOW_TARGETS_OBJECTS" in js
|
||||
|
||||
Reference in New Issue
Block a user