Last time, I reported that I was making good progress on importing levels from a map editor for The Dungeon Under My House, my non-violent, first-person role-playing game and my second Freshly Squeezed Entertainment project.
I anticipated that I only had a few hours left to go before I could confidently use the new level loader code to load the dungeon, allowing me to easily create the dungeon layout.
Sprint 2024-14: Level editor
Planned and incomplete:
- Create level editor
I anticipated incorrectly.
Despite putting in a relatively significant amount of time into game development this week, I have not finished the level loader code.
But I am a lot more confident that I am almost finished with it. This time.
As you recall from the last couple of reports, I’ve been trying to leverage Tiled, the general-purpose level editor, to create the dungeon layout. Up until this effort, my small test dungeons have been created in code. Just trying to add a door and a single cell room beyond it already showed me how painful and error-prone it was going to be to continue without a level editor.
Of course, using a general-purpose tool like Tiled meant learning how Tiled works, then figuring out how best to use it for my own purposes. The Tiled Discord, specifically the very knowledgeable eishiya, has been a great help.
So to recap what I’ve accomplished so far, I have a DungeonGridCell which looks like:
struct DungeonGridCell { DungeonGridCell(); ~DungeonGridCell() {} DungeonFloorType floorType; DungeonCeilingType ceilingType; DungeonWallTypes walls; OrientationToDungeonDoorIDs doors; DungeonPortals portals; DungeonLight lightSource; DungeonLight lightAmbience; bool valid; };
The floor and the ceiling are defined by single values, but the walls, doors, and portals include not only the type but also the orientation. That is, you can have a cell with zero, one, two, three, or four walls.
So how would I represent a single grid cell in Tiled with all of that data?
I use layers.
So each cell is actually split out across multiple layers of data. I have a floor layer with tiles to represent the floor type, and I have something similar for the ceiling.
Doors and portals are represented as objects in their own object layers. Basically, I can place a door like a tile, even rotating it to get it into the correct orientation, and the only interesting thing I need to do when loading it later is calculate the cell it is in using its (x,y) position.
I tried to see if I can do the same with walls. See, the DungeonGridCell allows for the possibility of different types of walls in the same cell, but to represent that in Tiled would require a ton of different kinds of transition tiles depending on how many wall types I wanted to represent.
Maybe that’s not true. I think I know enough about Tiled to be able to create a tile layer, offset it so that the tiles show up in the corners of the regular floor tiles, and place the corners, then use the automap feature to generate the correct wall tiles, but it still sounds like a lot of work.
But if walls were objects, then I can place an arbitrary wall in an arbitrary location. Except the exported JSON would balloon in size. I calculated that if even half of the tiles in a 500×500 map had at least one wall, it would take at least ~130 MB just to represent walls in the JSON file. That’s way too large, even with compression, and I want to ensure the download size is small for this project.
So instead, I decided to limit cells to only have one type of wall possible, even if the code allows otherwise, mainly to make it easier to create Tiled maps.
Using the above two rows of tiles, I can represent every configuration of walls for a given wall type (dirt or stone). Eventually I will add more wall types, and maybe variations of walls to break up the tedium.
I can easily create this test dungeon which uses single walls, corners, hallways, and dead ends. I found I don’t need to create a tile that represents an enclosed cell, but maybe in the future I might have such a room with a ladder in it? So I’ll keep the tile in the tileset.
Now that I have a dungeon, I can save it as a JSON file.
But then I needed to import that JSON file and turn it into a dungeon level full of DungeonGridCell objects.
That’s what my DungeonLoader code is doing, and in the last week, I have been able to test-drive the code that can load the layers that represent everything except the dungeon light source and the light ambience.
Loading dungeon walls was slightly complicated due to needing to not only know which tile I was looking at but also what orientation the tile was in. The corner wall tile, for instance, represents west and north walls by default, but when rotated, Tiled represents that tile with some high-order bits flipped to represent horizontal, vertical, and diagonal rotations, which means I need to write code that looks at those bits and figure out which walls need to be represented.
I finished the week by almost getting the light source loading code in, which required converting from the hex representation of the light source’s color (a custom property I added to the tile in Tiled) to the Color object I have in my game. But my code isn’t working correctly, and I am starting this week by figuring out why.
Thanks for reading!
—
Want to learn when I release The Dungeon Under My House, or about future Freshly Squeezed games I am creating? Sign up for the GBGames Curiosities newsletter, and download the full color Player’s Guides to my existing and future games for free!
One reply on “Freshly Squeezed Progress Report: Almost Done Loading the Dungeon”
[…] my last report, I had mostly finished my work of creating the level loader code for The Dungeon Under My House, my […]