From Start to Finish

Last month, I said that I wanted to have the game flow done by the end of the first week of this month. Did I actually get it done?

Short answer: No.

Games are complicated.

I already had most of the front end flow working at the point that post went up anyway. I made an adjustment to it, because there are two entry points to the game after getting to the end of the splash screen. At the moment the splash screen is a bit of text that says the game is in development, but at some point it is going to have a logo on it. After a few seconds, the game will do and check and decide what to do.

  • Is there a save file?
    • Yes
      • Go to the title screen -> menu screen
      • From the menu screen, continue, start a new game, show the options or quit
    • No
      • Show the options screen -> character creation -> intro cutscene -> intro dialogue -> game
The intro cutscene does not show, because I haven't made it yet, but that all flows correctly. The intro dialogue has some branching paths that lead to two outcomes: the player ends up in the hub world, or the credits play. Again, most of this worked when I wrote the post saying I wanted the flow done. So what did I actually need to do?

Moving between areas didn't work properly. The player always spawned at co-ordinates (100,100) which was fine for the initial interior level because it was inside the level's bounds. It also worked when moving between interiors because the player kept their position as the camera transitioned to the next room. But when loading into the hub world, the player was now spawned outside of the playable area and was blocked from getting in by the collision I'd added.

I'd had the foresight to give doors the properties to set co-ordinates to move the player to if they had moved between areas, but I hadn't actually set them up and the game wouldn't do anything with them even if they were. Doing this also brought another feature online - loading a save and being placed in the same room that the player visited before they quit. But it also revealed that other things were broke.

If reloading when the player was in an interior, and they weren't in the first room of the area, the player would be unable to move because their collision box had calculated incorrectly. After fiddling with the calculation for a little bit, this ending up working correctly, although I then discovered the same thing occurred with enemies.

There were also various other issues with enemies, and other objects in the level. If the objects were set to load when the level first loaded then they would. But I hadn't written the code to spawn them when the requirements to spawn them had been met.

While enemies spawned, they just stood there since there was no logic telling them to move or attack. I got some basic movement working, and made it so that only one enemy could attack at once. When leaving and returning to a room that had attacking enemies in, the enemies would no longer attack. This was because I'd made the enemies join what I called the Hivemind when the spawned with an id based on their spawn point, and when they respawned and tried to register with the Hivemind again, it ignored their request because that id was already in use.

To sort this, I added some proper cleanup code when leaving a level so that enemies would leave the Hivemind and any projectiles that hadn't yet collided with anything would just get removed so there weren't rogue projectiles waiting to hit the player when they returned.

The player couldn't take damage yet, and neither could the enemies. I made it so that if the player had a weapon then it could damage enemies and blockades. Things just disappeared since I hadn't done any animations, but logically it all worked.

Moving on from level stuff, I wanted to get the shop and costume selector working and that's when I realised I had no idea what I was actually making.

Back when I was making Halloween Game as 3DS homebrew, it was a game about going through dungeons and beating up various monsters. But, thanks to the lack of debugging tools, I hadn't got far enough into making it to question why. Making it as an actual thing to sell, I'd implemented the part where the player is explicitly told what the objective is, but getting to the objective still wasn't making much sense.

Watching a friend play Minish Cap, I realised I needed puzzles beyond having the right item to destroy a door. And I still had to work out what the boss fights were going to be.

The 3DS idea involved collecting costumes from chests but, beyond cosmetics, they had no other use. And with me already not having enough costume ideas to even fill 2 of the areas, that would mean none left for the shop. So I decided they would be only found in the shop, have stats that alter movement speed and damage, and some would come with their own items.

Making the shop work was not as easy as I thought. I needed text to wrap, the code that I had written previously didn't actually work, and there were bugs in pretty much every direction. The costume selector was much easier in comparison.

Then I needed to make layouts for the levels. Like I said, I wasn't looking for puzzles to be implemented, but wanted to go through each area, hit a trigger at the end of it, then move on until eventually hitting the end of the game. Before I started that, I was still hung up over boss fights. Then the designer, who is me, came up to me, who is the coder, and said "What if there aren't boss fights?"

"But what's the point of going through an area if there isn't a boss fight at the end?" coder-me asked.

Designer-me shrugged. "Dunno."

I'd previously thought about the boss characters displaying some kind of interest or personality that would somehow tie in to the fight - one of them would be an aspiring chef, and maybe the fight against them would be more of a puzzle where you have to try and poison their food without them noticing.

Not having fights would subvert expectations, but then it would mean that items had no purpose except for defeating enemies and destroying blockades on the way to the boss, and that didn't feel right.

I then had a couple of other ideas for boss fight alternatives which were fun, but I was torn because it would mean that the game was a splurge of random ideas instead of a tight, cohesive package. I was going to implement them anyway, because having something that was fun seemed more important than having something that made sense.

The next day designer-me reappeared for less than 10 seconds and managed to connect each of the boss fight alternatives with an item that was already going to be part of the game in such an effortless way that made it look like this was the plan the entire time.

While it was great to connect some dots, I now had 2 weeks to figure out the layouts of every level, and which order they came in. All I had at the moment was the beginning of two areas - one which you'd enter and discover you couldn't progress without an item, and the other area which you would collect the item from.

I wrote down the rough flow, and how many levels would make up each area. And then I drew out a layout for the first area which was going to be the smallest area. Once I had drawn it, I counted a total of 40 rooms. Extrapolating the numbers to what I had written down for the other areas, this meant there would be around 376 rooms to make across the entire game.

Creating a room was relatively easy. In the game flow post I mentioned that I had a tool where I could create a level by setting some parameters. But I still needed to work out the parameters for each of the 300+ levels, and the tool currently didn't place objects. What I wanted was a way to bulk create levels. If I had an entire floor mapped out on my whiteboard, reduce them down to a few parameters and then put them into the tool and it will create each room.

Instead of jumping straight into modifying the tool, I decided to go and put some of my old Power Rangers toys in the loft instead hoping that I'd think of a way to allow bulk creating while I was organising the toys into boxes. Instead, my brain thought up more problems - doors with keys should have interaction zones only when the player has a key. At the moment interaction zones were based off checkpoints, so I'd need to write some code to set and unset a checkpoint whenever the player picked up or used a key.

Then I decided to mess around with getting some more Steam stuff working. I had achievements unlocking, so looked into cloud saves and using the input API to change the colours on the DualShock and DualSense controllers. Setting up cloud saves was fairly straight forward, but then I remembered that my brother has my PS4 so I'd only be able to test on the DualSense.

What followed was many hours of trying to figure out how to get inputs to register. If I created a build, uploaded it, downloaded it and played it through Steam then it worked fine because Steam wraps around it. But when running a debug build, even though Steam launches and I can trigger parts of the Steam API, the wrapper that Steam uses did not run. And I needed a more permanent fix than "just rely on Steam" for non-Steam PC builds anyway, so I had to look into what MonoGame was actually doing.

Xbox controllers worked because MonoGame registered them as a GamePad. The DualSense did not work because MonoGame registered it (and Joy Cons) as a Joystick. The forums said to simply use the base method that MonoGame called to register controllers, but I was unable to do so as it was not actually exposed. Instead of dicking around trying to install a development build of MonoGame, I added Joystick support to the game.

Then, with a week to go and maybe 2% of the levels done, I made the mistake of committing myself to do the Ludum Dare - a game jam where you have 2 days (or 3 if you do the less intensive one) to make a game from start to finish. And we'll find out why it was a mistake next week.

Popular posts from this blog

Getting Started with the FireRed Decompilation

Phoning It In

Tonight Matthew, I'm Going to Make...