Commit Graph
11 Commits
Author SHA1 Message Date
williamandClaude Sonnet 5 521792fe00 Dialogues de quête : bulles illimitées, n'importe quel objet, timeline reliée
Build and deploy / test-python (push) Successful in 7m32s
Build and deploy / test-js (push) Successful in 1m2s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
- "qui parle" n'est plus réservé au personnage : N'IMPORTE QUEL objet de
  scène nommé (personnage, décor, fond — voir "ℹ️ Informations",
  screens/rendering/scene_object_names.py, ex-personnage_names.py) peut
  parler dans un dialogue.
- Confirmé/documenté : aucune limite au nombre de répliques par colonne
  (bouton "+ Réplique" reste toujours disponible).
- Bulle = header (menu déroulant du "qui parle") + body (le texte),
  centrée dans sa colonne à 70% de largeur, alignée verticalement et
  reliée à la suivante par un trait — remplace l'ancien alignement
  gauche/droite façon chat.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 11:54:06 +02:00
williamandClaude Sonnet 5 2347a70c45 Quêtes/collision : personnages nommés, dialogues qui parlent, boîte de dialogue en jeu
Build and deploy / test-python (push) Successful in 11m32s
Build and deploy / test-js (push) Successful in 1m12s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
- "ℹ️ Informations" (propriétés d'un personnage) : nom éditable, réutilisé
  comme "qui parle" dans l'éditeur de dialogue de quête (menu déroulant,
  plus "Joueur" toujours disponible) — remplace l'ancien choix binaire
  joueur/pnj. db.sanitize_quest_dialogues accepte maintenant un nom libre.

- Nouveau menu "🖥️ Interface" (palette d'objets) avec le premier widget :
  "💬 Boîte de dialogue" (kind="dialogue_box", screens/rendering/
  dialogue_box_style.py) — position/taille comme tout objet de scène,
  panneau "🎨 Style" dédié (police, taille, épaisseur, couleur du texte,
  couleur header/body/footer). Rendu en <div> à 3 zones, jamais soumis à
  la collision ni à l'éditeur de collision (exclu partout : obstacles,
  liste des règles, payload). Rendu côté jeu dans .sceneUI, une couche
  FIXE au viewport (jamais .sceneWorld, qui défile avec la caméra).

- static/js/play/dialogue-box-controller.js : fait le lien moteur entre
  l'action "quete" de l'éditeur de collision et ce widget — affiche la
  réplique en cours du dialogue correspondant au STATUT ACTUEL de la
  quête (gameData.quests, désormais exposé game-wide par
  full_game_payload.py), avance au clic sur "Suivant" (header = qui
  parle, body = texte, footer = bouton), se masque à la dernière réplique.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 11:20:58 +02:00
williamandClaude Sonnet 5 51427b5297 Éditeur de quêtes : titre/objectif/récompense/statut/résultat + dialogue à 3 colonnes
Build and deploy / test-python (push) Successful in 6m14s
Build and deploy / test-js (push) Successful in 51s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Nouvel espace "🗺️ Quêtes" (game-wide, comme les événements
personnalisés) : liste de cartes + "+ Nouvelle quête", chaque carte
ouvrant une modale d'arbre de dialogue en bulles de théâtre
("speaker: texte"), une colonne par statut de quête (nouvelle/en
cours/terminée) puisque le dialogue joué dépend de l'état de la
quête au moment où le joueur parle au PNJ. Bulles alternées
joueur/PNJ, couleur différente selon qui parle.

L'action "Déclencher une quête" de l'éditeur de collision n'est plus
un champ texte libre : elle ouvre directement CETTE MÊME modale
(picker de quêtes existantes + création à la volée), et finalise la
règle avec l'id numérique de la quête choisie — collision_rules.py
migré en conséquence (quete_id devient un entier, comme evenement_id).

Corrige aussi la miniature d'objet de la carte "🧩 Collision", 3× plus
grande (120px) comme demandé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 20:24:57 +02:00
williamandClaude Sonnet 5 ee270d0286 Éditeur de collision (jeu 2D) : règles trigger -> action par objet
Build and deploy / test-python (push) Successful in 6m31s
Build and deploy / test-js (push) Successful in 50s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Nouvel onglet "🧩 Collision" dans l'éditeur de scène 2D : chaque objet
(hors joueur et fond) peut porter des règles "à la collision" ou "dans
un périmètre (px)" déclenchant une action (quête, attaque, événement,
ou interagir - qui affiche "Appuie sur [touche]" puis exécute une
sous-action à l'appui, un seul niveau d'imbrication). Backend
(sanitisation, route de persistance, exposition dans
full_game_payload) + assistant modal en cartes empilées côté client.

