Illustration

Niveau

Un niveau est stocké en JSON, décrivant l'ensemble des calques, collisions, points de localisation, lumières, état de l'éditeur et chemin vers le LevelGraph.


// Extrait d'un fichier level.json
{
  "layers": [
    {
      "opacity": 1.0,
      "tiles": [
        {
          "TileMap": "dungeon",
          "x": 18, "y": 19,
          "Originalx": 1, "Originaly": 1,
          "rotation": 0,
          "flipHorizontal": false,
          "flipVertical": false
        },
        /* … autres tuiles … */
      ]
    },
    /* layers 1 à 8 vides ou partiellement remplies */
  ],
  "currentLayer": 0,
  "currentTool": "LocationPoint",
  "viewport": {
    "panningOffset": [-456.0, -508.5],
    "zoom": 2.5
  },
  /* … autres sections … */
}
      

📐 Coordonnées & dimensions

  • x, y : position de la tuile dans le monde (grille)
  • Originalx, Originaly : indices de la tuile dans la source TileMap
  • rotation : angle en degrés (0, 90, 180, 270)
  • flipHorizontal / flipVertical : retournement

TileMaps

La section tilePalette décrit les tilesets chargés :


"tilePalette": {
  "currentTileMapIndex": 0,
  "tileMaps": [
    {
      "name": "dungeon",
      "filepath": "C:\\…\\Dungeon Tile Set.png",
      "tileSize": 16,
      "colorKey": null,
      "zoom": 1.0,
      "panningOffset": [0, 0]
    }
  ]
}
      
Info : Les chemins de TileMap sont enregistrés en absolu ; si vous déplacez vos dossiers, éditez manuellement ou remplacez-les par des chemins relatifs.

Animations

La section animations liste chaque animation avec son nom, durée, vitesse, boucle, état de lecture et ses keyframes :


"animations": [
  {
    "name": "animation_1",
    "end": 2.0,
    "speed": 1.0,
    "loop": false,
    "play": false,
    "keyframes": []
  },
  {
    "name": "test",
    "end": 1.5,
    "speed": 2.0,
    "loop": true,
    "play": true,
    "keyframes": [
      {
        "tile_map": "dungeon",
        "x": 24, "y": 20,
        "layer": 0,
        "time": 0.402,
        "Originalx": 3, "Originaly": 5,
        "rotation": 0, "flipH": false, "flipV": false
      },
      /* … autres keyframes … */
    ]
  }
]
      

🔑 Keyframes de suppression

Quand vous supprimez une tuile animée, un keyframe de suppression est généré :


{
    "tile_map": "",
    "x": 24,
    "y": 20,
    "layer": 0,
    "time": 1.17,
    "Originalx": 0,
    "Originaly": 0,
    "rotation": 0,
    "flipH": false,
    "flipV": false
}
      
Info : Un keyframe dont tile_map est vide indique une suppression de tuile à cet instant.

💡 Lumières

Les sources lumineuses sont enregistrées dans la section lights du JSON :


"lights": [
  {
    "x": 376.4,
    "y": 367.4,
    "radius": 59.79,
    "color": [255,180,80],
    "blink": false
  }
  /* … autres lights … */
]
      
  • x, y : position dans le monde (coordonnées du centre)
  • radius : rayon d'éclairage
  • color : couleur RGB
  • blink : clignotement activé ou non
Attention : Si globalIllumination est à 1.0, les lights ne sont pas actives – baissez la valeur dans settings.globalIllumination.

LevelGraph (Nodes)

Le chemin vers le fichier .lvg du graphe nodal est indiqué en fin de JSON :


"levelGraph": "C:\\…\\test_graph.lvg"
      
Info : Au chargement, l'éditeur essaie d'abord ce chemin absolu, puis un chemin relatif depuis le dossier du level si l'absolu échoue.

🗃️ Format des fichiers LevelGraph (.lvg)

Le fichier .lvg stocke l'ensemble des graphes nodaux d'un niveau. Chaque graphe correspond à un rectangle de collision dans l'éditeur et contient des nœuds connectés entre eux pour définir des logiques de gameplay.

Lors de la sauvegarde d'un niveau, un fichier .lvg est automatiquement généré dans le même dossier que le niveau .json. Le chemin absolu de ce fichier est référencé dans le champ levelGraph du fichier JSON principal.

🔌 Structure des données

