The Obsidian Tower has several boss enemies, and I wanted to introduce colored variants of existing bosses to indicate different stat values — stronger versions of the same creature that the player could distinguish at a glance. The plan was straightforward: reuse the existing enemy sprites for the golem and the dragon, and simply change their colors in code. The golem would be tinted red, and the dragon would be tinted blue.
The Problem
I wrote the code to apply the color tints to the sprites and ran the game. The golem appeared in its original color. The dragon appeared in its original color. No red, no blue — just the default sprites as if I hadn't changed anything.
I double-checked the code. The color values were being set correctly. I added debug logging and confirmed that the tint was being applied at the right time. But visually, the enemies stubbornly remained in their original colors.
The Root Cause
The issue turned out to be in how libGDX, the framework we use, handles sprite colors internally. When you create a sprite in libGDX, the framework remembers the original color of that sprite. This becomes a problem when other systems interact with the sprite's color.
In the Obsidian Tower, we have a damage animation system. When an enemy takes a hit, their sprite briefly flashes to indicate damage. After the flash effect completes, the system needs to restore the sprite back to its normal appearance. And here's the catch: the damage animation system was automatically reverting the sprite's color back to its original default color after displaying the hit effect.
So while my code was correctly applying the red or blue tint, the moment the first damage animation played (or in some cases, during initial setup routines that touched the color), the sprite would snap right back to its original color. The tint was being applied and then immediately overwritten.
The Solution
I considered several approaches — overriding the damage animation's color restoration, storing custom colors separately and reapplying them, or modifying the sprite color management in libGDX. But each of these introduced complexity and potential side effects with other systems that relied on the existing color behavior.
In the end, I went with the most reliable solution: I created new spritesheets in GIMP with the desired colors baked directly into the assets. Instead of trying to tint the sprites in code, I produced a red golem spritesheet and a blue dragon spritesheet as separate image files. The game simply loads the appropriate spritesheet for each variant.
This approach is slightly less flexible than runtime tinting — adding a new color variant means creating new art assets rather than just changing a color value in code. But it's completely immune to any color-related side effects from other systems, and the results look exactly as intended every time.