Ajoute le moteur d'exécution runtime (collision-rules-controller.js) :
détecte l'entrée en collision/périmètre avec le joueur à chaque tick,
déclenche l'action une seule fois par entrée, pur JS client sans appel
serveur (fonctionne à l'identique en ligne et en export SCORM).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 17:11:42 +02:00
williamandClaude Sonnet 5 bc3feb5080 Panneau scène simplifié + boîte de collision + rôle joueur/ennemi/pnj
Build and deploy / test-python (push) Successful in 11m52s
Build and deploy / test-js (push) Successful in 56s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Trois retours utilisateur sur l'éditeur de scène 2D :

- Retire l'arborescence "Objets de cette scène" (un objet reste
  sélectionnable en cliquant dessus sur le canevas) et le bouton
  "+ Ajouter un décor" (le type "decor" reste supporté côté serveur,
  juste plus accessible depuis ce menu).

- Chaque objet de scène a désormais une boîte de collision AUTOMATIQUE
  (= sa propre boîte, comportement inchangé pour une condition de
  collision déjà posée) réglable dans un nouveau panneau "🧱 Collision" :
  activée/désactivée, forme (rectangle/cercle), taille et décalage —
  utile pour un sprite très paddé (CraftPix) dont la silhouette réelle
  est bien plus petite que son canevas. elementsOverlap() (conditions.js)
  applique ces réglages en restant identique par défaut.

- Nouveau champ "🏷️ Rôle" (Joueur/Ennemi/PNJ) sur un personnage : SEUL un
  personnage "Joueur" est désormais déplacé/animé au clavier et suivi
  par la caméra (personnage-controller.js) — "Ennemi"/"PNJ" restent
  immobiles tant qu'aucune logique de flow ne les pilote (déplacement
  ennemi automatique/apparition, dialogue de PNJ... hors scope de ce
  réglage, qui ne fait qu'identifier "quel objet est le joueur").

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 15:30:34 +02:00
williamandClaude Sonnet 5 9199897784 Image de fond de scène + caméra qui suit le personnage, fps d'animation cohérent
Build and deploy / test-python (push) Successful in 6m26s
Build and deploy / test-js (push) Successful in 57s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Trois retours utilisateur :
- fps d'idle/interagir/touches supplémentaires alignés sur celui de la
  marche (8 i/s partout, était 4 pour idle — perçu comme "les autres
  animations sont lentes à côté de la marche").
- Nouveau menu "🏞️ Images de fond" dans "Objets de cette scène" : pose
  un objet kind="fond" à la taille RÉELLE de l'image choisie (pack
  CraftPix intégré en galerie, admin seulement — licence, voir
  core/sprite_gate.py), derrière tout le reste, insensible au clic.
- Si ce fond dépasse la scène, elle devient le "monde" : .playScreen.
  playScene est désormais le viewport (overflow:hidden, taille fixe),
  .sceneWorld le monde à l'intérieur — la caméra centre le premier
  personnage trouvé, bornée pour ne jamais montrer au-delà des bords
  (voir personnage-controller.js::forgeUpdateSceneCamera). Le personnage
  peut désormais se déplacer sur tout le monde, pas seulement le petit
  cadre visible (clampSceneObjectPosition, actions.js). Un jeu sans fond
  XXL garde un comportement strictement identique à avant (monde ==
  scène, transform vide).

Bibliothèque générée une fois par scripts/generate_background_manifest.py
(assets/background/, non versionné, licence CraftPix) vers
static/backgrounds/ (committé), même patron que
generate_animal_sprite_manifest.py.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 12:24:10 +02:00
williamandClaude Sonnet 5 5891c82c62 Commandes personnage : détection de touche au clavier + touches d'animation supplémentaires
Build and deploy / test-python (push) Successful in 6m17s
Build and deploy / test-js (push) Successful in 53s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Deux retours utilisateur sur le panneau "Commandes" (déplacement/
animation automatiques, voir précédent commit) :
- Les champs de touche (haut/bas/gauche/droite/interagir) capturent
  maintenant la touche au clavier (clic puis appui — event.key, même
  valeur que heldKeys/triggers.js) au lieu d'être tapés à la main,
  source d'erreurs ("Espace" vs " ", "flèche haut" vs "ArrowUp"...).