{
  "graphs": [
    {
      "rect_id": "UUID_du_Rectangle",
      "nodes": [...],
      "connections": [...]
    }
  ]
}
  • rect_id — Identifiant unique du rectangle de collision associé.
  • nodes — Liste des nœuds placés dans ce graphe, avec leur position et paramètres.
  • connections — Connexions entre les nœuds via leurs pins (exec ou data).

📄 Exemple complet

Voici un exemple de graphe associé à un rectangle de collision :

{
  "rect_id": "2bfc28a5-7d5a-4fa4-8d41-81fc045b16f2",
  "nodes": [
    {
      "node_id": "on_enter_197_226",
      "label": "On Enter",
      "pos": [197, 226],
      "properties": {}
    },
    {
      "node_id": "Set SpawnPoint_670_244",
      "label": "Set SpawnPoint",
      "pos": [670, 244],
      "properties": {
        "choice": "point_0"
      }
    },
    {
      "node_id": "Sequence_437_261",
      "label": "Sequence",
      "pos": [437, 261],
      "properties": {}
    },
    {
      "node_id": "Teleport_923_339",
      "label": "Teleport",
      "pos": [923, 339],
      "properties": {
        "choice": "point_0"
      }
    },
    {
      "node_id": "Print Console_675_408",
      "label": "Print Console",
      "pos": [675, 408],
      "properties": {
        "value": "Hello World"
      }
    },
    {
      "node_id": "Get Player Health_543_498",
      "label": "Get Player Health",
      "pos": [543, 498],
      "properties": {
        "health": 200
      }
    }
  ],
  "connections": [
    {
      "out_node": "on_enter_197_226",
      "out_pin": "out",
      "in_node": "Sequence_437_261",
      "in_pin": "in"
    },
    {
      "out_node": "Sequence_437_261",
      "out_pin": "out0",
      "in_node": "Set SpawnPoint_670_244",
      "in_pin": "in"
    },
    {
      "out_node": "Sequence_437_261",
      "out_pin": "out1",
      "in_node": "Teleport_923_339",
      "in_pin": "in"
    },
    {
      "out_node": "Sequence_437_261",
      "out_pin": "out2",
      "in_node": "Print Console_675_408",
      "in_pin": "in"
    },
    {
      "out_node": "Get Player Health_543_498",
      "out_pin": "health",
      "in_node": "Print Console_675_408",
      "in_pin": "value"
    }
  ]
}

🧠 Analyse du graphe

  • On Enter — Événement déclenché quand le joueur entre dans la collision.
  • Sequence — Exécute plusieurs branches dans l'ordre : spawnpoint → téléportation → console.
  • Set SpawnPoint — Définit le point d'apparition.
  • Teleport — Téléporte le joueur à un point nommé point_0.
  • Print Console — Affiche dans la console le texte "Hello World" et y ajoute aussi la vie du joueur via le nœud Get Player Health.

🧩 Autre exemple de graphe (collision secondaire)

{
  "rect_id": "f4685698-3196-480a-b141-cdff2d4d86c7",
  "nodes": [
    {
      "node_id": "on_start_320_284",
      "label": "On Start",
      "pos": [320, 284],
      "properties": {}
    },
    {
      "node_id": "Set MaxHealth_550_354",
      "label": "Set MaxHealth",
      "pos": [550, 354],
      "properties": {
        "health": "20"
      }
    }
  ],
  "connections": [
    {
      "out_node": "on_start_320_284",
      "out_pin": "out",
      "in_node": "Set MaxHealth_550_354",
      "in_pin": "in"
    }
  ]
}

Ce graphe initialise la santé du joueur à 20 au début du mode Play.

Remarque : Un même événement (par ex. On Start) ne peut apparaître qu'une seule fois dans un même graphe.

Paramètres

La section settings stocke les préférences de l'éditeur pour ce niveau :


"settings": {
  "backgroundIndex": 21,
  "globalIllumination": 0.0,
  "start_mode": 0,
  "showLights": true,
  "showCollisions": true,
  "showLocationPoints": true,
  "playerSpawnPoint": null,
  "keyframeOverlay": true
}
      
Attention : Certaines options (ex. playerSpawnPoint) peuvent être null si non définies ; vérifiez leur existence avant utilisation.

Envie d'en savoir plus ?

Consultez les pages suivantes pour explorer les fonctionnalités clés de l'éditeur :

  • 🔧 Interface — Comprendre les outils de dessin, la gestion des layers et le fonctionnement du viewport.
  • 🎞️ Animations — Créez, éditez et déclenchez des animations dans vos niveaux à l'aide de la timeline visuelle.
  • Éditeur Nodal en action