Roguelike 1 - Building a game loop
This is the first of several posts I’m writing to catalogue the development of my game.
Building a roguelike
Roguelikes, a genre named after the first of it’s kind, Rogue, is a turn based game where the player has infinite amount of time to make a move. Usually roguelikes offer randomized worlds and intricate, deep gameplay. The first Rogue was made in 1980 so it plays fully in the terminal using ASCII graphics. Moderns roguelikes often do feature better graphics but there are still plenty of new ones out there that focus soleley on gameplay.
Roguelikes are a great way for a programmer to flex the old development muscle. Games, for most developers, are not part of their day-to-day job while there are a lot of skills involved that are worth practicing such as algorithm design, the need to logically structure a large codebase, and unless you’re already perfect at the previous, a lot of refactoring. They generally require minimal graphics so there’s no need to be worried about designing characters and what not.
Here are two screenshots of my current work-in-progress. First is a completely randomized island with climate zones:
The second is a dungeon, demonstrating field of vision.
Some initial thoughts
Alright so HTML. Looking at the ASCII based roguelikes, the first thing that popped into my head was a grid of thousands of block elements. All these elements can have a class and a single character based on what kind of tile they represent, like the player, or grass, or rocks… This can be styled with common CSS.
I also decided to make a simple but proper game loop as opposed to using just events, so that keyboard or mouse interaction can be more fluid, and so I can make the occasional animation. Then I thought I’d make it state based because screen manipulation would not be very quick or easy. See, with canvas or a similar tech you just clear the screen and draw different stuff, but HTML doesn’t work like that; I would have to depend on div insertion and removal which is slow.
The Basics: Game loop
requestAnimationFrame, a more sturdy alternative to
setInterval. All you need to do is call the start, stop and pause methods to get it going.
Here’s a small jsFiddle to demonstrate:
Engine itself is an object literal, because juggling scope with
requestAnimationFrame is a pain. My first attempts used an object, but
window kept creeping back into scope.
The most interesting part here is the
This continuously runs the
loop function. Inside the loop function, screen is always drawn, but the game is only updated when it’s not paused.
Because it’s a simple loop, this just runs requestAnimationFrame as often as possible, which is max 60 times a second. If you add heavy processing in the update or draw method, this will slow down. Fancier games need fancier loops to keep a similar speed but with a turn based game I didn’t feel that was necessary.
Games are made of several parts that needs separate key bindings, mouse events, screen handling and content. For instance, in a menu the up or down buttons do different things than they would in the game itself; one moves through the options, the other moves the player around. One way of dealing with these differences without resorting to giant IF statements is the state machine.
There are three parts to this. The first is a
State object, which mimics the methods of the game loop: init, start, stop, draw and update.
The second is
StateMachine, a singleton responsible for maintaining the state stack, keeping a particular state active, and switching from one state to the other.
The third is a small change to the
engine object. Gone are the
paused variables. These are moved to
State. Engine should also be calling the proper methods in the active state. As per the example below:
Breaking down the code in there, first up is the StateMachine object:
Straight forward: a stack of states, one method to add a state to the stack, and one method to activate a state with a particular name.
When adding a state, I decided not to expose the
name, which will be used for switching, everything else is optional. States don’t need to implement everything. Continuing from the above:
State class. I’ll show part of it to give you an idea of how those methods above are called. For the working code, please see the fiddle.
This way of calling methods accomplishes a few things. First, it allows me to decorate or add to any or all of the methods before calling the user-defined ones in the state object. This is helpful because second, my implementation of
State in the actual game is larger: every state also has its own set of key- and mouse bindings. I can handle keys in the update loop without the need to scaffold it into every
update method in every added state. Third, thanks to
call, inside the start, init, draw, update and stop methods,
this will represent the State object itself, so
this.keys is valid code when implementing a method through
That’s all for the game loop. I’ll talk about the way I’m using HTML elements to create my game in part two
Jorg is a SAP and UI5 developer.