Corrige : une animation déjà posée dans la logique ignorait le changement de personnage
Bug réel identifié grâce à la vidéo fournie + inspection directe de la
base de jeu de test : quand un nœud de flow "Jouer une animation"
(ou un clip de Timeline "sprite") était configuré pour un personnage,
ses frames étaient résolues et FIGÉES dans data_value/custom_keyframes
au moment de la configuration — changer ensuite le personnage Forge de
l'élément (galerie des propriétés) n'avait donc aucun effet sur les
animations déjà posées, qui continuaient à jouer indéfiniment les
frames de l'ANCIEN personnage.
Le nœud/clip ne stocke désormais que le NOM de l'animation
({"animation": "walk", "fps": 8, "loop": true}) — ses frames sont
résolues à l'EXÉCUTION, à partir du personnage ACTUELLEMENT assigné à
l'élément cible :
- screens/payload/full_game_payload.py expose un nouveau
gameData.personnage_animations (élément → animations), reconstruit à
chaque chargement de la page de jeu depuis _personnage_data — donc
toujours à jour, y compris après un changement de personnage.
- static/js/play/actions.js (resolveSpriteFrames) et
static/js/play/screens.js (applyAnimationClip) résolvent le nom
d'animation en frames à ce moment précis, plutôt que d'utiliser des
frames figées — repli sur l'ancien format {frames,...} pour les
nœuds/clips déjà créés avant ce correctif.
- Éditeur (flow-editor.js/animation-timeline.js) : simplifié en
conséquence — plus besoin de deviner rétroactivement quelle animation
correspond à une liste de frames stockées (l'ancien hack de
comparaison), le nom est maintenant stocké directement.
Nouveau test de régression (test_swapping_forge_character_updates_
already_configured_flow_action) qui reproduit exactement le scénario
filmé : configure l'action pour "male-adventurer", change le personnage
en "zombie", vérifie que gameData.personnage_animations reflète bien
zombie sans avoir à retoucher le nœud de flow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
5ead091c75
commit
70c2b8df05
@@ -245,7 +245,7 @@ function runActionNode(node) {
|
||||
if (targetEl) {
|
||||
let spriteData = {};
|
||||
try { spriteData = JSON.parse(node.data_value || '{}'); } catch (e) { /* data_value invalide : rien à jouer */ }
|
||||
runSpriteAnimation(targetEl, spriteData);
|
||||
runSpriteAnimation(targetEl, resolveSpriteFrames(node.target_element_id, spriteData));
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -268,6 +268,25 @@ function runActionNode(node) {
|
||||
// deux partagent ce même moteur, aucune logique dupliquée.
|
||||
var activeSpriteAnimations = new Map();
|
||||
|
||||
// Phase 8 — résout le NOM d'une animation (ex. "walk") en liste de frames à
|
||||
// partir du personnage ACTUELLEMENT assigné à cet élément
|
||||
// (gameData.personnage_animations, reconstruit à chaque chargement de la
|
||||
// page de jeu depuis _personnage_data — voir full_game_payload.py) plutôt
|
||||
// que depuis des frames figées au moment où le créateur a configuré
|
||||
// l'action/le clip : sans ça, changer le personnage Forge d'un élément
|
||||
// dans l'éditeur n'avait aucun effet sur les animations déjà posées dans
|
||||
// la logique de flow/la Timeline, qui continuaient à jouer indéfiniment
|
||||
// les frames de l'ANCIEN personnage (bug signalé par l'utilisateur).
|
||||
// `spriteData.frames` (ancien format, Phase 7) reste géré en repli pour
|
||||
// les nœuds/clips déjà créés avant ce changement.
|
||||
function resolveSpriteFrames(elementId, spriteData) {
|
||||
var byAnimation = (gameData.personnage_animations || {})[elementId];
|
||||
if (byAnimation && spriteData.animation && byAnimation[spriteData.animation]) {
|
||||
return { frames: byAnimation[spriteData.animation], fps: spriteData.fps, loop: spriteData.loop };
|
||||
}
|
||||
return spriteData;
|
||||
}
|
||||
|
||||
function runSpriteAnimation(targetEl, spriteData) {
|
||||
var frames = spriteData.frames || [];
|
||||
var fps = spriteData.fps > 0 ? spriteData.fps : 8;
|
||||
|
||||
@@ -147,14 +147,16 @@ function applyAnimationClip(clip) {
|
||||
});
|
||||
}
|
||||
} else if (clip.kind === 'sprite') {
|
||||
// Phase 7 — même moteur que l'action de flow "jouer_animation_sprite"
|
||||
// (voir runSpriteAnimation() dans actions.js) : custom_keyframes
|
||||
// stocke ici {frames, fps} en JSON plutôt que des images-clés CSS
|
||||
// (réutilise la colonne générique existante, pas de nouveau champ).
|
||||
// Phase 8 — même moteur que l'action de flow "jouer_animation_sprite"
|
||||
// (voir runSpriteAnimation()/resolveSpriteFrames() dans actions.js) :
|
||||
// custom_keyframes stocke {animation, fps} (nom de l'animation, pas
|
||||
// ses frames — résolues ICI depuis le personnage ACTUELLEMENT
|
||||
// assigné, gameData.personnage_animations, pas figées au moment où
|
||||
// le clip a été configuré).
|
||||
var spriteData = {};
|
||||
try { spriteData = JSON.parse(clip.custom_keyframes || '{}'); } catch (e) { /* invalide : rien à jouer */ }
|
||||
spriteData.loop = infinite;
|
||||
setTimeout(function() { runSpriteAnimation(target, spriteData); }, delay * 1000);
|
||||
setTimeout(function() { runSpriteAnimation(target, resolveSpriteFrames(clip.element_id, spriteData)); }, delay * 1000);
|
||||
} else {
|
||||
var animClass = 'animate__' + clip.animate_name;
|
||||
target.style.setProperty('--animate-duration', duration + 's');
|
||||
|
||||
Reference in New Issue
Block a user