diff --git a/documentation/levels/README.md b/documentation/levels/README.md index eee151b..26dfdfe 100644 --- a/documentation/levels/README.md +++ b/documentation/levels/README.md @@ -1,8 +1,9 @@ # Game levels ## Table of contents +* [File Formats](./file_formats.md) * [Signals](./signals.md) * [Cutscenes](./cutscenes.md) (TODO) -* Level objects +* [Level objects]() * [Triggers](./level_objects/triggers.md) (TODO) * TODO: more as encountered \ No newline at end of file diff --git a/documentation/levels/file_formats.md b/documentation/levels/file_formats.md new file mode 100644 index 0000000..30dcb1c --- /dev/null +++ b/documentation/levels/file_formats.md @@ -0,0 +1,60 @@ +# Level File Formats + +## Levels + +Each level of the game is defined via two files: + +1. Blender (`.blend`) file +2. YAML (`.yaml`) file + +These files are located in the `assets/test_chambers//` directory +corresponding to a given level. + +### Level layout (Blender file) + +A level's `.blend` file specifies its static 3D layout and lighting, as well as +the dynamic objects contained within (e.g., cubes, doors, elevators, etc.) and +any animations, such as for moving platforms. These files can be edited in +[Blender](https://www.blender.org/) as with any other `.blend` file. + +Reusable objects are defined in their own `.blend` files located in the +`assets/models/` directory and then referenced from the level `.blend` files +which use them. At export time, level object data beyond position, rotation, +etc. is generally not read from `.blend` files. Rather, objects use a naming +convention which tells the exporter their type and parameters so information +like the mesh and material data can be looked up elsewhere. This naming +convention is also what hooks the objects up to code. To learn more, see +[Level Objects](./level_objects/README.md). + +### Level scripting (YAML file) + +The second file that makes up a level is its `.yaml` file. This file contains +its [cutscene steps](./cutscenes.md) and [signal operators](./signals). At build +time, the data in these files is used to generate corresponding C code. See the +linked pages for more details. + +## Materials + +As mentioned above, material data for objects is not read from their `.blend` +files. This is also true for static level geometry. Instead, all materials are +defined in `.skm.yaml` files located in the `assets/materials/` directory. These +YAML files specify textures, colors, as well as other more complex RDP/RSP +settings. They are currently used at export time to generate display lists using +libultra. Since one of the goals of this project is to build a +library-independent abstraction layer, it is currently not a priority to +document the format of these files. + +When exporting a level, only the name of each material is used. The actual +material information is looked up in the `.skm.yaml` files using the name. This +means that a level's appearance in Blender will not necessarily match the game. +However, for convenience, `assets/materials/materials.blend` contains Blender +versions of the various materials so that it is easier to apply them and also +get a reasonable visual approximation while editing. + +## TODO + +* Asset pipeline +* Blender scripts +* Skeletool +* Exporter scripts +* Material YAML file structure (ideally after library-independent abstraction is done) diff --git a/documentation/levels/signals.md b/documentation/levels/signals.md index c7cbf2e..c5c581e 100644 --- a/documentation/levels/signals.md +++ b/documentation/levels/signals.md @@ -1,22 +1,28 @@ -# Level signals +# Level Signals -Signals are a way to indicate that something has happened in a level. They can be emitted by: +Signals are a way to indicate that something has happened in a level. They can +be emitted by: * Level objects * Triggers * Cutscenes * Signal operators -Other parts of the level can listen for signals in order to perform some sort of action. The possible listeners are: +Other parts of the level can listen for signals in order to perform some sort of +action. The possible listeners are: * Level objects * Cutscenes -Signal information is output into generated level definition C source files at build time by the Lua scripts in `tools/level_scripts/`, initiated by `export_level.lua`. +Signal information is output into generated level definition C source files at +build time by the Lua scripts in `tools/level_scripts/`, initiated by +`export_level.lua`. -The code for sending and receiving signals is in `src/scene/signals.c`. The engine uses this to wire up the various emitters and listeners. +The code for sending and receiving signals is in `src/scene/signals.c`. The +engine uses this to wire up the various emitters and listeners. ## Level objects -Level objects which send or receive signals have the relevant signal name as part of their object name in the level's `.blend` file using the format: +Level objects which send or receive signals have the relevant signal name as +part of their object name in the level's `.blend` file using the format: ``` @object_type signal_name ``` @@ -25,32 +31,52 @@ For example, consider the following object names: * `@ball_catcher exit_activate` * `@door exit_activate` -In this example, the ball catcher sets the `exit_activate` signal when activated. The door listens for that signal, and so it will open when a ball reaches the ball catcher. +In this example, the ball catcher sets the `exit_activate` signal when +activated. The door listens for that signal, and so it will open when a ball +reaches the ball catcher. -There are various other level objects that can send and receive signals, including those that the player cannot directly interact with such as the indicator light strips (they are materials). Buttons are special cases and can set two possible signals: one for a regular press and another for a press with a cube. This is useful for only progressing a cutscene once a level is properly solved. +There are various other level objects that can send and receive signals, +including those that the player cannot directly interact with such as the +indicator light strips (they are materials). Buttons are special cases and can +set two possible signals: one for a regular press and another for a press with a +cube. This is useful for only taking an action once a level is properly solved. +Note that the exact name structure differs per object. +See [Level Objects](./level_objects/README.md) for more details. -Objects which can be deactivated will clear their associated signal when that occurs. +Objects which can be deactivated will clear their associated signal when that +occurs. ## Triggers -Triggers are volumes in a level that set signals depending on which object type intersects with them. Like level objects, this information is defined in their object name in the level's `.blend` file. Trigger object names are of the form: +Triggers are 3D volumes in a level that set signals depending on which object +type intersects with them. Like level objects, this information is defined in +their object name in the level's `.blend` file. Trigger object names are of the +form: ``` @trigger PLAYER_CUTSCENE_NAME player_signal_name CUBE_CUTSCENE_NAME cube_signal_name ``` -`player_signal_name` is set/unset when the player enters/leaves the trigger and `cube_signal_name` is set/unset when a cube enters/leaves the trigger. +`player_signal_name` is set/unset when the player enters/leaves the trigger and +`cube_signal_name` is set/unset when a cube enters/leaves the trigger. For more information on triggers, see [Triggers](./level_objects/triggers.md). ## Cutscenes -Cutscenes can set or clear signals using the `set_signal` and `clear_signal` steps, respectively. For example: +Cutscenes can set or clear signals using the `set_signal` and `clear_signal` +steps, respectively. For example: ``` set_signal door_activate [...] clear_signal door_activate ``` -Cutscenes can also wait for a particular signal to occur using the `wait_for_signal` step. A number of frames to wait after the signal is set can optionally be specified. For example: +The way this works internally is by altering the default state of the signal. In +the above example, in between `set_signal` and `clear_signal`, other signal +emitters such as buttons would clear the signal when activated. + +Cutscenes can also wait for a particular signal to occur using the +`wait_for_signal` step. A number of frames to wait after the signal is set can +optionally be specified. For example: ``` [...] wait_for_signal player_in_trigger @@ -65,14 +91,18 @@ For more information on cutscenes, see [Cutscenes](./cutscenes.md). ## Signal operators -Level definition YAML files can optionally contain an array property named `operators`. Each array entry must be an equation matching one of the following forms: +Level definition YAML files can optionally contain an array property named +`operators`. Each array entry must be an equation matching one of the following +forms: ``` signal_name = not other_signal_name signal_name = signal_a or signal_b signal_name = signal_c and signal_d ``` -Only one `not`, `or`, or `and` operator is allowed per entry. If more complex combinations are required, operators can use signals defined by previous operators. For example: +Only one `not`, `or`, or `and` operator is allowed per entry. If more complex +combinations are required, operators can use signals defined by previous +operators. For example: ``` door_not_activated = not door_activated cube_not_in_room = not cube_in_room