This week I worked on one big thing that lead to a thousand problems, but it was worth it, because now the Monolith has random level generation!
So this week the first thing I got done was random level generation, which is obvious a key feature in all rogue-like games. How the level generation is actually very simple:
1. The first room is created in the center of the map.
2. A random wall is chosen, and a door is created somewhere on that wall.
3. A random width and height for the next room is generated, and then the level checks if that room can fit next to the door.
4. If it can’t fit, then the room is not created and the cycle returns back to step 2.
5. If it can, the room is created, and the cycle returns back to step 2. If the number of rooms created is equal to the maximum amount of rooms, the generation is done.
And that’s it! There are actually some really cool results that come from this, and every time the level feels different, but an average level looks something like this
Sometimes a large room full of enemies is created, or maybe the level is a series of small rooms and hallways that have enemies sprinkled in. Each situation needs a different approach from the player, and there are many ways the player can choose to deal with each room. Hide behind a door and wait for the enemy to come to you, or run and gun through each room until you reach the end as the enemies struggle to catch up to you? Both are valid solutions!
Of course, what would a rogue-like be without a bunch of enemies? When each room is generated, the amount of mobs it can fit is calculated (the mob-per-tile ratio right now is 1/75, which I believe works nicely), and then each tile in the room is checked to place a mob. Each tile has a 33% chance to create a mob (which may be too much, and I will reduce that later). When a mob is created, to avoid all the mobs spawning in the top left corner, the next tiles counted through are 5 x 5 tiles away from the mob just created.
There were some changes to mobs this week to make them more difficult to fight. Now, enemy spells also home into players the same way player bullets home into the player’s target, but now they are a bit too hard… so I will continue to find the right blend for enemies, but it may be a while before they are exactly where I want them.
Multiplayer Woes and a Thousand Small Problems
So far in this entire project, most features have been added almost flawlessly, and sometimes they accidentally create new features! But everything must come to an end, unfortunately, and the first big problem I did not plan for in advance arose. That is, multiplayer players receiving the level from the server. At first, it seemed like it was as simple as sending a packet of the level tiles, colors, and which tiles where solid or not. However, sending all of that information was too much for one packet to carry, which then created a problem, the level had to be made in parts, instead of one method creating the level as it has so far. So to solve this, the level sent the tiles and solids information, then sent the colors, and everything seemed to work. Then the multiplayer was tested…
Oh my, the errors that began with the new loading level system for multiplayer clients. Before, the code never expected the player not to have a level when the game and player is created. This through errors left and right, broke the mob AI, and in general was an absolute mess! I spent 5/7 days this week working on cleaning up that mess. The worst part of fixing it, was that sometimes the multiplayer worked fine, then the next time it is tested, the game won’t even start!
The final solution to this, was created just today, and I had to handle all situations in which the level may not exist, and completely re-write the way multiplayer works, which deserves it own section…
A New Approach on Multiplayer
So the easiest way to fix the multiplayer for all players was to treat all players as if they are multiplayer players. Before, the game that had the server running had it’s own player. Now, the server is it’s own game running with no player attached to it, which saved a good bit of code from having to check if X object had to send X packet to the server or client, which became confusing at some times. Now, each player is a multiplayer player to the server, so there is no longer a need for a fix for both the server player and client player! This may be a bit difficult to understand, because it difficult to explain.
This change does make the game slightly more annoying to test now, though, because a server must be launched before a player can join to test something.
In the future, the plan is that the server would be a separate program, and I also have to figure out a way to run the game without a server for players who want to play single player.
Right now, the server acts as if it was a spectator, as it can see the entire map, until a player joins, where it just renders what the players can see. Not sure if there will be a need or want for a spectator mode, but it wouldn’t be that difficult to add now.
That’s about it for the changes this week. Not much new, but as described before, a lot of problems were created and fixed. Monolith sure is growing up quick, hard to believe it’s already 6 weeks in and so much has been done!