Recently, I promised an article every second Monday giving updates on “Escape From Epstein Island,” the game project I announced about a year ago under the title “Saint Nasim’s day off.” I was initially hesitant to write these articles. Game development is a slow process, and that kind of content was always a fairly large departure from the typical content on this site. However, I did promise, and I just don’t particularly care to chronicle the day to day non-happenings of ZOG. Besides, I regret not writing updates more frequently, if for no other reason than to document the process for my own enjoyment.

CAMPAIGN 

I recently added the campaign. Not the actual campaign, just the programming that is required to have any campaign.

Even in the finished project, the campaign will be just a series of pre-made encounters called “scenarios,” glued together through simple cutscenes. The scenarios are waves of enemies thrown at the player, or occasionally a boss battle. I decided to build the crude tools required to create the scenarios inside of the project itself.

The cutscenes in the final project will be mostly text and image, with the occasional cheaply made full motion video. For now, they’re simply text blurbs that serve as stand ins until the real cutscenes are written.

Kill all the enemies in the scenario, and you’ll be rewarded with a victory screen that currently tells you that you died, because it’s the same screen that pops up when you actually die, and I forgot to rewrite the text. Details like this are not a high priority for me right now.

There are a number of problems with the simple victory condition of killing all the enemies. The game works best when its throwing tons of enemies at the player, so when you’re just hunting down stragglers after killing 95% of the enemies it’s somewhat anti-climactic. I have a number of candidate solutions to the problem, such as automated turrets that pop up after the last wave, FBI agents that come with increasing numbers the longer the player dawdles, or just a straight up time limit, but I’ll write about that more when I actually get around to solving that problem. There’s little point in more work on the campaign when the basics of gameplay still need a ton of work.

Such as:

PATHFINDING

There are some maps in EEI that don’t have any obstacles. In that case, pathfinding is dead simple. The NPC simply moves in a straight line to their intended destination. This is also true for any situation where there are no obstacles in the direct line between the current position, and the goal position. ove straight from X -> O.

Above we see X mark the current position for the NPC, and O marks the destination. Since there is nothing in the way, we move directly from X -> O. On the other hand, if there is some obstacle, shown by the grey tiles, then we need to calculate a path.

The old pathfinding system I created was quite simple. As the level is built with a 16×16 grid, I connected all traversable tiles (orange) with their neighbours, as long as said neighbours were also traversable. A tile could therefore have eight total connections. Up, down, left, right, and all four diagonals. I then use A* to calculate the path. The final product looks something like this.

Unfortunately, there are three obvious issues with this system. The first is that the path suffers from something that reminds me of the jagged line problem in computer graphics. Because we need to navigate to the center of each tile in order to continue, our path becomes very odd. Sort of like this.

This problem could be ameliorated by going to a much higher resolution grid, but that is far more computationally demanding, and requires more time spent on my end building the maps in the first place, for little gain. It also doesn’t truly solve the problem, which is a silly byproduct of a very sub-optimal pathing system. We can do better, and with a far more performant algorithm, which is important since I was already getting performance slowdowns when dozens of NPCs are active, and there is no reason to tolerate something like that in a simple 2D game. 

What the path should look like.

The game is 2D, there are no moving obstacles, and all the pillars, or other obstructions, are squares. All calculated paths should hug the shoulders of the pillars, so the only pathfinding nodes that we need to create are the ones diagonal to the edges of the obstructions. Like this.

The only connections those nodes need to have is to the other edge nodes that they can see. 

An annoying bug is visible in this image.

This simple solution holds for any pattern of squares.

Even an irregular pattern. While the below image looks messy, it still has far fewer connections, and thus much higher performance, than the old pathfinding system, while giving better results. 

 

I mentioned a bug visible in one of the above images. That took me a long while to fix, because it ended up being related to the implementation of Unity’s raycasting API. The bitmask needed for collision checking was accidentally passed in as the maximum distance to cast, which gave some extremely odd results, such as the incorrect mess you see below.

But in the end it all got worked out, and I have a pathfinding system that is somewhere around two orders of magnitude faster, and gives better results. There are plenty of optimizations I could use to lower the pathfinding cost, such as pruning redundant connections along the same line, or putting various NPCs in a queue and only updating their paths every ten frames or so. I don’t see it being an issue in the forseeable future, so that’s extremely low priority work. If I do work on that subject, I’ll write about it later.

*The third problem with the old system takes longer to explain, and was a result of the characters being forced to navigate to the center of tiles.

 

 

ARCADE

The main mode that I’ve been working on is the arcade mode. In this mode, the player is trying to survive as long as possible, holding out against increasingly powerful waves of enemies. Each new wave spawns after twenty seconds, so there will come a point where the player becomes overwhelmed, no matter how skilled they are. When they die, their high score is preserved, and displayed on the arcade menu.

There are a few issues with such a design. First of all, if the initial waves are quite easy, then we have a situation where the player may have cleared all the enemies, and is just waiting for the next wave to spawn.

Eventually, the next wave spawns, harder but still pretty easy. The player clears that, then waits around for the next wave to spawn, and so forth. 

There will be a fairly brief period of time when they are actually tested, since the amount of enemies in play are roughly level to what they can deal with. Then we run into the other problem, where the enemies spawn far too quickly for the player to keep up. That last problem isn’t so bad, but we’d ideally like to have the challenge match the player’s skill for longer.

We could tune the starting wave strength, but that’s a solution that must be individualized for each player’s individual skill. Instead, I decided to just spawn the next two waves if the first wave gets cleared early. If the player clears the wave in half the time allotted, we spawn in the next three waves. 

The original system had a scoring system that was entirely dependent on time spent alive. That was obviously placeholder, although it feels good to see the timer clicking up as you play, so I decided to give the player one additional point for every second spent alive. They get 100 points for every enemy they kill, 500 points for an early clear, and 1500 points for a very early clear. All of this is, again, obviously placeholder, but it’s good enough for now because it incentivizes the aggressive play that we want right from the start, while also slowing down the spawning once the player begins to get overwhelmed.

I haven’t bothered working on the UI necessary to convey this to the player. Ideally, we’d want something like a flashing “+1500 fast wave clear,” coupled with sound effects, and similar for each enemy killed. For now it’s all behind the scenes, because again, that’s not of very high importance right now. As it stands, arcade mode looks like this.

CONCLUSION

I’ve currently borked the build, so I’m working on fixing that. Once I have that done, I will be releasing this version of the game into the public Telegram group, which you can find here. The idea is that you download the build, then spend five minutes playing it and give feedback. If you’re at all interested in doing free playtesting of a game that is nowhere near completion, please join the group.

You may also like

Leave a reply

Your email address will not be published. Required fields are marked *

More in GDev