Both method A and B are feasible.
While an event system is the best way to decouple components, keep in mind that such systems tend to create a lot of overhead. The event handling and dispatching itself creates overhead and you might end up duplicating data in multiple layers of your architecture which takes additional memory and might cause a few bugs due to the additional complexity involved.
A much more efficient way is to simply have the game mechanics directly expose any state required by the rendering system, so the rendering system can operate on the original data. But this creates a tighter coupling between the rendering enginesystem and the game stategamestate.
An in-between solution could be to create another layer between the game mechanicsgamestate and the rendering system: the animation system. This system knows the state of the game mechanics and uses them to determine which spriteID to use for each object in the game on each frame. For example, when mario.hasStar == true it alternates between spriteIDs from the original spritesheet and spriteIDs from the alternative colors spritesheet each frame.
The rendering system then reads the spriteID the animation system came up with, determines the corresponding resource, and renders it.
As David Wheeler once said:
All problems in computer science can be solved by another level of indirection... Except for the problem of too many layers of indirection.