Première brique du plan "Fondations d'une plateforme multi-éditeurs" — l'utilisateur veut un éditeur dédié aux jeux 2D/serious games (scène à coordonnées pixel fixes, objets en couches, collision, personnages animés), distinct de l'éditeur générique actuel, sans dupliquer ce qui peut être partagé (comptes, objets de données, moteur de logique de flow, hébergement/publication). - db/games/get_game_type.py (nouveau) : "document" (défaut, éditeur actuel) ou "jeu_2d" (nouveau), stocké dans _meta comme is_public_played — aucune migration pour les jeux déjà créés (retombent sur "document"). Choisi obligatoirement à la création (templates/index.html), jamais modifiable ensuite. - screens/scenes/ (nouveau sous-module) : table _scene_objects (une scène = des objets en pixels fixes, pas les % fluides de _screen_elements — indispensable pour la collision/l'animation), CRUD complet, rendu HTML. kind="personnage" réutilise TELLE QUELLE la structure _personnage_data et les fonctions resolve_personnage_* déjà écrites pour le widget "personnage" de l'éditeur document (Phase 8) — même bibliothèque Forge, même moteur d'animation, juste une autre table de stockage. - screens/flow/ensure_flow_schema.py : += trigger_object_id/ target_object_id (ALTER TABLE sans contrainte FK, même patron que cond_element_a) — le moteur de logique de flow (_flow_nodes/_flow_edges, flow-engine.js) reste EXACTEMENT le même pour les deux éditeurs, seule la palette de nœuds change (screens/scenes/flow_palette.py, nouveau : sous-ensemble direct des triggers/actions existants, déjà génériques). - screens/screens_repo/ensure_schema.py : += scene_width/scene_height sur _screens (taille de scène fixe en pixels, sans effet sur un écran "document"). Reste à faire (prochains commits) : route + template de l'éditeur de scène, puis le rendu en mode jouable. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
91 lines
3.2 KiB
Python
91 lines
3.2 KiB
Python
import os
|
|
|
|
from ..connection import connect
|
|
from ..game_dir import game_dir
|
|
from ..slugify import slugify
|
|
from .get_game_type import DEFAULT_GAME_TYPE
|
|
|
|
|
|
def create_game(name, slug_override=None, game_type=DEFAULT_GAME_TYPE):
|
|
"""Feature 1 : crée le dossier du jeu, ses fichiers index.html/css/js
|
|
reliés entre eux, et sa base de données dédiée (nom du jeu en méta).
|
|
|
|
slug_override : impose le nom du dossier au lieu de le dériver de
|
|
`name` — utilisé par l'inscription (auth/) pour que le dossier d'un
|
|
compte porte son adresse email (slugifiée), indépendamment du nom
|
|
donné à son jeu. Toujours rendu unique de la même façon (suffixe
|
|
-2/-3...) si, par un hasard extrême, le dossier existe déjà.
|
|
|
|
game_type : "document" (défaut, éditeur générique actuel) ou "jeu_2d"
|
|
(éditeur de scène — voir get_game_type.py) — choisi une fois pour
|
|
toutes à la création, gate quel éditeur/quel rendu jouable ce jeu
|
|
utilise (voir routes/screens/screen_edit.py)."""
|
|
slug = slugify(slug_override) if slug_override else slugify(name)
|
|
base = slug
|
|
n = 2
|
|
while os.path.isdir(game_dir(base)):
|
|
base = f"{slug}-{n}"
|
|
n += 1
|
|
slug = base
|
|
|
|
os.makedirs(game_dir(slug), exist_ok=True)
|
|
|
|
index_html = f"""<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{name}</title>
|
|
<link rel="stylesheet" href="index.css">
|
|
</head>
|
|
<body>
|
|
<h1>{name}</h1>
|
|
<p>Squelette généré par le moteur Forge — à remplir au fur et à mesure
|
|
des fonctionnalités du jeu.</p>
|
|
<script src="index.js"></script>
|
|
</body>
|
|
</html>
|
|
"""
|
|
index_css = """body {
|
|
font-family: system-ui, sans-serif;
|
|
margin: 40px;
|
|
color: #222;
|
|
}
|
|
"""
|
|
index_js = """// index.js — point d'entrée du jeu, généré par le moteur Forge.
|
|
console.log("Jeu chargé.");
|
|
"""
|
|
with open(os.path.join(game_dir(slug), "index.html"), "w", encoding="utf-8") as f:
|
|
f.write(index_html)
|
|
with open(os.path.join(game_dir(slug), "index.css"), "w", encoding="utf-8") as f:
|
|
f.write(index_css)
|
|
with open(os.path.join(game_dir(slug), "index.js"), "w", encoding="utf-8") as f:
|
|
f.write(index_js)
|
|
|
|
conn = connect(slug)
|
|
conn.executescript(
|
|
"""
|
|
CREATE TABLE _meta (key TEXT PRIMARY KEY, value TEXT);
|
|
CREATE TABLE _definitions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
table_name TEXT NOT NULL UNIQUE,
|
|
created_at TEXT DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE TABLE _fields (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
definition_id INTEGER NOT NULL REFERENCES _definitions(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
type TEXT NOT NULL,
|
|
relation_definition_id INTEGER REFERENCES _definitions(id),
|
|
required INTEGER NOT NULL DEFAULT 0,
|
|
position INTEGER NOT NULL DEFAULT 0
|
|
);
|
|
"""
|
|
)
|
|
conn.execute("INSERT INTO _meta (key, value) VALUES ('name', ?)", (name,))
|
|
conn.execute("INSERT INTO _meta (key, value) VALUES ('game_type', ?)", (game_type,))
|
|
conn.commit()
|
|
conn.close()
|
|
return slug
|