-
Notifications
You must be signed in to change notification settings - Fork 4
Levels
In SKX, rooms are the fundamental unit of game design, each room being a "level" in the game.
The data for a given room is loaded based on the room number, and the story the player is currently playing.
When the game loads the data for a room the work directory
is checked for the presence of a file named room_xxs.json where
xx is the hexadecimal room number and the s is the story ID (e.g. c, p, ...)
If this file is found, it is used, otherwise the internal Bundle is checked for the room. If the room is not found (which does not occur during normal gameplay), the engine will load a blank room (of the default size with a blank layout).
A standard SKX room is 17x14 cells, with the leftmost and rightmost columns being used for the solid bounding blocks, the top row being used for a solid ceiling (usually hidden behind the HUD), and the bottom row also solid blocks.
Custom dimensions can be used, however rooms other than 17x14 will need to define their own borders; standard size rooms can also define their own borders by turning the UseDefaultBorders property off. If UseDefaultBorders is true, and the room is 17x14, then the first and last rows and columns are automatically replaced by the engine.
Warning: Large room support is provided for specific scenarios and story arc progression. SKX always renders the entire room to a buffer internally regardless of size and/or Dana's position, so the theoretical size of rooms is limited by the ability for the game to create this off-screen buffer. It is not recommended to create areas larger than 1000 cells^2 (e.g. 100x100, 200x500, ...) as a single room.
By default, game objects (including Dana) will wrap around to the other side automatically if they leave the valid dimensions of the room.
Exceptions are some classes of enemies which will disappear off bottom of the level without wrapping, and enemy projectiles which do not wrap.
Unlike the NES version (which indexed into arbitrary data), out-of-bounds accesses to the cell grid (e.g. Dana trying to create a block off the side of the level) are wrapped appropriately.
The background is a tilemap used to construct the background visual layer of the level. It holes one Tile per cell, up to the cell dimensions of the world/room.
Similar to the background, the super foreground is a tilemap that, if present, is used to construct the super foreground layer which appears in front of all objects and terrain. The super foreground is optional for a layout.
The cell grid (aka foreground) of the room contains an array of Cell values the correspond to the world-size grid of blocks in the level.
Cell.Empty is empty space, with other values being terrain (blocks), items, keys, doors, decorations, and other items that
are placed in the cell grid.
Each cell in the grid has two components that are ORed together:
-
Contents (low word) -- Either
Emptyor the contents of the space -
Modifier (high word) --
Normal,Covered,Cracked,Hidden, xorFrozen
+
= 
One peculiarity worth noting, which is a hold over from the original NES logic,
is that breakable (dirt) blocks with nothing inside are use Cell.Dirt as their
value (with no modifier), rather than, for example Cell.Covered | Cell.Empty.
Likewise an empty frozen block is usually stored as Cell.FrozenBlock and not Cell.Frozen | Cell.Empty.
There are also certain conditions under which specific items will be removed from the cell grid automatically upon a room loading:
- Items flagged as
FirstTry(see reference) are only present during Dana's first attempt at the level. On subsequent attempts (after a death), the items are removed. - Keys that Dana already holds in his inventory will not be placed
-
Persistentitems (such as Seals) that Dana has already collected will not be placed - Doors that Dana already has opened will be opened as part of the level start sequence.
- Spells may execute immediately upon level load which modify the layout before it is visible to the player.
Every room has a hexadecimal room number unique to the story it is a part of. In most rooms the room number is well-known and visible on the title card, however some bonus, hidden, and finale rooms instead use room names which are shown instead.
By default new game sessions begin on room 1. The next room loaded is determined by the various "Next Room" properties of the current room.
If a room name is provided, it is used instead of the room number. If the room name is omitted, ROOM xxx is used as the room name, where xxx is the room's number in hexadecimal format.
As in the original NES game, each room is part of a "Shrine" which is displayed on the title screen and in load game menus. The shrine is stored as an integer from 0 to 0x28. The Classic story uses shrine 0x3D (Solomon) for any value over 0xA (Pieces), while other story types can use any shrine ID.
Defines the room number Dana travels to when he exits the room normally.
Defines the room number Dana travels to when he exits the room using a secret exit (see Doors).
Defines the room number Dana travels to when he exits the room using a gold wing (see Doors).
A layout can define the initial life that Dana/Adam start the level with; if not provided, the default is the standard 10,000 life.
Determines which song is used for the room.
| ID | Song |
|---|---|
| 0 | Normal level (NES) |
| 1 | Hidden level (NES) |
| 2 | Easter egg |
| 3 | Puzzle/Bonus |
| 4 | Techno |
Determines which dynamic audio effect is in use in the room.
| ID | Name | Special Sauce |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--| | 0 | Normal | LF0=Life, LP1=Life*2-1, LF1=Life*-1.5 | 1 | Special Room A | F0=dana.x, F1=dana.y, F2=0.75, LF0=Life*-1, LF1=Life*-1.5, LP1=Life*2-1, LF2=Life*-1.5 | 2 | Special Room B | F0=Life F1=-Life F2=0.75 LF0=Life*-1.5 LF1=Life*-1.5 LP1=1-Life*2 LF2=1-Life*-2 | 3 | Special Room C | F0=-Life F1=Life F2=0.75 LF0=Life*-1.5 LF1=Life*-1.5 LP1=1-Life*2 LF2=1-Life*-2 | 4 | Special Hidden | | 5 | Full Volume | No processing