Thursday, November 17, 2016

Devlog Update: The Morphine Western Revenge (#5)

I've been adding quite a bit of polish to the game in the past month. As shown here, I've recently darkened the cave quite a bit, and, in response to playtester feedback, made weapons on the ground shine at regular intervals.

In a Nutshell

Recently, I made the mistake of re-reading my old devlogs, both for this project and others. I've noticed a recurring trend in my writing about my work - the very persistent failure to accurately forecast release dates for my projects. From here on out, I aspire to take a "it's-done-when-it's-done" approach to discussing release dates, no matter how self-assured I am of my progress.

When I last wrote on October 10th, I expected that the game would be completed within a month. I then self-imposed a deadline of November 3rd to complete playtesting for the game, and November 10th to release it. November 10th, as you may be aware, was seven days ago. Seven days and counting, depending on when you read this.

My attempt at setting a reasonable release date was not entirely in vain - playtesting was, in fact, completed by the 5th, and at that point, I imposed a moratorium on adding new features to the game. Any changes that haven't already been proposed and listed as a to-do item aren't going to happen.

The closest thing I've had to an official design document - The Morphine Western Revenge To-Do List, as it currently stands.
Were it not for a deadly cocktail of current national events and personal developments, the game would have been completed on time. I only need three or four free evenings to add the finishing touches. The completion of the game depends on when I am able to come across those evenings.

Since this definitely, absolutely, is going to be the game's final devlog, I wanted to take a little time to have some fun and showcase all of the weird bugs I've produced over the past nine months. It is common for players to experience the unexpected when playing games. Rarely do developers get to be genuinely surprised by their own work, but bugs are one of the ways in which it happens.

Who doesn't like a good blooper reel? I don't. But, in any case,

Regarding Bugs

Bug #1: Slow Rain

Problem: Rain isn't supposed to do that. It isn't supposed to do any of those things. Christ.

Explanation: I don't actually remember specifically what happened here. I think one of the variables* that controlled raindrop movement kept resetting itself each frame? In order to render each raindrop as a "blur," the game has to remember it's previous position in space. That way, each raindrop can be drawn as a line between it's current and previous coordinates. Obviously, in this case, the game is forgetting the previous coordinates of the raindrops. So, instead, it is drawing the lines between the current and original coordinates.

Something awful was also going on with rain acceleration - namely, it wasn't happening? Hell if I remember. You can see the rain working correctly in the following GIFs for reference.

*For you non-coders, you can think of a variable as a container that stores a number or text. For example, the height of a raindrop is numerically stored in a variable I named "height."

Bug #2: Gltichfence

Problem: Fences aren't supposed to do that either. God damn it.

Explanation: This is a fairly common and easily solvable bug for Game Maker projects. Most of the game's graphics are stored as sprites, and each sprite contains a series of individual images. To ease development, I usually like to store all images pertaining to a particular object (like the fence) in a single sprite. However, if you forget to program the object to behave otherwise, it will, by default, cycle through all of the images in its sprite as an animation. So, each piece of fence cycles through all possible fence configurations.

Bug #3: Pseudo-pausing

Problem: The top GIF is actually bug-free, as I will explain in a moment. In the bottom GIF, however, the ejected shotgun shells should not be animated when time freezes, nor should the enemies be moving, nor should they be rendering themselves underneath the rocks.

Explanation: Pausing is one of the few features of a game that affects nearly everything else in it. Everything that moves, is time dependent, or, well, does anything needs its own pause script. It is good practice to start implementing pause-capability from day one. Otherwise, you have to dig through and edit just about every piece of code in your game.

I waited until the end of development to add a pause function.

The only benefit of waiting to add a pause function that, as you work on it, you get to dick around with an incomplete time-control feature. At the very end of adding it, I was left with a player character who was able to freeze the entire world around her at will, which is damn pleasant!

At the time of capturing the first GIF, everything was working as it should. However, things were not operating correctly in the second - at that point, the player character should've been the only thing moving during the pausing. Most motion and graphics changes are handled in-code on a frame-by-frame basis. All you normally have to do is turn off that code when the game is paused, and it should freeze all action for its respective object.

However, sprite animations (as described under Bug #2) and AI movement are not updated on a frame-by-frame basis. Essentially, once an enemy starts moving along a set path, he continues moving along that path until explicitly told not to. A similar thing happens when an animation is triggered (in this case, the spinning of the shotgun shells). However, even though the enemy movement is still active, the code that correctly renders enemies in front of rocks is not. Hence, the enemies are rendered underneath the rock piles.

Bug #4: Shadow Depth

Problem: Everything around the edges of the cave - the wall "tops," rocks, and stalagmites - should be cast in shadow. Instead, only the floor and walls of the cave are shaded with darkness.

Explanation: In order to add to the cave's ambience, I attempted to apply a simple lighting effect to the level. Essentially, an image of a semi-transparent gradient - transitioning from total transparency to opaque darkness - is supposed to be applied right on top of everything else. The end result is that the edges of the screen appear to fade into darkness. This isn't physically realistic, but it does get the idea across: this is a dark cave. Cave is dark.

All graphics in the game are sorted by depth. The floor and walls of the cave are on the lowest level (underneath everything else), the healthbar and crosshair are on the highest level (above everything else), and everything else is sorted in-between.

I forgot to put the shadow gradient above the aforementioned "everything else." This was easily fixed. You can see the correct application of the lighting effect in the first GIF of this post.

It is probably one of the prettiest bugs I've ever produced. I miss it.

Bug #5: Lazy Enemies

Problem: Surprise - it isn't the player invulnerability. See those two dudes in the top left who 1) are standing on top of eachother, and 2) aren't shooting at the player because someone else is blocking their line of sight? When either of those things happen, they're supposed to move around and find a better place from which they can take shots at the player. That's not happening. Artificial intelligence? More like genuine stupidity.

Explanation: The behavior of a mass of enemies to form a semi-circle around the player (so that everyone could shoot her without hurting their comrades) was one of the first things I had successfully implemented in the game. Naturally, I expected this behavior to continue to work as intended. I didn't notice that it had, at some point, stopped working until it became obvious during playtesting.

Normally, enemies will pursue the player character until 1) they have a clear line of sight to her, and, this is important, 2) she is at (not within!) optimal firing distance. Once these criteria are met, the code that causes them to re-arrange themselves in a semi-circle then triggers. At some point, I thought it was a good idea to only have the code trigger when the bad guys were well within optimal firing range of their target. Since most enemies will stop moving towards the player once they reach that firing distance, the probability of the code triggering was near zero. Even when the code did trigger, it deactivated again the instant they move outside of firing range.

I hope you found these glitches visually interesting, if nothing else! A nearly bug-free version of the game will be released soon.