Wednesday, September 18, 2013

1000 Dungeons

This blog post is an introduction to the Torque 2D game I'm working on and a highlight of some of the custom features and functions I've built for the game so far.

About 1000 Dungeons

1000 Dungeons is a Rouge like game of exploration, battle, and crafting. The game features 1000 randomly generated dungeons spread out over 10 different randomly generated lands. The goal is to make it through as many of the dungeons as you can. If you die in dungeon 999, you have to start over from number 1. To help you on your journey, there will be weapons to upgrade, items to craft, and varied creatures to hunt and be hunted by.


World Generation

The first element I tackled for the game was creation of the randomly generated worlds. The world generation uses an algorithm based on a seed and grow process. There are 5 basic land types:

  1. Grass
  2. Water
  3. Desert
  4. Mountain
  5. Forest

Each terrain type can have a frequency value set from script before world generation. This allows the game to then control the primary terrain type for each world that gets generated. Terrain types play an important role in the game, as certain monsters will only be in a dungeon that is on a specific terrain type. And since the monsters drop the resources you need to craft items and upgrade weapons, making sure you get all the different creature types is important to being able to make it through all of the dungeons.

Here is an example of what the world might look like after seeding:
The frequency values across all terrain types totals 100, which is the number of seed tiles that will be placed in the world. Once the seed tiles are placed, the code loops through the map and starts to grow the terrain type it encounters into any empty cells adjacent to the current cell.

Here is what the above image would look like after one growth round:
This basic growth routine continues until all of the tiles have been filled. We now have a world.

All of the above is handled by a custom C++ class written and integrated into the T2D engine.

Dungeon Generation

The dungeon generation is another custom C++ class added to the engine. Dungeon generation is room based. It always starts with a random sized room in the middle of the dungeon. Once that initial room is placed, a random location is picked until a we find the wall of an existing room that doesn't already have an opening on either side of our spot. The wall is removed from that location and left as either an empty space, or randomly chosen to be a door. If at any point we loop 10000 times without being able to create a room, then we call the dungeon done.

Example image of a generated dungeon:

Rendering of Worlds and Dungeons

Example of part of a dungeon being rendered:
Example of part of a world being rendered:
The rendering of the world and the dungeon are both handled with the excellent new CompositeSprite object. When a world is loaded or generated new, the game builds a composite sprite querying the C++ generation code for the tile type and setting the sprite to the correct image. This allows me to easily swap out new graphics for each tile type and only have to make script changes.

Dynamic LOS Shadows

A dungeon crawl wouldn't be a dungeon crawl if you could see everything in the dungeon. To fix that, I added another new class to the engine that builds dynamic shadows based on the players position.

This was a fun class to write as unlike the dungeon and world generation stuff, this actually renders to the scene, and is a new child of SceneObject. The object takes a copy of the current dungeon map and a radius value and automatically calculates the shadows for the walls of the dungeon based on the position of the player.

This code was based on the resource found on the site for dynamic shadows in TGB. Converting the code from that resource took a bit of time, but in the end, I got it all worked out.


In addition to the dynamic shadows above, light plays an important role in the game. Including the color of the light. Time for another custom scene object. This one renders a gradient circle from the player getting darker as it moves away. This can be dynamically updated with size and color based on what kind of light the player has equipped.

Here is an example with a base yellow torch:
The color matters, because for some creatures, the color of your torch can weaken or strengthen them. All things the player has to find out as they crawl through the many dungeons.

That covers the custom C++ side of the changes I've made so far for 1000 Dungeons. In the next update I'll go over some of the script side systems I've implemented, including the inventory system (complete with drag and drop), event call backs and all sorts of fun stuff.

If you want to read more about the development of 1000 Dungeons, be sure to follow our page on IndieDB.

If anyone has any specific questions on anything or is interested in more details on anything, just ask here in the comments and I'll give you all the information I can.