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.

190 lines
5.8 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package wow.doge.mygame.game.entities
  2. import akka.actor.typed.ActorRef
  3. import akka.actor.typed.Scheduler
  4. import akka.actor.typed.SpawnProtocol
  5. import akka.util.Timeout
  6. import com.jme3.bullet.BulletAppState
  7. import com.jme3.bullet.control.BetterCharacterControl
  8. import com.jme3.math.FastMath
  9. import com.jme3.renderer.Camera
  10. import com.jme3.scene.CameraNode
  11. import com.jme3.scene.Geometry
  12. import com.jme3.scene.Node
  13. import com.jme3.scene.Spatial
  14. import com.jme3.scene.shape.Box
  15. import com.softwaremill.tagging._
  16. import io.odin.Logger
  17. import monix.bio.IO
  18. import monix.bio.Task
  19. import wow.doge.mygame.AppError
  20. import wow.doge.mygame.game.GameAppTags
  21. import wow.doge.mygame.game.SimpleAppExt
  22. import wow.doge.mygame.implicits._
  23. import wow.doge.mygame.math.ImVector3f
  24. import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
  25. import wow.doge.mygame.subsystems.events.PlayerEvent
  26. import wow.doge.mygame.subsystems.events.TickEvent
  27. import wow.doge.mygame.subsystems.movement.ImMovementActor
  28. import wow.doge.mygame.utils.AkkaUtils
  29. import wow.doge.mygame.utils.wrappers.jme._
  30. object PlayerControllerTags {
  31. sealed trait PlayerTag
  32. sealed trait PlayerCameraNode
  33. sealed trait PlayerCameraPivotNode
  34. }
  35. object PlayerController {
  36. sealed trait Error
  37. case class CouldNotCreatePlayerModel(reason: AssetManager.Error) extends Error
  38. class Props(
  39. enqueueR: Function1[() => Unit, Unit],
  40. rootNode: AppNode2 @@ GameAppTags.RootNode,
  41. loggerL: Logger[Task],
  42. // physicsSpace: com.jme3.bullet.PhysicsSpace,
  43. physicsSpace: PhysicsSpace,
  44. initialPlayerPos: ImVector3f = ImVector3f.Zero,
  45. playerEventBus: GameEventBus[PlayerEvent],
  46. playerPhysicsControl: BetterCharacterControl,
  47. // appScheduler: monix.execution.Scheduler,
  48. playerNode: Node @@ PlayerControllerTags.PlayerTag,
  49. cameraNode: CameraNode @@ PlayerControllerTags.PlayerCameraNode,
  50. cameraPivotNode: Node @@ PlayerControllerTags.PlayerCameraPivotNode,
  51. tickEventBus: GameEventBus[TickEvent],
  52. camera: Camera
  53. )(implicit
  54. spawnProtocol: ActorRef[SpawnProtocol.Command],
  55. timeout: Timeout,
  56. scheduler: Scheduler
  57. ) {
  58. val playerActorBehavior = {
  59. val movementActorBeh = new ImMovementActor.Props(
  60. enqueueR,
  61. camera
  62. ).behavior(playerPhysicsControl)
  63. val cameraActorBeh = new PlayerCameraActor.Props(
  64. cameraPivotNode,
  65. enqueueR,
  66. playerNode.getWorldTranslation _
  67. ).behavior
  68. new PlayerActorSupervisor.Props(
  69. playerEventBus,
  70. tickEventBus,
  71. movementActorBeh,
  72. cameraActorBeh
  73. ).behavior
  74. }
  75. val create: IO[AppError, ActorRef[PlayerActorSupervisor.Command]] =
  76. (for {
  77. playerActor <-
  78. AkkaUtils.spawnActorL(playerActorBehavior, "playerActorSupervisor")
  79. _ <- (for {
  80. _ <- rootNode += playerNode
  81. _ <- physicsSpace += playerNode
  82. _ <- physicsSpace += playerPhysicsControl
  83. _ = cameraPivotNode += cameraNode
  84. _ <- rootNode += cameraPivotNode
  85. } yield ()).mapError(AppError.AppNodeError)
  86. } yield playerActor)
  87. }
  88. def apply(
  89. app: SimpleAppExt,
  90. modelPath: os.RelPath,
  91. cam: Camera
  92. )(assetManager: AssetManager, bulletAppState: BulletAppState) = {
  93. val playerPos = ImVector3f.Zero
  94. val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
  95. .withJumpForce(ImVector3f(0, 5f, 0))
  96. val playerNode = new Node("PlayerNode")
  97. .withChildren(
  98. assetManager
  99. .loadModel(modelPath)
  100. .asInstanceOf[Node]
  101. .withRotate(0, FastMath.PI, 0)
  102. )
  103. .withLocalTranslation(playerPos)
  104. .withControl(playerPhysicsControl)
  105. {
  106. bulletAppState.physicsSpace += playerNode
  107. bulletAppState.physicsSpace += playerPhysicsControl
  108. }
  109. {
  110. app.rootNode += playerNode
  111. }
  112. playerPhysicsControl
  113. }
  114. object Defaults {
  115. def defaultMesh = {
  116. val b = Box(1, 1, 1)
  117. val geom = Geometry("playerGeom", b)
  118. geom
  119. }
  120. // def defaultTexture(assetManager: AssetManager) =
  121. // MyMaterial(
  122. // assetManager = assetManager,
  123. // path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
  124. // )
  125. // new CameraControl(cam) {
  126. // override def controlUpdate(tpf: Float) = {
  127. // this.getCamera().setRotation(spatial.getWorldRotation())
  128. // cameraPivotNode.setLocalTranslation(
  129. // playerNode.getWorldTranslation()
  130. // )
  131. // this.getCamera().setLocation(spatial.getWorldTranslation())
  132. // }
  133. // }
  134. def defaultCamerNode(
  135. cam: Camera,
  136. // playerNode: Node,
  137. // cameraPivotNode: Node,
  138. playerPos: ImVector3f
  139. ) =
  140. new CameraNode("CameraNode", cam)
  141. // .withControlDir(ControlDirection.SpatialToCamera)
  142. .withLocalTranslation(ImVector3f(0, 1.5f, 10))
  143. .withLookAt(playerPos, ImVector3f.UnitY)
  144. def defaultPlayerNode(
  145. playerPos: ImVector3f,
  146. playerModel: Node,
  147. // camNode: CameraNode,
  148. playerPhysicsControl: BetterCharacterControl
  149. ) =
  150. Node("PlayerNode")
  151. .withChildren(playerModel)
  152. .withLocalTranslation(playerPos)
  153. .withControl(playerPhysicsControl)
  154. .taggedWith[PlayerControllerTags.PlayerTag]
  155. def defaultNpcNode(
  156. // assetManager: AssetManager,
  157. npcModel: Spatial,
  158. initialPos: ImVector3f,
  159. npcPhysicsControl: BetterCharacterControl,
  160. npcName: String
  161. ) =
  162. // Either
  163. // .catchNonFatal(
  164. Node(npcName)
  165. .withChildren(
  166. // defaultMesh.withMaterial(defaultTexture(assetManager))
  167. npcModel
  168. )
  169. .withLocalTranslation(initialPos)
  170. .withControl(npcPhysicsControl)
  171. // )
  172. def defaultPlayerPhysicsControl =
  173. new BetterCharacterControl(1.5f, 6f, 1f)
  174. .withJumpForce(ImVector3f(0, 5f, 0))
  175. }
  176. }