Posted On: 2021-08-09
As part of my continuing work on the new flight system, I've recently worked through what happens when the player character is injured mid-flight. Going into it, I had thought it was a simple problem with an interesting, but simple, solution, but once I started implementing it I found I'd overestimated my design. As such, I thought it would be of general interest: a short story about how being both designer and programmer can sometimes create problems.
From the moment I first thought about mid-flight injury, I immediately thought that after colliding with a hazard, the character should bounce off, pause in mid-air (to allow the player ample time to decide how to proceed), and then either resume flight (if desired) or cancel flight (if desired). Additionally, I reasoned that, if the player simply refused to make a choice, the opportunity to resume flight should eventually time out and the flight cancel by default. I was particularly committed to this design as I knew flight would involve moving both quickly and predictably, and thus players would need additional time to react when that is disrupted.
Once I began implementing it, I immediately ran into issues due to the lack of clarity. "Bounce off" is a good "feel" word, but it's not technically detailed enough to turn into an actual implementation. How should the "bounce" resolve? Certainly not using actual physics forces: the rest of the game's physics are deliberately unrealistic, so it would feel off to suddenly use a realistic simulation. Reversing the current trajectory is an option, but that would look weird if it were a glancing blow, or the hazard hit the character (instead of the other way around.) For now, I'm using "bounce off" to mean "move in the opposite direction relative to the character's and hazards' respective centers", but I fully expect I'll need to refine this further*.
The second issue I ran into was quite a bit more troublesome: how does the player express their intent to continue flying? Obviously I won't be making a dedicated "continue flying" button, but since the start flight button is currently a toggle*, I can't use that. Picking one of the movement buttons probably wouldn't work either, as players may be pressing the button too late while trying to avoid the hazard. None of the other buttons seem particularly related to the desired behavior either, so there don't seem to be any good options for how to express the intent.
As an added wrinkle on top of this, in the case of flying into a static hazard, simply resuming will cause them to fly into it again. Thus, to avoid the hazard, a player must now hit both the "resume" button and also steer at the same time. As mentioned previously, trying to steer shouldn't be enough to express the intent to resume, so something had to change in the design.
Fortunately, as I iterated on various attempts, I happened upon something that seemed to work out alright: simply resuming flight by default. When I tried it in-game, "bounce off, pause, resume" didn't feel nearly as bad as I expected - in fact, it actually felt better than my original "bounce off, pause, fall". Although I initially resisted this (designer ego getting in the way), as the other issues started to pile up, I began to consider it more seriously. Along with feeling better, resuming by default means the player can focus on steering, and the existing toggle flight button is readily available should the player wish to stop doing so. Unfortunately, this does create the issue that a distracted/absent player might repeatedly slam into a hazard if they don't do anything at all, but I doubt this is the only scenario where leaving the game unattended causes problems.
Hopefully this window into designing how flight injuries work was interesting. It's still got more room for improvement (particularly how the "bounce off" is resolved), but I think it wound up working out, despite the problematically vague design. While this situation is not exactly unique to being a solo developer (vague designs are a common complaint among programmers), being both designer and programmer means that such issues can't be caught during the communication between the two roles.