Last updated on
hotpotato
Example
This example demonstrates how to use the ClockDrivenStateMachine
provided by the library. It enables you to simulate a continuous, time-based game instead of relying solely on discrete player actions.
In the hotpotato
game, a player starts holding a potato. The longer they keep it, the more points they earn. However, after a random amount of time, the potato will explode, turning into rösti. The player holding the potato at that moment loses a significant number of points.
ClockDrivenStateMachine
To use the clock, your Logic
class needs to extend ClockDrivenStateMachine
class Logic extends ClockDrivenStateMachine[Event, State, View]:
apps/jvm/src/main/scala/apps/hotpotato/Logic.scala
This requires defining two fields:
override val clockPeriodMs: Int = 100 // How frequently we want to receive the clock tick events in ms
override val clockDrivenWire: AppWire[Event, View] = hotpotato.Wire // The wire of our app
apps/jvm/src/main/scala/apps/hotpotato/Logic.scala
Your transition
function will now take an event of type Either[Tick, Event]
, instead of Event
. This will allow you to handle the Tick
events as well as your regular events.
override def transition(state: State)(
userId: UserId,
event: Either[Tick, Event]
): Try[Seq[Action[State]]] =
apps/jvm/src/main/scala/apps/hotpotato/Logic.scala
For example, in our transition function, we separately handle cases where a Tick
or an Event
is received.
event match
case Left(Tick(_)) =>
if timer - clockPeriodMs <= 0 then
goToNextRound(state, holder)
else
Seq(Render(state.copy(
scores = state.scores.updatedWith(holder)(prevScore => Some(prevScore.get + 1)),
phase = Phase.Playing(holder, timer - clockPeriodMs)
)))
case Right(Event.Pass) =>
if holder == userId then
val players = state.scores.keys.toList.sorted
Seq(Render(state.copy(
phase = Phase.Playing(holder = pickNextPlayer(players, holder), timer = timer)
)))
else Seq()
apps/jvm/src/main/scala/apps/hotpotato/Logic.scala
Pictures
This example also includes a picture. If you want to use any kind of picture file, you can wrap it in a img
element. You need to put all your images in the apps/jvm/src/main/resources/www/static
directory, similar to thumbnails.
Then the src
attribute of the img
element needs to be /static/<my_image>
img(
src := "/static/rosti.png",
alt := "Rosti!",
cls := "rosti-image"
)
apps/js/src/main/scala/apps/hotpotato/UI.scala