Switch Hitter Development Log

Behold as I pretend that I am a game developer.

Sprint #13: "The kitchen sink."

October 7th, 2018

Well, last week, I said that this would be a free-form sprint touching all kinds of systems. I'd introduce a new mechanic here, fix a bug there, maybe even create some new visuals. I did all that and more and, frankly, I don't even know where to start. If you like screenshots and videos, this is the devlog post for you.

A different kind of bug

Through watching some unthinkably large number of hours of televised sporting events, I've been made aware that the main graphic you see on the screen these days--the thing that tells you the score, the baserunning situation, the count, etc.--is called the "score bug". Until this week, I've had a very bare bones version of a score bug that tries to keep you updated on your balls, strikes, and outs.

Generally speaking, though, people don't seem to actually notice it. That's fine because it's so far from my bigger vision for it, I had an excuse to actually work on some new art for it this week. In my mind, the final score bug will be very reminiscent of an actual ballpark scoreboard, sporting a look that reminds you of hundreds or thousands of individual light-bulbs creating simple but effective imagery. After a little time spent working on it this sprint, here's what I've come up with, in four different states.

I really like how this came out and, in the longer term, I very much want to add animation to it. I could even see the score bug becoming almost its own character within the game that offers help when you need it or just adds a cool flourish to your actions. I'm very excited to go deeper and really see what I can do with this thing.

Back to basics

Even though I'm to the point where I've spent twelve months of effort on this game, the fundamental rules of my platforming universe are still being tweaked. One thing I released but didn't mention in the devlog post from last sprint was that you now have to hit every checkpoint in a level before being allowed to exit it. I sort of think of this as having to touch all the bases before you're allowed to touch home, though I don't actually require that you touch them in a particular order. Anyway, for the levels that exist right now, it doesn't make a huge difference because the checkpoints are laid out in a pretty linear fashion. I look forward to experimenting with this a little, though, and making some levels that afford you the ability to collect checkpoints in whatever order you like.

The biggest fundamental change I made, though, was something I've been kicking around a lot lately: the idea that you could convert an already-collected ball into a projectile. Think of it as ammunition but, to use the ammunition, you cost yourself a ball that you've collected and that could presumbly go towards nullifying one or two strikes later on. It's a trade-off that's very interesting to me and I spent a good amount of time implementing it this week.

As you can see, when the hero collects the ball, their count goes to 1-0 but, when the hero elects to use the ball as projectile, it not only decreases the count back to 0-0, it actually manifests as a strike. This introduces a good trade-off for being able to have ammunition along for the ride. If you swing and miss at the newly introduced strike, you'll end up collecting it, hugely affecting your count. This took the better part of a day to implement decently and, in many ways, the toughest thing was figuring out how on Earth the player should control this. I landed on: whenever the player holds up and presses the glove button while they have at least a one-ball count, that ball will be converted into a strike and peppered right in front of the hero. I think it actually works pretty well.

Watch out for the rebound

At some point, I started thinking the projectile system might be a little too generous to the player. Specifically, there didn't really seem to be any downside to just swinging your bat as often as possible to try to avoid having to actually confront an enemy head-on. Well, that changed quite a bit when I made a very simple modification to the bat mechanic: enemies can now hit you as they rebound off of walls.

On the other hand, you can also bounce off of rebounding enemies. This is a fairly precise maneuver, very much like a shell jump in Super Mario World and I don't think I would ever hide a checkpoint behind this mechanic. I could, however, envision hiding something optional behind it.

Special modifications

It's funny how just small tweaks can make a huge difference. This sprint, I've been experimenting a lot with modifiers to standard objects and processes. Even though these three things I'll talk about aren't strictly related, I view them as all part of the same "take a basic system and play with it" group of things I was goofing around with.

Firstly, I've introduced several variations of balls and strikes, along with two special collectibles that actually change the number of balls and strikes you're allowed to collect before your count is reset or you make an out, respectively. Keep an eye on how the scoreboard changes as the hero collects the MinusBall and PlusStrike.