- Nouvelle section "Animations supplémentaires" : un nombre illimité de
  touches, chacune liée à UNE pose au choix parmi celles réellement
  disponibles pour ce personnage (sauter, attaquer, courir...) — pas
  seulement les 4 touches de déplacement + interagir.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 11:50:29 +02:00
williamandClaude Sonnet 5 74f7ca396f Déplacement/animation automatiques d'un personnage (scène 2D)
Build and deploy / test-python (push) Successful in 6m25s
Build and deploy / test-js (push) Successful in 55s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Simplification demandée pour l'éditeur de jeu RPG : un personnage posé
sur une scène 2D se déplace et s'anime TOUT SEUL avec ZQSD (+ E pour
interagir) dès qu'il est posé — plus besoin de poser le moindre nœud de
flow pour un mouvement de base. Le panneau "🕹️ Commandes" du personnage
permet de remapper les 4 touches de déplacement et la touche
d'interaction, et de bloquer un axe (horizontal/vertical seulement).

Entièrement client (static/js/play/personnage-controller.js), réutilise
heldKeys (triggers.js) et applyObjectProperty/clampSceneObjectPosition/
runSpriteAnimation (actions.js) — aucune logique dupliquée, et ça
fonctionne aussi bien en ligne que dans l'export Web/SCORM (aucune
requête serveur). "walk"/"idle"/"interact" (poses déjà présentes pour
tout personnage Forge/CraftPix) sont utilisées telles quelles ; une pose
absente dégrade silencieusement (déplacement sans animation) plutôt que
de planter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 11:26:37 +02:00
williamandClaude Sonnet 5 d5a59bdbd8 Fusion des deux moteurs : type d'écran par écran, plus par projet
Build and deploy / test-python (push) Failing after 6m10s
Build and deploy / test-js (push) Successful in 58s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
"document" (écrans %) et "jeu_2d" (scène pixels) devient une propriété
PAR ÉCRAN (_screens.kind, migration automatique idempotente dans
ensure_schema.py, source = l'ancien game_type au niveau projet) plutôt
qu'un choix figé pour tout le jeu — un même projet peut désormais
mélanger écrans classiques et scènes 2D librement.

- routes/screens/screen_edit.py : dispatch vers l'éditeur de scène selon
  screen["kind"] (l'écran demandé), plus game["game_type"].
- screens/payload/full_game_payload.py, templates/play.html,
  static/js/play/screens.js : le rendu jouable (payload, markup, bascule
  du mode plein-écran #playFrame) décide écran par écran, y compris en
  cours de partie (changer d'écran ne recharge pas la page).
- screens/screens_repo/create_screen.py : nouveau paramètre kind.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 06:21:13 +02:00
williamandClaude Sonnet 5 449c36fd5d Bibliothèque de sprites animaux CraftPix (1/3) : catalogue, galerie, accès admin
Build and deploy / test-python (push) Failing after 12s
Build and deploy / test-js (push) Successful in 6s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Premier commit d'une fonctionnalité découpée en plusieurs lots (voir le
plan "Bibliothèque de sprites animaux CraftPix") : intègre 14 familles
d'animaux (15 variantes de couleur chacune) comme personnages Forge
sélectionnables, à côté des 6 Kenney existants — réservé au rôle admin,
licence CraftPix oblige (interdiction contractuelle de rendre ces sprites
utilisables par un compte "user" via l'application).

- screens/labels/animal_sprite_library.py (nouveau) : charge un manifest
  JSON généré une fois (voir scripts/generate_animal_sprite_manifest.py,
  commit suivant) et construit ADMIN_SPRITE_LIBRARY, dans le même format
  que l'existant PUBLIC_SPRITE_LIBRARY (screens/labels/sprite_library.py,
  ex-SPRITE_LIBRARY, renommé pour distinguer les deux). screens.SPRITE_LIBRARY
  reste le catalogue FUSIONNÉ (utilisé par resolve_personnage_animations
  pour la résolution runtime, sans filtrage par rôle — voir le constat
  d'exploration : le payload de jeu et /jouer/<slug> ne vérifient déjà
  aucun rôle nulle part).
- screens/labels/sprite_gallery.py (nouveau) : sprite_gallery_families()
  groupe la galerie par famille — un animal n'apparaît qu'une fois (sa
  variante "de base"), ses 15 couleurs se choisissent depuis le panneau
  de propriétés (render_variant_gallery, templates/screen_edit.html),
  répondant à la suggestion de l'utilisateur plutôt que d'encombrer la
  galerie d'ajout de 210 tuiles quasi identiques.
- routes/screens/screen_edit.py, routes/scenes/scene_edit_view.py :
  la galerie passée au template est filtrée par rôle
  (PUBLIC_SPRITE_LIBRARY pour un compte "user", SPRITE_LIBRARY complet
  pour un admin) — même idiome que core/auth_guard.py.
- core/sprite_gate.py (nouveau) + 4 routes d'écriture (element_add,
  element_set_personnage_data, scene_object_add, scene_object_personnage_data) :
  ferme la brèche d'un POST direct qui contournerait la galerie filtrée
  (403 si un compte non-admin tente d'assigner un personnage animal).
- tests/conftest.py : nouvelles fixtures user_client/user_game (compte
  "user" non-admin avec un projet assigné) pour tester le filtrage par
  rôle de bout en bout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 21:49:05 +02:00
williamandClaude Sonnet 5 f0070faced Phase A (2/2) : éditeur de scène 2D — route, template, runtime jouable
Build and deploy / test-python (push) Successful in 1m56s
Build and deploy / test-js (push) Successful in 8s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Deuxième et dernier commit de la Phase A du plan "Fondations d'une
plateforme multi-éditeurs" (le premier, efa7d1d, posait le schéma et le
CRUD des objets de scène). Ce commit branche l'éditeur et le mode
jouable sur ces fondations, en réutilisant TEL QUEL tout ce qui est déjà
générique côté moteur de logique.

Éditeur (routes/scenes/, templates/scene_edit.html,
static/js/scenes/scene-editor.js) :
- routes/screens/screen_edit.py délègue à render_scene_edit() dès que
  game_type == "jeu_2d" — même endpoint Flask "screen_edit" pour les
  deux éditeurs, aucune route dupliquée.
- Nouveau template scene_edit.html : canevas à taille FIXE en pixels
  (scene_width/scene_height) avec glisser-déposer/redimensionnement en
  pixels (scene-editor.js, mirror pixel de tree-panels.js), galerie
  personnages/décors. Les onglets "Blocs de logique"/"Timeline
  d'animation"/"Événements" réutilisent tels quels flow-editor.js,
  tabs-and-blocks.js et animation-timeline.js.
- flow-editor.js : nouveau flag FLOW_TARGETS_OBJECTS (false par défaut,
  true dans scene_edit.html) qui fait écrire submitNodeForm() vers
  trigger_object_id/target_object_id au lieu de trigger_element_id/
  target_element_id, plus une branche "Modifier un objet de scène"
  (position px, visibilité, orientation) et des gardes null partout
  (le DOM de scene_edit.html n'a pas tous les champs de l'éditeur
  document).
- blocks_view.py étend l'ensemble d'ids d'éléments concernés par un
  bloc pour inclure aussi trigger_object_id/target_object_id.

Runtime jouable (templates/play.html, static/js/play/actions.js,
screens/payload/full_game_payload.py) :
- full_game_payload() construit les écrans d'un jeu jeu_2d à partir de
  _scene_objects (render_scene_object) au lieu de _screen_elements, et
  récupère les animations de personnage sur les objets de scène.
- play.html : #playFrame occupe tout le viewport pour une scène jeu_2d
  (pas de ratio fluide) ; la scène se centre via .playScreen.playScene,
  qui réutilise tel quel showScreen() (déjà indexé par id d'écran, pas
  par forme DOM) — aucun fichier "scenes.js" séparé n'a été nécessaire.
- actions.js : jouer_animation_sprite retombe sur target_object_id si
  target_element_id est absent ; nouvelle action modifier_objet_scene
  avec applyObjectProperty() (positions en px, contrairement aux % de
  applyElementProperty()).

Un bug de gabarit a été découvert et corrigé pendant la vérification :
le commentaire CSS de play.html contenait littéralement "{% for %}"
comme texte français, que Jinja interprétait comme une vraie balise et
faisait planter le rendu — reformulé. render_scene_object() n'était en
outre jamais appelé par la vue de l'éditeur (les objets de scène
s'affichaient sans image) — scene_edit_view.py attache maintenant
rendered_html à chaque objet avant de les passer au template.

Nouveaux tests (tests/test_scene_edit_view.py, 10 cas) : dispatch
document vs jeu_2d, rendu d'un personnage sélectionné, CRUD géométrie/
suppression d'objet, nœuds de flow ciblant un objet de scène (action et
condition de collision), payload et page /play pour un jeu jeu_2d,
présence des nouveaux helpers JS. Suite complète : 309 tests passent
(299 existants + 10 nouveaux, aucune régression). node --check et
node --test (13 tests JS) passent également.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 10:05:40 +02:00