Description of the gameYou control a character able to jump and climb ladders, and your goal is to simply reach the exit of a level, which are made of various sets of platforms, ladders, and hazard zones (spikes). Jack Benoit uses 4 layered tile maps:
- The parrallax background,
- The platforms,
- The ladders,
- The sprites (collectable items, decorations, etc).
Step 1. Generating a level layoutLevels are composed by a random set of discretely connected "rooms" (rectangles of 20x16 tiles). Each room can have up to 3 "walls", at its own edges. Two rooms are connected if their shared edge doesn't contain a wall. The structure becomes quite clear when you see a whole level. This one is made of 15 rooms:
function findPath(x, y, minDistance): if (x,y is goal and minDistance == 0) return true if (x,y not open) return false mark x,y as part of layout path switch(random number 1 out of 4): case 1: if (findPath(North of x,y, minDistance - 1) == true) return true case 2: if (findPath(East of x,y, minDistance - 1) == true) return true case 3: if (findPath(South of x,y, minDistance - 1) == true) return true case 4: if (findPath(West of x,y, minDistance - 1) == true) return true unmark x,y as part of solution path return falseOnce this is done, we make sure the structure is easily iterable, and each Room knows about the location of next and the previous ones.
Step 2. Generating a solution pathThe second step is the most critical to ensure the correctness. It's very easy, if you're not careful, to produce impossible levels! In our example, the player must always be able to navigate through all these rooms, to reach the last one. Given that the player movement is constrained by physics (he can jump 4-5 tiles high), we had to make sure that the vertical parts (two or more rooms vertically connected) were always in reach. That part proved to be tricky. I finally chose to create a solution path, i.e. a set of platforms and ladders that leads the player directly to the level exit, without interruption.
for each room in the layout: select a random point P1(X1,Y1) in the room select a random point P2(X2,Y2) in the next room of the layout set cursor C(Xc, Yc) to P1 while P2 is not reached by cursor: if (selectionFunction): create a platform between (Xc, Yc) and (X2, Yc) move cursor to (X2, Yc) else: create a ladder between (Xc, Yc) and (Xc, Y2) move cursor to (Xc, Y2)The selectionFunction is used to determine if we start by a ladder or a platform. It's randomized, however in order to generate well-designed levels, it will also take some heuristics into account, like the minimum length of a ladder or a platform.