Programmers like to program. At least they should. And liking to program means liking cool data structures and systems.
In my current project, I decided that the enemies and player characters should flash white when hit, indicating both that they have been damaged and that they are invulnerable while the flashing lasts. Classic.
To do this I wrote a component that detects damage sources, keeps track of entity hit points, causes the entity to flash for a set amount of time, and sets an invulnerability flag. Besides a few additional settings to hook it all up, all I had to do was attach this modular component to an entity and I’d be good to go.
Of course, I made it possible to configure the hit points for each entity type, since not everything will be able to take the same amount of damage. I also started out thinking I’d make other things configurable. Maybe the speed of the flashing? The length of the invulnerability?
From a pure programmer’s perspective, this made sense. Modularity is cool. Configurability is also cool. More cool stuff is better than less cool stuff, because more cool.
Then I started thinking as a designer, which means thinking from the players’ perspective. I want the flashing to mean something to them. I want it to clearly indicate what is happening, and I want it to do that through experience. Flashing when hit is eye catching and dramatic, and only lasts a certain amount of time. I don’t think it will be hard for them to figure out that it means taking damage and invulnerability.
But what if something flashes faster, or slower? What does that mean? How will I tell the player what it means? Will they be able to keep track of it, or even really notice the difference? And what about flashing for longer or shorter periods of time? Do I want them to have to memorize an arbitrary number of different periods of invulnerability?
In the end I decided this was all extra cognitive load on the player that wasn’t worth it. Everything flashes at the same rate, for the same length of time, the player character and the enemies. The flashing is a single symbol that communicates one thing.
And this meant doing less programming.
Another example is moving platforms (which it turns out are a tricky problem in more ways than one). If a platform catches something between itself and another solid object, what happens? Well, the platform was pushing the player character into the ground. Then he would pop out on top of it. Also, if the platform caught the player against the ceiling, he would get pushed outside the level.
Different games handle this differently. Mega Man gets straight up killed if he gets pinched even a little bit. I didn’t want to do that, but what was the solution? As I was thinking of other possibilities it occured to me: What if I just don’t let platforms get close to walls?
Would that really restrict the design space in any meaningful way? Would the player ever notice? Currently, I don’t think so. Maybe I’ll rethink it if something comes up, but careful positioning to avoid the problem seems like a handy solution that avoids what could be a lot of extra code for little to no benefit in terms of gameplay.
It would be an engaging problem as a programmer, but I’m not just programming, I’m making a game. So the question isn’t whether I can implement a feature or solve a problem. The question is whether I should, and the goals of my design and the experience of the player should determine that.