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>
This commit is contained in:
william
2026-09-02 12:24:10 +02:00
co-authored by Claude Sonnet 5
parent 5891c82c62
commit 9199897784
24 changed files with 581 additions and 33 deletions
+8 -1
View File
@@ -78,7 +78,14 @@
screens/scenes/), pas de wrapper .playElement/elstyle (spécifiques
au %/DOM d'un écran "document") : juste le HTML tel quel. -->
<div class="playScreen playScene" data-screen-id="{{ s.id }}" data-kind="jeu_2d" style="width:{{ s.scene_width }}px; height:{{ s.scene_height }}px;">
{% for obj in s.elements %}{{ obj.rendered_html|safe }}{% endfor %}
<!-- .sceneWorld : le "monde" (voir static/style.css et
static/js/play/personnage-controller.js) — taille par défaut 100%
(identique au viewport ci-dessus), agrandie/décalée en JS
uniquement si un objet kind="fond" plus grand que la scène est posé
(caméra qui suit le personnage). -->
<div class="sceneWorld" data-scene-width="{{ s.scene_width }}" data-scene-height="{{ s.scene_height }}">
{% for obj in s.elements %}{{ obj.rendered_html|safe }}{% endfor %}
</div>
</div>
{% else %}
<div class="playScreen" data-screen-id="{{ s.id }}" data-kind="document" data-aspect="{{ s.preview_aspect or '9/16' }}">
+21 -1
View File
@@ -51,7 +51,7 @@
{% for o in objects %}
<div class="treeNode" data-element-id="{{ o.id }}">
<a class="treeNodeLabel {{ 'selected' if o.id == selected_id else '' }}" href="{{ url_for('screen_edit', slug=game.slug, screen_id=screen.id, selected=o.id) }}">
{{ '🏃' if o.kind == 'personnage' else '🖼️' }} <span class="treeLabel">{{ o.name or ('Personnage' if o.kind == 'personnage' else 'Décor') }}</span>
{{ '🏃' if o.kind == 'personnage' else ('🏞️' if o.kind == 'fond' else '🖼️') }} <span class="treeLabel">{{ o.name or ('Personnage' if o.kind == 'personnage' else ('Fond' if o.kind == 'fond' else 'Décor')) }}</span>
</a>
</div>
{% endfor %}
@@ -78,6 +78,26 @@
</div>
</details>
<button type="button" class="button is-small is-fullwidth" onclick="addSceneObject('decor')">🖼️ + Ajouter un décor</button>
{% if background_library %}
<!-- Images de fond CraftPix (screens.BACKGROUND_LIBRARY, admin
seulement — voir core/sprite_gate.py). Posée à la taille RÉELLE
de l'image (voir screens/scenes/add_scene_object.py) : plus
grande que la scène, la caméra la suit en défilant derrière le
personnage (voir static/js/play/personnage-controller.js). -->
<details class="propGroup">
<summary>🏞️ Images de fond</summary>
<div class="propGroupBody">
<div class="iconGallery personnageGallery">
{% for slug_b, background in background_library.items() %}
<button type="button" class="iconGalleryTile" title="{{ background.label }}" onclick="addSceneObject('fond', null, '{{ slug_b }}')">
<img src="{{ background.url }}" alt="{{ background.label }}" class="personnageThumb">
</button>
{% endfor %}
</div>
<p class="help">Posée à sa taille réelle (souvent plus grande que la scène) — un seul fond par scène recommandé, la caméra le suit en défilant.</p>
</div>
</details>
{% endif %}
</div>
</div>