I'm also equipped now to have one collectible item give you different numbers of balls or strikes. In some cases, this just replaces, say, a cluster of four individual balls. In others, though, I can more effectively charge the player two strikes for making a mistake without having to clumsily have two distinct objects on the screen.

Another type of modifier I messed around with was a simple enemy trait modifier. Put simply, I wanted to be able to create some enemies that you could never actually bounce off with a standard jump attack, as well as some enemies that wouldn't get damaged whenever you executed a standard jump attack. I named these traits "unbounceable" and "undamageable", respectively, and here are a couple of videos showing them in action. These enemies are otherwise just a normal Sitter (despite the very cool-looking horns, I know) and a normal Pacer.

Finally, I spent more time than I'd probably like to admit tweaking some magic numbers and controls related to the launch angle that results when you hit something with your bat. The main thing I really wanted to accomplish with this was to allow a projectile to contact pretty much anything on the same vertical parallel with it in close range. That is to say, if you have two enemies close to each other and you swing the bat to hit one, I wanted its natural path to hit the other.

This actually needed a bit more work than you might think. My default gravitational acceleration is far too strong to allow such a shallow launch angle to do much, so I have to temporarily nullify it and build it back up gradually. I actually consider myself kind of lucky that one of my first two or three guesses at how best to implement it ended up feeling pretty good to me.

I didn't stop there, though. I also wanted to be able to launch something at a much sharper angle while ideally preserving at least as many angles as I already had in the game. This is where the L button on the SNES controller (Q on the keyboard) came in. Now, if you're holding that button in addition to either up or down when you contact something with a bat, you'll launch it at a sharper angle up, if you're holding up, or down, if you're holding down. Here's an example of a big lob.

New faces, new names

The experimentation with enemies didn't stop at simple traits. They haven't yet shown up in a level but I created four completely new enemies. The first three all use a notion of proximity to the hero in order to dictate their behavior and the fourth actually integrates with the projectile system.

First up, we have the Chaser. This simple variation of a Walker plays dead when you're at a distance, tries to slowly walk away from you as you get closer, and pursues you at double speed when you're not looking.

Next, the Napper, who acts similarly but never retreats.

Then, we've got the Diver, who patrols a certain territory from the air. If you enter a Diver's space, it'll dive at you--with a little extra logic to estimate your position once it reaches the ground--at a pretty quick speed.

Finally, and, unfortunately, with no artwork yet, we have the Comebacker, who will automatically relaunch anything that's been launched at it. I've actually rigged up a little level where you must make use of a Comebacker to progress.

Breaking it down

Another new mechanic that got implemented this sprint was one I've had my eye on for pretty much all summer: breakable terrain. In this particular example, this terrain acts like a normal piece of solid ground except that it will disappear whenever it encounters either your bat or an enemy that's been launched at it. There are some really nasty things that you can do with this concept that combine both platforming expertise and puzzle solving. I'm sure those will show up in the main game in some form.

Visual reinforcement

Finally, I made a few visual changes that all make a huge difference. The first is that I've made switches change color once they're activated. The second is that platforms now also change color if transition from a deactivated state to an activated one. Both of these combine to really help the player realize that the two things are connected. Lastly, I've added a faint line that shows the path that a platform will travel. This does wonders for helping the player know when the right time to jump is, especially in what currently exists as 1-2 over in the prototype.

Closing thoughts

Whew! I got a lot of stuff done these past two weeks. Early on, I actually made a note to myself that I thought I was putting way too much in the queue than I could possibly accomplish in two weeks' time but, on the whole, I actually did get through it. It was a really fun period of experimentation and, I think, very good iteration on visuals and mechanics. By the way, I've decided to just go ahead and merge it all in so everything I've talked about in this post--to the extent that it was already in the existing levels--can be played around with in the prototype.

Next sprint

Sprint #14 will certainly not have as much media associated with it. I'm going to be focusing specifically on refactorization and optimization. Now that I've had some good time creating many different objects and entities within my codebase, I feel like I have a good idea of redundancies I'd like to get rid of. I've also been noticing somewhat lower framerates lately and I'd like to go take a good look at getting things nice and smooth. It should be a fun and/or mind-numbing two weeks.