Files
Forge-Engine/screens/scenes/add_scene_object.py
T
williamandClaude Sonnet 5 9199897784
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
Image de fond de scène + caméra qui suit le personnage, fps d'animation cohérent
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

65 lines
3.1 KiB
Python

import json
import db
from .ensure_scene_schema import ensure_scene_schema
_DEFAULT_PERSONNAGE_DATA = {"source": "forge", "forge_character": "male-adventurer"}
_KINDS = {"personnage", "decor", "fond"}
def add_scene_object(slug, scene_id, kind="personnage", forge_character=None, background_slug=None):
"""Pose un nouvel objet sur une scène (voir ensure_scene_schema.py).
kind="personnage" : attributes._personnage_data, MÊME structure/mêmes
fonctions resolve_personnage_* que le widget "personnage" de l'éditeur
document (screens/rendering/personnage_data.py) — un objet de scène
"personnage" partage donc directement la bibliothèque Forge et le
système d'animation déjà écrits. kind="decor" : une simple image fixe
(attributes.src), pas d'animation. kind="fond" : même image fixe que
"decor" (render_scene_object.py ne les distingue pas au rendu), mais
posée en dessous de tout le reste (z_index très négatif, voir
static/style.css .sceneBackground) et à la taille RÉELLE de l'image
choisie (voir screens/labels/background_library.py) par défaut — une
image plus grande que la scène devient alors le "monde" que la caméra
suit en défilant (voir static/js/play/personnage-controller.js)."""
ensure_scene_schema(slug)
kind = kind if kind in _KINDS else "personnage"
attributes = {}
width = height = None
if kind == "personnage":
data = dict(_DEFAULT_PERSONNAGE_DATA)
if forge_character:
from ..labels.sprite_library import PUBLIC_SPRITE_LIBRARY
from ..labels.animal_sprite_library import ADMIN_SPRITE_LIBRARY
if forge_character in PUBLIC_SPRITE_LIBRARY or forge_character in ADMIN_SPRITE_LIBRARY:
data["forge_character"] = forge_character
attributes["_personnage_data"] = json.dumps(data)
elif kind == "fond" and background_slug:
from ..labels.background_library import BACKGROUND_LIBRARY
background = BACKGROUND_LIBRARY.get(background_slug)
if background:
attributes["src"] = background["url"]
width, height = background["width"], background["height"]
conn = db.connect(slug)
if kind == "fond":
z_index = -1000
else:
max_z = conn.execute(
"SELECT MAX(z_index) AS m FROM _scene_objects WHERE scene_id = ?", (scene_id,)
).fetchone()["m"]
z_index = (max_z or 0) + 1
cols = ["scene_id", "kind", "attributes", "z_index"]
values = [scene_id, kind, json.dumps(attributes), z_index]
if width is not None:
# x=0/y=0 (jamais le défaut 100/100, voir ensure_scene_schema.py) :
# un fond commence au coin haut-gauche de la scène/du monde, pas
# décalé arbitrairement comme un objet ordinaire.
cols += ["width", "height", "x", "y"]
values += [width, height, 0, 0]
placeholders = ", ".join(["?"] * len(values))
conn.execute(f"INSERT INTO _scene_objects ({', '.join(cols)}) VALUES ({placeholders})", values)
object_id = conn.execute("SELECT last_insert_rowid() AS id").fetchone()["id"]
conn.commit()
conn.close()
return object_id