Ludum Dare has come and gone and I, being the busy person that I am, did not participate. But not to let a good idea go to waste I thought that maybe I could make a game from scratch really quickly. After all, I now have some experience working in Gamemaker Studio 2.
I have been on a little bit of a Roguelike kick recently playing games in this genre. Rogue Legacy and Spelunky are 2 of the games that I like to play most but recently I have started to play a little gem called Downwell. Downwell is a quaint little rogue like available for just about every platform under the sun. I have been playing it on my Playstation Vita and on my smartphone and I started thinking about what it would take to make something similar. After all, imitation is the sincerest form of flattery.
If we break Downwell into its 2 most basic parts there are vertical procedural levels and platforming. I have the platforming part down thanks to my work on Cursed Squire, and the platforming in this game would be even simpler than that, because the player will be constantly falling, I will not need to have the player be able to jump through platforms like in Cursed Squire, so I will “borrow” a lot of my platforming code from that game.
The second part is procedural levels. This part is going to be the hardest to do, mainly because of tweaking with variables so that levels are not incredibly easy nor completely impossible. Working on the newest game with the team over at Elektri has given me an idea of how to start with these levels using a ds_grid.
The first thing I will need to do is create a new script and make some macros for constant variables that I will need to refer back to several times.
The cells of the grid are going to be 32 pixels by 32 pixels each, and the values of the cells are either going to have a platform on them or be empty space that the player can fall through. To be able to get a visual representation of the level I created a 32*32 sprite and just made it solid red and a matching game object just called obj_solid. This game object is what is going to be put into the room to build our level.
#macro CELL_WIDTH 32
#macro CELL_HEIGHT 32
#macro PLATFORM -5
#macro VOID -6
In order to actually build the levels I created a level manager game object and put it into an empty room in Gamemaker. Downwell has tall and narrow levels, to build something similar my rooms are going to be 9 cells across by 100 cells in height. Inside the create event of my level manager I adjust the size of the room, and create local variables to reference the width and height of my level grid. Finally I will create the ds_grid that I will use to create the levels.
// Resize the room
room_width = CELL_WIDTH * 9;
room_height = CELL_HEIGHT * 100;
// Set the dimensions of the grid
var width = room_width div CELL_WIDTH;
var height = room_height div CELL_HEIGHT;
// Create the grid
grid = ds_grid_create(width, height);
Now that the grid has been created I can go about this in 2 different ways. I can fill the room with platforms and then carve out the empty space, or I can leave the grid empty and go through and place the platforms. With this example I am going to try to leave the room empty and add platforms instead of filling the room with platforms and carving out the empty space. So the next thing is to flag every single tile of our grid as void.
// Fill the grid with void
ds_grid_set_region(grid, 0, 0, width, height, VOID);
To place platforms inside of the empty grid I decided to loop through the entire grid and then I will choose if I should place a platform at a tile. I gave my script a 25% chance to place down a floor tile or leave it as empty space.
// The odds for creating a platform
var odds = 3;
// Flag the platforms
for (var cx = 0; cx < width; cx ++)
for (var cy = 0; cy < height; cy++)
if (irandom(odds) == odds)
grid[# cx, cy] = PLATFORM;
After filling the grid with the flags to see if the space is a platform or empty, I need to loop through the grid a second time and spawn in the ground platforms.
for (var xx = 0; xx <= width; xx++)
for (var yy = 0; yy < height; yy++)
if (grid[# xx, yy] == PLATFORM)
instance_create_layer (xx * CELL_WIDTH, yy * CELL_HEIGHT, "Instances", obj_platform);
All that is left is to test the game and see how it looks (I should point out that if you do not turn on views and give your camera a 16*9 vertical aspect ratio, your room will look a little bit weird).
Looking at this, apparently a 25% chance to spawn in a platform is a little bit too much. There is not enough space to be able to jump or free-fall. I want a fewer platforms than that a more negative space. Playing around with the numbers will be able to get you the amount of platforms that you would want for your own roguelike platformer. I switched mine over about 16% and I am pretty happy with the results.
After adding in the player object and my platforming code, ripped right out of Cursed Squire, I have a game object that I am able to navigate through a procedural generated well. All that is needed to turn this into something that people would want to play is some enemy types and combat mechanics.