Single Responsibility Principle means a class should only have a single "responsibility." This does not mean one "action" or one "attribute" however.
If I were to write down a list of what a monster in a game might need to do, I may come up with a list such as this one:
- Monsters have attributes such as health and attack power. These attributes may change as the monster takes damage, or perhaps it can pick up a different weapon.
- Monsters have an AI that governs its actions and differentiate dumb little monsters with tougher, smarter monsters.
- Monsters need to be displayed on the screen somehow.
There are multiple responsibilities here. Clearly, "having health" and "having attack power" are not different responsibilities: they are both attributes that define what a monster is and how tough it is compared to other monsters.
The AI might be different responsibility. Perhaps a game has 200 types of monsters, and 10 different AIs. Different types of monsters might be grouped and act similarly: the AI does not need to be recoded each time, it can be shared. How the monster acts might be a responsibility of the AI, not the monster itself! For example, in the Diablo series of games, the Fallen (cowardly little imps) all act pretty much the same despite having slightly different appearances and different toughness.
Displaying a monster on the screen is a great application for an adapter object that has its own single responsibility: figuring out, for a given monster; where it is located, what state it is in (swinging its weapon, running, standing), and generally how it should look on screen.
In this example we might have a core monster object describing the current state of the monster, a pluggable AI that governs its actions, and an adapter object that knows the current visual state of the monster and can produce its graphical state to the graphics subsystem for display on screen.
Note that this analysis does not dig down to the level of individual functions or methods. I analyzed this at a higher level than that: getting bogged down in the nuts and bolts of the implementation is a bad idea when defining object responsibilities. Once those responsibilities are defined and you move on to the low level implementation details, of course you need to write the attributes and functions to support those responsibilities.