Switch Hitter Development Log

Behold as I pretend that I am a game developer.

Sprint #7: "I have no idea what I'm doing."

July 15th, 2018

No vacation, quasi or otherwise, for me this week, which meant I had a no-excuses amount of time to dedicate towards both basic level design and a mechanic I've been wanting to implement for a little while now. I prioritized a few miscellaneous bugs and tasks for good measure--okay, actually to ensure my sanity during the trying times of level design.

Existential crises and level design

It wasn't like some big secret to me that designing a level in a 2D platformer is a difficult thing to do. It wasn't unknown that it taps into a brand of creativity far more akin to making artwork and composing music than manipulating Objects. I fundamentally know that things don't need to be perfect right now. Yet, for whatever reason, I kind of forgot all of that over the past couple of months. I'll admit that, in working on these levels this week, I had a little bout with imposter syndrome, as if the process revealed to me that I'm not actually a video game developer.

I don't want to say that any kind of level design is "easy", just to get that out there right now. For me, though, it's much more manageable to design levels of the one-screen/one-gimmick ilk that anybody who's played Ensue so far has been exposed to. Those levels are far more focused, only asking the player to do one thing or prove that they know how to execute one mechanic or show that they can choreograph and execute one maybe-elaborate dance. Unfortunately for my instincts, those types of levels just aren't what I've generally envisioned for Ensue's future. They work great as proofs-of-concept for me but I'm probably not far away from designating them as "for internal use only".

See, the main inspiration for Ensue is Yoshi's Island, whose level design represented a major departure from the types of levels we'd seen to that point in the Mario series. Its levels were big, if not sprawling, intended to be explored and experimented on, not rushed through and completed as precisely as possible. Although I accept that what worked for that game may not be what ends up working best for Ensue, I still want to at least try making some levels that evoke my main influence. For me, this ended being a brutal cycle of: 1) having no clue what boxes to put where; 2) eventually putting some boxes in places; 3) hating that maybe the placement of said boxes wasn't perfect; 4) getting mad at myself for not having had a clearer vision of what my levels should look like; 5) working on something else; and 6) reluctantly returning to step 1 out of a sense of responsibility that, yes, the levels are still important right now.

I got to the point where I actually implemented the Yoshi's Island map for level 1-1 within the Ensue level editor (if you get in touch with me and ask, I'll tell you how to play through it), just to get a little insight into that universe's level layout. What I learned--and sort of already knew--is that the environments in that game feel far more organic than I've considered Ensue's to be. There are a lot of imperfections and bumps, as opposed to flat, runway-like surfaces. Just to call out a specific issue with that type of layout, I worry that, early on, having too many small jumps in my levels will frustrate the player because they'll be triple jumping too often and not necessarily feeling like they've been taught that mechanic.

Anyway, despite the digression, my main goal for this sprint was to come up with a couple of levels that could vaguely be considered the first levels in an Ensue that actively tries to take after its Yoshi's Island influence. I specifically wanted to have them teach the player about a handful of the basic concepts, including balls and strikes, which I've mostly put off introducing until now.

Those levels have now been hooked up within the Ensue prototype. It was an interesting exercise in making things complicated enough that the player could accidentally learn stuff while also making things simple enough that the player doesn't need to explicitly be taught anything in order to clear them. I'll likely start more actively asking for feedback on them next week and I already have a few ideas for how I could iterate. Oh, and there are also a couple of new one-screen levels because I was able to get a new mechanic implemented.

Even switches get to switch it up

A couple of weeks ago, I mentioned that I'd created a basic switch mechanic: whenever the hero was standing within a switch region, something elsewhere on the screen happened. Well, now, enemies are also able to trigger switches.

Implementation-wise, this was pretty trivial. All I really had to do was find the code where the game determines whether the hero has intersected a switch or not and have it do the same for any enemies within the level. This isn't optimal or anything but it works. A more optimal solution might require the level data to declare which enemies (or entities!) are even able to trigger switches, giving a hint to the game engine that "you only need to be concerned with testing these things, not all things". To that end, though, this mechanic has me thinking about the idea that, just for instance, certain-colored enemies could only trigger certain-colored switches. Taking this to its logical conclusion, maybe everything should be allowed to observe everything and be notified whenever its state changes. For now, though, I'm happy to add a dozen or two more if statements to every frame and call it fine.

Separately, when I finally saw this thing in action, it was honestly kind of a relief. For a long time, I've been worrying that the bat mechanic has no real use so long as the glove mechanic exists; as shown in that video, I now have at least one situation I can point to where you must use the bat. I've also been thinking that the Ensue world just isn't dynamic enough; this adds a bit of that missing dynamicism. I've got a bunch of ideas for where we can go from here, to the point where I'm scared of overdoing it (but, at least in that case, I also have a super-secret idea for what I could call the game).

Miscellaneous bugs

So, just real quick, I fixed an issue caused by the move to the build system (discussed last week) that rendered the "Reconfigure Gamepad" button completely nonfuctional. This was a dumb front-end bug that took less than a second to fix.

The far more substantive bug I fixed this week was introduced by the new wallJumpable state developed during Sprint #5. Very literally, in order to determine whether a hero bounces off an enemy or gets hit by it, the game asks: 1) is the hero intersecting an enemy with his feet?; 2) is the hero's y state machine in the falling state? If both answers are "yup", the hero wins the encounter. (I have my reasons for believing this is a poor implementation but, you know, I'll get there when I get there.) It became apparent pretty quickly that wallJumpable is, for bouncing-off-enemies purposes, an equivalent state to falling because it sure did suck whenever this happened:

This was another trivial-to-fix issue (just add wallJumpable to the list of states for magic question #2) but it's made a huge difference. Especially given the introduction levels I was working on this week, in which a new player could very easily come across this situation and get confused and/or frustrated by it, it was an important thing to take care of.

You should get feedback, too

Finally, somewhat necessitated by the new "traditional-style" levels, I made an animation for the checkpoints that verifies to the player that they did, in fact, hit them. I was originally only supposed to make a new sprite, not a full animation, but reticence to go back to level design is a powerful force.

This actually required more code than a person who makes reasonable assumptions about sane ways in which an animation system might be implemented may think because, unfortunately, my animation system is just a total mess. I think I could spend a full week refactoring it (and, uh, I probably should do that) and still have complaints. In any case, the main feature added was the ability to make a once-through animation; previously, all animations had been assumed to be looped, meaning they'd repeat indefinitely while active. This feature will certainly be used in other ways and, in a separate sense, the more frustrated I get with the animation system, the more ideas I'll accumulate along with the urgency to implement them. Honestly, I feel like "being frustrated with something and having the agency and motivation to fix it" is the holy grail of the active software developer.

Closing thoughts

So, despite feeling like a complete fraud for a portion of the week, I think the sprint actually went well! Once I got into a little bit of a rhythm, I enjoyed making the two "full" levels (that, again, you can and should go take for a test drive) and I emerged a bit more optimistic about the whole balls and strikes mechanic, as well as the bat. I assume that at least some of this stuff is eventually going to be ripped out for being "a little much" but, for now, I'm very interested in figuring out different ways to use all of the mechanics I've got available. There are only a couple more on my list that I'd like to have.

Next sprint

In fact, I'm going to try to get the rest of that mechanics-of-interest wishlist implemented this week and, hopefully, get a third "traditional" level done so I can feel like I have something substantive to submit to Feedback Friday. I'll also likely spend a little time on getting the prototype page to exist within the RDG.com shell but, man, that stuff is so much less fun to work on.