Switch Hitter Development Log

Behold as I pretend that I am a game developer.

Sprint #6: "Iteration on vacation."

July 8th, 2018

This week was another short one as I went on a quasi-vacation out to Eastern Washington for Independence Day. Knowing that it'd be tough to cobble together much more than a few hours of effort in the face of drinking a beer while floating on a lake, I wanted to be sure to schedule mostly small things for this sprint. The stories were almost exclusively non-user-facing things that aren't particularly interesting to write about (e.g. "Ensue's repository should be hosted on the RDG server" and "Storybook should ignore case when filtering by tag"). There were a few highlights I'll let you in on, though.

Maybe they should be called "people movers"?

Although I haven't yet made a level that uses them, I was able to implement horizontal "elevators" that get activated whenever the hero lands on them. The vertical analog of this has existed for some time but a horizontal version had yet to be developed. Here's a quick look at our hero using a "righter" (because it moves to the right, of course) to clear a gap that he otherwise wouldn't be able to cross.

If you look closely, you may notice a little bit of a delay in between the moment that the hero hits the righter and the moment that the righter starts moving (and again in between the hero getting off the platform and it starting to return to its original position). An astute reader will note that there's no such delay with the vertical elevators (which are much more tastefully named "ascenders" and "descenders"). There's actually a programming reason for it.

The hero is constantly being asked if he's "riding" a platform. The basic implementation of physics in Ensue needs to know about whether the hero is riding a platform so it can correctly update his position, even absent player input. More plainly, as a player, when I've got the hero standing on a moving platform and I'm not pressing any buttons, the hero should be anchored to that platform, moving along with it. Thus, one of the things that needs to exist is a definition of what it means for the hero to be riding a platform. In Ensue's case, it's all just, "Are any of the y-coordinates of the hero's feet adjacent to a platform?"

Elevators are also asking the hero if he's riding them because their cycles are affected by it. If the hero is riding an elevator, it needs to go into its movement cycle; if he's not, it needs to go into its return cycle. A strange case arises when the hero is trying to walk off a platform. When it's a vertical platform we're talking about, that platform's x-coordinate never changes, so the game is easily able to allow the hero to dismount. When it's a horizontal platform, though, you can get things into a state that's tough for the game to distinguish between the hero's movement and the platform's. Here's what a situation could look like absent that delay.

Based on the player's input, the game updates the hero's movement, which takes him off the platform, which triggers the platform's return cycle, which immediately places a portion of the platform back under the hero, which means that the game think's he's once again riding it, which triggers the platform's activation cycle. It's not exactly an infinite loop because the hero can eventually get to a speed that's faster than the (default) speed at which a platform travels and then the expected behavior happens. It is, however, pretty low-quality looking and needed to be handled somehow.

This is where I admit to you that I really didn't give this a deep look to see if maybe I was just updating things in the wrong order or search for a super-elegant solution that would satisfy even the most academic of programmers. No, I decided that just giving a platform a cool-down would do the trick. Indeed, whenever the platform thinks the hero is no longer riding it, it counts to 15 (in frames) before it commits to entering its return cycle. (For symmetry, I introduced the same delay on the front-end when the hero first mounts the platform.) In practice, that's more than enough time for the game to safely end up doing the right thing from the player's perspective. There's nothing special about the number 15, it's just what seemed sort of reasonable to my eye when I was playing with numbers. Just at a glance, it seems like 3 or 4 frames is the shortest cool-down window at which this issue is rarely reproduced.

Anyway, this cousin of a hackfix is interesting because I kind of like the idea that you can activate a platform and have some window of time to dismount it before it returns to its original state. Imagine riding a platform a little ways over on the screen, jumping off of it, making it stop dead, and having a few seconds to go get some collectible before the platform runs away and you end up in a bad situation.

It's like a combination of an escort mission and an autoscroller! Great!

A semblance of a build system

