Testing out JmonkeyEngine to make a game in Scala with Akka Actors within a pure FP layer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.4 KiB

4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package wow.doge.mygame.game.entities
  2. import scala.concurrent.duration._
  3. import scala.util.Random
  4. import akka.actor.typed.ActorRef
  5. import akka.actor.typed.Behavior
  6. import akka.actor.typed.LogOptions
  7. import akka.actor.typed.SupervisorStrategy
  8. import akka.actor.typed.scaladsl.ActorContext
  9. import akka.actor.typed.scaladsl.Behaviors
  10. import akka.actor.typed.scaladsl.TimerScheduler
  11. import com.typesafe.scalalogging.Logger
  12. import org.slf4j.event.Level
  13. import wow.doge.mygame.game.subsystems.movement.CanMove
  14. import wow.doge.mygame.subsystems.events.EventBus
  15. import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
  16. import wow.doge.mygame.subsystems.events.PlayerCameraEvent
  17. import wow.doge.mygame.subsystems.events.PlayerMovementEvent
  18. import wow.doge.mygame.subsystems.events.TickEvent
  19. import wow.doge.mygame.subsystems.events.TickEvent.RenderTick
  20. import wow.doge.mygame.subsystems.movement.ImMovementActor
  21. object PlayerActorSupervisor {
  22. sealed trait Command
  23. final case class Props(
  24. playerMovementEventBus: ActorRef[
  25. EventBus.Command[PlayerMovementEvent]
  26. ],
  27. playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
  28. tickEventBus: GameEventBus[TickEvent],
  29. imMovementActorBehavior: Behavior[ImMovementActor.Command],
  30. playerCameraActorBehavior: Behavior[PlayerCameraActor.Command]
  31. ) {
  32. def create[T: CanMove](movable: T) =
  33. Behaviors.logMessages(
  34. LogOptions()
  35. .withLevel(Level.TRACE)
  36. .withLogger(
  37. Logger[PlayerActorSupervisor[T]].underlying
  38. ),
  39. Behaviors.setup[Command] { ctx =>
  40. ctx.log.info("Hello from PlayerActor")
  41. // spawn children actors
  42. lazy val movementActor =
  43. ctx.spawn(
  44. Behaviors
  45. .supervise(imMovementActorBehavior)
  46. .onFailure[Exception](SupervisorStrategy.restart),
  47. "playerMovementActorChild"
  48. )
  49. val playerCameraActor =
  50. ctx.spawn(playerCameraActorBehavior, "playerCameraActor")
  51. val playerCameraEl = ctx.spawn(
  52. PlayerCameraEventListener(playerCameraActor),
  53. "playerCameraActorEl"
  54. )
  55. ctx.spawn(
  56. PlayerMovementActor
  57. .Props(
  58. movementActor,
  59. playerCameraActor,
  60. playerMovementEventBus,
  61. tickEventBus
  62. )
  63. .create,
  64. "playerMovementAcor"
  65. )
  66. //init actors
  67. playerCameraEventBus ! EventBus.Subscribe(playerCameraEl)
  68. new PlayerActorSupervisor(
  69. ctx,
  70. this,
  71. Children(movementActor)
  72. ).receive
  73. }
  74. )
  75. }
  76. case class Children(
  77. movementActor: ActorRef[ImMovementActor.Command]
  78. )
  79. }
  80. class PlayerActorSupervisor[T: CanMove](
  81. ctx: ActorContext[PlayerActorSupervisor.Command],
  82. props: PlayerActorSupervisor.Props,
  83. children: PlayerActorSupervisor.Children
  84. ) {
  85. import PlayerActorSupervisor._
  86. def receive =
  87. Behaviors.receiveMessage[Command] {
  88. case _ =>
  89. // children.movementActor ! ImMovementActor.MovedDown(true)
  90. Behaviors.same
  91. }
  92. }
  93. object PlayerMovementActor {
  94. sealed trait Command
  95. final case class Props(
  96. movementActor: ActorRef[ImMovementActor.Command],
  97. playerCameraActor: ActorRef[PlayerCameraActor.Command],
  98. playerMovementEventBus: ActorRef[
  99. EventBus.Command[PlayerMovementEvent]
  100. ],
  101. tickEventBus: GameEventBus[TickEvent]
  102. ) {
  103. def create: Behavior[Command] =
  104. Behaviors.setup { ctx =>
  105. val playerMovementEl = ctx.spawn(
  106. Behaviors
  107. .supervise(PlayerMovementEventListener(movementActor))
  108. .onFailure[Exception](SupervisorStrategy.restart),
  109. "playerMovementEventHandler"
  110. )
  111. val renderTickElBehavior =
  112. Behaviors.receiveMessage[RenderTick.type] {
  113. case RenderTick =>
  114. movementActor ! ImMovementActor.Tick
  115. // playerCameraActor ! PlayerCameraActor.Tick
  116. Behaviors.same
  117. }
  118. val renderTickEl =
  119. ctx.spawn(renderTickElBehavior, "playerMovementTickListener")
  120. playerMovementEventBus ! EventBus.Subscribe(playerMovementEl)
  121. tickEventBus ! EventBus.Subscribe(renderTickEl)
  122. Behaviors.receiveMessage { msg => Behaviors.same }
  123. }
  124. }
  125. }
  126. object GenericTimerActor {
  127. sealed trait Command
  128. final case object Start extends Command
  129. final case object Stop extends Command
  130. private case object Send extends Command
  131. case class TimerKey(seed: Long)
  132. case class Props[T](
  133. target: ActorRef[T],
  134. messageToSend: T,
  135. timeInterval: FiniteDuration
  136. ) {
  137. val create = Behaviors.withTimers[Command] { timers =>
  138. new GenericTimerActor(timers, TimerKey(Random.nextLong()), this).idle
  139. }
  140. }
  141. }
  142. class GenericTimerActor[T](
  143. timers: TimerScheduler[GenericTimerActor.Command],
  144. timerKey: GenericTimerActor.TimerKey,
  145. props: GenericTimerActor.Props[T]
  146. ) {
  147. import GenericTimerActor._
  148. val idle: Behavior[Command] =
  149. Behaviors.receiveMessage {
  150. case Start =>
  151. timers.startTimerWithFixedDelay(timerKey, Send, props.timeInterval)
  152. active
  153. case _ => Behaviors.unhandled
  154. }
  155. val active: Behavior[Command] =
  156. Behaviors.receiveMessagePartial {
  157. case Send =>
  158. props.target ! props.messageToSend
  159. Behaviors.same
  160. case Stop =>
  161. timers.cancel(timerKey)
  162. idle
  163. }
  164. }