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.

237 lines
6.4 KiB

  1. package wow.doge.mygame.game.subsystems.input
  2. import com.jme3.input.InputManager
  3. import wow.doge.mygame.implicits._
  4. import akka.actor.typed.ActorRef
  5. import wow.doge.mygame.events.EventBus
  6. import com.jme3.input.KeyInput
  7. import com.jme3.input.controls.KeyTrigger
  8. import monix.bio.UIO
  9. import wow.doge.mygame.utils.IOUtils._
  10. import wow.doge.mygame.subsystems.events.MovementEvent.PlayerMovementEvent
  11. import scala.concurrent.duration._
  12. import com.jme3.input.controls.MouseAxisTrigger
  13. import com.jme3.input.MouseInput
  14. // class GameInputHandler(
  15. // inputManager: InputManager
  16. // // inputEventBus: InputEventBus
  17. // ) {}
  18. object GameInputHandler {
  19. final case class Props(
  20. inputManager: InputManager,
  21. playerMovementEventBus: ActorRef[
  22. EventBus.Command[PlayerMovementEvent]
  23. ]
  24. ) {
  25. def begin =
  26. for {
  27. _ <- UIO(setupKeys(inputManager))
  28. _ <- toIO(
  29. generateMovementInputEvents(
  30. inputManager,
  31. playerMovementEventBus
  32. ).completedL.startAndForget
  33. )
  34. _ <- toIO(
  35. generateRotateEvents(
  36. inputManager,
  37. playerMovementEventBus
  38. ).completedL.startAndForget
  39. )
  40. _ <- toIO(
  41. generateCameraEvents(
  42. inputManager,
  43. playerMovementEventBus
  44. ).completedL.startAndForget
  45. )
  46. } yield ()
  47. }
  48. def setupKeys(inputManager: InputManager) =
  49. inputManager
  50. .withMapping(
  51. "Left",
  52. new KeyTrigger(KeyInput.KEY_A)
  53. // new KeyTrigger(KeyInput.KEY_LEFT)
  54. )
  55. .withMapping(
  56. "Right",
  57. new KeyTrigger(KeyInput.KEY_D)
  58. // new KeyTrigger(KeyInput.KEY_RIGHT)
  59. )
  60. .withMapping(
  61. "Up",
  62. new KeyTrigger(KeyInput.KEY_W)
  63. // new KeyTrigger(KeyInput.KEY_UP)
  64. )
  65. .withMapping(
  66. "Down",
  67. new KeyTrigger(KeyInput.KEY_S)
  68. // new KeyTrigger(KeyInput.KEY_DOWN)
  69. )
  70. .withMapping(
  71. "Jump",
  72. new KeyTrigger(KeyInput.KEY_SPACE)
  73. )
  74. .withMapping(
  75. "ROTATE_RIGHT",
  76. new KeyTrigger(KeyInput.KEY_RIGHT),
  77. new MouseAxisTrigger(MouseInput.AXIS_X, true)
  78. )
  79. .withMapping(
  80. "ROTATE_LEFT",
  81. new KeyTrigger(KeyInput.KEY_LEFT),
  82. new MouseAxisTrigger(MouseInput.AXIS_X, false)
  83. )
  84. .withMapping(
  85. "CAMERA_UP",
  86. // new KeyTrigger(KeyInput.KEY_LEFT),
  87. new MouseAxisTrigger(MouseInput.AXIS_Y, false)
  88. )
  89. .withMapping(
  90. "CAMERA_DOWN",
  91. // new KeyTrigger(KeyInput.KEY_LEFT),
  92. new MouseAxisTrigger(MouseInput.AXIS_Y, true)
  93. )
  94. .setCursorVisible(false)
  95. def generateMovementInputEvents(
  96. inputManager: InputManager,
  97. playerMovementEventBus: ActorRef[
  98. EventBus.Command[PlayerMovementEvent]
  99. ]
  100. ) = {
  101. val name = "movementInputEventsGenerator"
  102. inputManager
  103. .observableAction(
  104. "Left",
  105. "Right",
  106. "Up",
  107. "Down",
  108. "Jump",
  109. "ROTATE_RIGHT",
  110. "ROTATE_LEFT"
  111. )
  112. // .dump("O")
  113. .doOnNext { action =>
  114. action.binding.name match {
  115. case "Left" =>
  116. toTask(
  117. playerMovementEventBus !! EventBus.Publish(
  118. PlayerMovementEvent.PlayerMovedLeft(pressed = action.value),
  119. name
  120. )
  121. )
  122. case "Right" =>
  123. toTask(
  124. playerMovementEventBus !! EventBus.Publish(
  125. PlayerMovementEvent.PlayerMovedRight(pressed = action.value),
  126. name
  127. )
  128. )
  129. case "Up" =>
  130. toTask(
  131. playerMovementEventBus !! EventBus.Publish(
  132. PlayerMovementEvent.PlayerMovedForward(pressed = action.value),
  133. name
  134. )
  135. )
  136. case "Down" =>
  137. toTask(
  138. playerMovementEventBus !! EventBus.Publish(
  139. PlayerMovementEvent.PlayerMovedBackward(pressed = action.value),
  140. name
  141. )
  142. )
  143. case "Jump" if action.value =>
  144. toTask(
  145. playerMovementEventBus !! EventBus.Publish(
  146. PlayerMovementEvent.PlayerJumped,
  147. name
  148. )
  149. )
  150. case _ => monix.eval.Task.unit
  151. }
  152. }
  153. }
  154. def generateRotateEvents(
  155. inputManager: InputManager,
  156. playerMovementEventBus: ActorRef[
  157. EventBus.Command[PlayerMovementEvent]
  158. ]
  159. ) = {
  160. val name = "rotateMovementEventsGenerator"
  161. inputManager
  162. .analogObservable("ROTATE_RIGHT", "ROTATE_LEFT")
  163. .sample(1.millis)
  164. .mapEval(analogEvent =>
  165. analogEvent.binding.name match {
  166. case "ROTATE_RIGHT" =>
  167. toTask(
  168. playerMovementEventBus !! EventBus.Publish(
  169. PlayerMovementEvent.PlayerRotatedRight,
  170. name
  171. )
  172. )
  173. case "ROTATE_LEFT" =>
  174. toTask(
  175. playerMovementEventBus !! EventBus.Publish(
  176. PlayerMovementEvent.PlayerRotatedLeft,
  177. name
  178. )
  179. )
  180. case _ => monix.eval.Task.unit
  181. }
  182. )
  183. }
  184. def generateCameraEvents(
  185. inputManager: InputManager,
  186. playerMovementEventBus: ActorRef[
  187. EventBus.Command[PlayerMovementEvent]
  188. ]
  189. ) = {
  190. val name = "cameraMovementEventsGenerator"
  191. inputManager
  192. .analogObservable("CAMERA_UP", "CAMERA_DOWN")
  193. .sample(1.millis)
  194. .mapEval(analogEvent =>
  195. analogEvent.binding.name match {
  196. case "CAMERA_UP" =>
  197. toTask(
  198. playerMovementEventBus !! EventBus.Publish(
  199. PlayerMovementEvent.PlayerCameraUp,
  200. name
  201. )
  202. )
  203. case "CAMERA_DOWN" =>
  204. toTask(
  205. playerMovementEventBus !! EventBus.Publish(
  206. PlayerMovementEvent.PlayerCameraDown,
  207. name
  208. )
  209. )
  210. case _ => monix.eval.Task.unit
  211. }
  212. )
  213. }
  214. // def bindMappings(inputManager: InputManager, mappings: ActionMapping*) = {
  215. // inputManager
  216. // .observableAction(mappings.map(_.name): _*)
  217. // .doOnNext(action =>
  218. // mappings.map(m =>
  219. // if (action.binding.name == m.name) toTask(m.cb(action))
  220. // else monix.eval.Task.unit
  221. // )
  222. // )
  223. // }
  224. }
  225. // case class ActionMapping(name: String, cb: ActionEvent => Task[Unit])