I'll try not to spend too much time on this devops stuff today but Ensue now sort of has a build system and I'd like to tell you why. Ensue is written entirely in JavaScript and is delivered via the web. That means that in the HTML page that I ask you to go to in order to play the prototype, I have to specifically include lines like <script src="classes/actors/enemies/hopper.js"></script> so that, in this case, the Hopper enemy can actually be used. Each one of those <script> lines means that your browser ends up making another network request to the RDG server so it can retrieve the corresponding file. If any one of those requests fails, your browser will probably do a bad job of telling you and it'll just seem like Ensue is broken garbage. Although web requests just about never fail when you're just asking your own computer for them (i.e. when you're the developer working on the game), they have a much spottier history in the wild. Over time, the number of files that I've had in the Ensue project has grown and, at some point, it's just stupid to be making a prospective player's web browser make thirty requests in addition to the one it's already making simply by accessing the prototype.

As such, I've introduced a basic system that pre-processes all of the JavaScript code into one file and even compresses it a little so that, now, when you access the prototype, you only need to make one additional request to fetch all of the game's code (images and level data are another story, though). This was all inspired from actually having this happen to someone I was getting feedback from: loading classes/hitbox.js failed, which broke everything, even though all of the other files loaded fine. That type of thing just can't happen right now in this period of "I'm going to look at your game for twenty seconds and decide whether to play it or not so it at least better work".

It's not good if it soft-locks

That kind of leads in to this. Reading peoples' comments and talking with those who have played Ensue so far, it's become pretty clear that some players are accidentally hitting the "soft reset" button at bad times--usually when the hero has fallen off screen but isn't quite dead yet--soft-locking the game and potentially replacing some more important feedback with "got into a state where I couldn't do anything; quit". During this heavy feedback phase, I just can't let that type of thing happen, so I've decided to disable the soft reset functionality altogether--it's more of a dev feature anyway--and I've documented "hard reset" as just "reset" in the controls. Hopefully, this is a reasonable fix for what I'm sure has made Ensue feel even buggier than it is.

Does anybody besides me still use an RSS reader?

If you love reading the Ensue Development Log but hate having to remember to check it for updates and also are still kind of upset that Google Reader got the axe five years ago (!), then you'll probably welcome with open arms the news that I've implemented an RSS feed for all of this stuff. One downside at this exact moment is that you only get the first paragraph in the feed, so you'll still have to click through. This is not because I'm religiously tracking engagement or whatever but rather because RSS doesn't automatically support using HTML (or something), so I can't just throw all the pregenerated markup into the feed. It's not exactly high priority to figure that out but, hey, maybe I'll get annoyed by it, too. I still use Feedly, after all.

You can totally trust me with your data now

Finally, I've enabled HTTPS on raindelaygames.com and all of its subsidiaries. This was almost trivially easy to do and most of the time I spent on it was allocated towards just understanding what was going to happen. I used Let's Encrypt and Certbot and it's actually very impressive how well it seems to have worked. Google is getting pretty serious about shaming non-HTTPS sites within Chrome so it seemed prudent to be on the right side of history with that. Also, it was hilariously easy. Did I mention that?

Closing thoughts

As it always is, adding a new toy to my toybox--in this case, lefters and righters--is very fun because it means I get to think about and then actually create new types of gameplay challenges within Ensue. Platforms, specifically, have always tickled my fancy. I'm definitely one of those people who thought the best parts of Super Mario Sunshine were all of the pure platforming secret levels, even though I love the game overall. I think Yoshi's Island is a masterpiece but I also think "5-7: Shifting Platforms Ahead" is my favorite level, owing to all of the movement coordination and anticipation it demands from the player.

Next sprint

This week, I'm going to try to flesh out a level or two that more closely represent my vision for what Ensue's worlds will feel like, along with going back to the toybox and playing around with a few new concepts. It's obvious that people aren't getting the balls/strikes/outs concept (because I just about never use it nor do I explain it) and I'd like for that to change. Hopefully, a week from now, I'll have at least one traditional-feeling level that helps advance Ensue out of the rage-game genre (or, alternatively, prove that that's where it best exists; I'd take that).