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.

139 lines
4.7 KiB

4 years ago
  1. package wow.doge.mygame
  2. import akka.actor.typed.ActorRef
  3. import akka.actor.typed.ActorSystem
  4. import akka.actor.typed.Scheduler
  5. import akka.actor.typed.SpawnProtocol
  6. import akka.util.Timeout
  7. import cats.effect.concurrent.Ref
  8. import com.jme3.app.state.AppStateManager
  9. import com.jme3.asset.AssetManager
  10. import com.jme3.asset.plugins.ZipLocator
  11. import com.jme3.bullet.BulletAppState
  12. import com.jme3.input.InputManager
  13. import com.jme3.renderer.Camera
  14. import com.jme3.scene.Node
  15. import com.softwaremill.macwire._
  16. import com.softwaremill.tagging._
  17. import io.odin.Logger
  18. import monix.bio.IO
  19. import monix.bio.Task
  20. import wow.doge.mygame.events.EventBus
  21. import wow.doge.mygame.game.GameApp2
  22. import wow.doge.mygame.game.nodes.Player
  23. import wow.doge.mygame.game.nodes.PlayerController
  24. import wow.doge.mygame.game.subsystems.input.GameInputHandler
  25. import wow.doge.mygame.implicits._
  26. import wow.doge.mygame.math.ImVector3f
  27. import wow.doge.mygame.subsystems.events.EntityMovementEvent
  28. import wow.doge.mygame.subsystems.events.EventsModule2
  29. import wow.doge.mygame.subsystems.events.PlayerCameraEvent
  30. import wow.doge.mygame.game.subsystems.level.DefaultGameLevel
  31. import com.jme3.renderer.ViewPort
  32. import wow.doge.mygame.subsystems.scriptsystem.ScriptSystemResource
  33. import wow.doge.mygame.subsystems.scriptsystem.ScriptInitMode
  34. class MainApp(
  35. logger: Logger[Task],
  36. gameApp: GameApp2,
  37. spawnProtocol: ActorSystem[SpawnProtocol.Command],
  38. jmeThread: monix.execution.Scheduler
  39. )(implicit
  40. @annotation.unused timeout: Timeout,
  41. @annotation.unused scheduler: Scheduler
  42. ) {
  43. lazy val scriptSystemInit =
  44. new ScriptSystemResource(os.pwd, spawnProtocol, ScriptInitMode.Eager).init
  45. lazy val gameInit: Task[Unit] = for {
  46. eventsModule <- Task(new EventsModule2(spawnProtocol))
  47. playerMovementEventBus <- eventsModule.playerMovementEventBusTask
  48. playerCameraEventBus <- eventsModule.playerCameraEventBusTask
  49. gameAppFib <- gameApp.start.executeOn(jmeThread).start
  50. /**
  51. * schedule a fiber to run on the JME thread and wait for it's completion
  52. * before proceeding forward, as a signal that JME thread has been
  53. * initialized, otherwise we'll get NPEs trying to access the fields
  54. * of the game app
  55. */
  56. initFib <- gameApp.enqueueL(() => Task("done")).start
  57. _ <- initFib.join
  58. inputManager <- gameApp.inputManager
  59. assetManager <- gameApp.assetManager
  60. stateManager <- gameApp.stateManager
  61. camera <- gameApp.camera
  62. rootNode <- gameApp.rootNode
  63. enqueueR <- Task(gameApp.enqueue _)
  64. viewPort <- gameApp.viewPort
  65. bulletAppState <- Task(new BulletAppState())
  66. appScheduler <- Task(gameApp.scheduler)
  67. // enqueueL <- Task(gameApp.enqueueL _)
  68. _ <- wire[MainAppDelegate].init(gameApp.scheduler)
  69. _ <- gameAppFib.join
  70. } yield ()
  71. lazy val program = for {
  72. scriptSystem <- scriptSystemInit
  73. game <- gameInit
  74. } yield ()
  75. }
  76. class MainAppDelegate(
  77. gameApp: GameApp2,
  78. spawnProtocol: ActorSystem[SpawnProtocol.Command],
  79. loggerL: Logger[Task],
  80. // eventBuses: EventsModule2
  81. playerMovementEventBus: ActorRef[
  82. EventBus.Command[EntityMovementEvent.PlayerMovementEvent]
  83. ],
  84. playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]],
  85. inputManager: InputManager,
  86. assetManager: AssetManager,
  87. stateManager: AppStateManager,
  88. camera: Camera,
  89. viewPort: ViewPort,
  90. enqueueR: Function1[() => Unit, Unit],
  91. rootNode: Ref[Task, Node],
  92. bulletAppState: BulletAppState
  93. )(implicit
  94. @annotation.unused timeout: Timeout,
  95. @annotation.unused scheduler: Scheduler
  96. ) {
  97. def init(appScheduler: monix.execution.Scheduler) =
  98. for {
  99. _ <- loggerL.info("Initializing Systems")
  100. _ <- Task(stateManager.attach(bulletAppState))
  101. _ <- Task(
  102. assetManager.registerLocator(
  103. (os.rel / "assets" / "town.zip"),
  104. classOf[ZipLocator]
  105. )
  106. )
  107. _ <- DefaultGameLevel(assetManager, viewPort)
  108. .addToGame(
  109. rootNode,
  110. bulletAppState.physicsSpace
  111. )
  112. .executeOn(appScheduler)
  113. _ <- createPlayerController(appScheduler).startAndForget.onErrorRestart(3)
  114. _ <- wire[GameInputHandler.Props].begin.onErrorRestart(3)
  115. } yield ()
  116. def createPlayerController(
  117. appScheduler: monix.execution.Scheduler
  118. // playerMovementEventBus: ActorRef[
  119. // EventBus.Command[PlayerMovementEvent]
  120. // ],
  121. // playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
  122. ): IO[PlayerController.Error, Unit] = {
  123. @annotation.unused
  124. val playerPos = ImVector3f.ZERO
  125. @annotation.unused
  126. val playerNode = None.taggedWith[Player]
  127. @annotation.unused
  128. val modelPath = os.rel / "Models" / "Jaime" / "Jaime.j3o"
  129. wire[PlayerController.Props].create
  130. }
  131. }