State diagrams are indeed an effective way to model the event-driven behavior of a single object.
Relative time event
The relative time interval after(3 minutes)
requires the player to not move. Whenever the player moves, for example making a step, the interval is reset.
The easiest way to model this is a self-transition for the move events, and a self-transition for the timing event. This way, every move re-enters the state and the timer starts anew.
Important remark: the after(delay)
does specify a time related event. It does not impose any way to implement such an event. In other words, you are not forced to actively (and inefficiently) monitor the passing time, and could very well use some efficient timer event of your OS.
Repetitive time event
The "every 15 minutes" is also a relative time event, that could be expressed with after(15 minutes)
. It's just that its count-down cannot be disturbed by any other state transition.
One way of modeling this, would indeed be to have a separate very simple state diagram for an object that would send the periodic events, e.g. Tick15
to the Player object. In your state machine, you would then react to such a Tick15
event with the appropriate transition. The inconvenience is that you loose the oversight (and have a more complex model with more objects).
A typical alternative is to keep the logic in your single object and use a composite state with nested orthogonal state machines. This allows separation of concerns: One orthogonal region would model the lifecycle around an Alive
state, and would only capture the repetitive time events. Another orthogonal region would be for tracking movement-related events around an Idle
state.
Other tips
Instead of going directly from Alive
to the pseudo-end-state, you may prefer to add a state Dead
that could care for things such as showing some animation of the player's end, showing the game score, or whatever. This state would then fire a transition to the pseudo-end-state upon its completion (outgoing arrow without any event).
The when(condition)
expresses a change event if the condition is true. So you'd typically use it to detect the end of the game: when(energy<=0)
. But you would not use it for when(step)
since it's not about a boolean expression. If step
is an event, just write step
.
Wrap-up
The diagram could look like:

Plantuml url
(At any given time, each orthogonal region has one active state, so Alive
and Idle
are active at the same time, each having independent state transitions, until a transition of the enclosing composite state is fired)
Alive
state, but that other things are happening. Perhaps a timing or activity diagram is more suited to what you want to model?