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.

255 lines
8.0 KiB

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
4 years ago
4 years ago
4 years ago
  1. package wow.doge.mygame.game.subsystems.input
  2. import scala.concurrent.duration._
  3. import akka.actor.typed.ActorRef
  4. import cats.effect.concurrent.Ref
  5. import com.jme3.input.InputManager
  6. import com.jme3.input.KeyInput
  7. import com.jme3.input.MouseInput
  8. import com.jme3.input.controls.KeyTrigger
  9. import com.jme3.input.controls.MouseAxisTrigger
  10. import monix.bio.UIO
  11. import monix.{eval => me}
  12. import wow.doge.mygame.implicits._
  13. import wow.doge.mygame.subsystems.events.EventBus
  14. import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
  15. import wow.doge.mygame.subsystems.events.PlayerCameraEvent
  16. import wow.doge.mygame.subsystems.events.PlayerMovementEvent
  17. import wow.doge.mygame.utils.IOUtils._
  18. object GameInputHandler {
  19. final class Props(
  20. inputManager: InputManager,
  21. playerMovementEventBus: GameEventBus[PlayerMovementEvent],
  22. playerCameraEventBus: GameEventBus[PlayerCameraEvent]
  23. // tickEventBus: GameEventBus[TickEvent]
  24. ) {
  25. def begin =
  26. for {
  27. _ <- UIO(setupMovementKeys(inputManager))
  28. // _ <- UIO(setupAnalogMovementKeys)
  29. _ <- UIO(setupCameraKeys())
  30. _ <- toIO(
  31. generateMovementInputEvents(
  32. inputManager,
  33. playerMovementEventBus
  34. ).completedL.startAndForget
  35. )
  36. _ <- toIO(
  37. generateAnalogMovementEvents(
  38. inputManager,
  39. playerMovementEventBus
  40. ).completedL.startAndForget
  41. )
  42. _ <- toIO(
  43. generateCameraEvents(
  44. inputManager,
  45. playerCameraEventBus
  46. ).completedL.startAndForget
  47. )
  48. _ <- toIO(
  49. Ref.of[me.Task, Boolean](false).flatMap(value => cursorToggle(value))
  50. )
  51. } yield ()
  52. def setupMovementKeys(inputManager: InputManager) =
  53. inputManager.withEnumMappings(PlayerMovementInput) {
  54. case PlayerMovementInput.WalkRight =>
  55. Seq(new KeyTrigger(KeyInput.KEY_D))
  56. case PlayerMovementInput.WalkLeft =>
  57. Seq(new KeyTrigger(KeyInput.KEY_A))
  58. case PlayerMovementInput.WalkForward =>
  59. Seq(new KeyTrigger(KeyInput.KEY_W))
  60. case PlayerMovementInput.WalkBackward =>
  61. Seq(new KeyTrigger(KeyInput.KEY_S))
  62. case PlayerMovementInput.Jump =>
  63. Seq(new KeyTrigger(KeyInput.KEY_SPACE))
  64. }
  65. def setupAnalogMovementKeys() =
  66. inputManager.withEnumMappings(PlayerAnalogMovementInput) {
  67. case PlayerAnalogMovementInput.TurnRight =>
  68. Seq(new KeyTrigger(KeyInput.KEY_D))
  69. case PlayerAnalogMovementInput.TurnLeft =>
  70. Seq(new KeyTrigger(KeyInput.KEY_A))
  71. }
  72. def setupCameraKeys() =
  73. inputManager.withEnumMappings(PlayerCameraInput) {
  74. case PlayerCameraInput.CameraRotateLeft =>
  75. Seq(
  76. new KeyTrigger(KeyInput.KEY_LEFT),
  77. new MouseAxisTrigger(MouseInput.AXIS_X, false)
  78. )
  79. case PlayerCameraInput.CameraRotateRight =>
  80. Seq(
  81. new KeyTrigger(KeyInput.KEY_RIGHT),
  82. new MouseAxisTrigger(MouseInput.AXIS_X, true)
  83. )
  84. case PlayerCameraInput.CameraRotateUp =>
  85. Seq(
  86. new KeyTrigger(KeyInput.KEY_UP),
  87. new MouseAxisTrigger(MouseInput.AXIS_Y, false)
  88. )
  89. case PlayerCameraInput.CameraRotateDown =>
  90. Seq(
  91. new KeyTrigger(KeyInput.KEY_DOWN),
  92. new MouseAxisTrigger(MouseInput.AXIS_Y, true)
  93. )
  94. }
  95. def cursorToggle(toggleRef: Ref[me.Task, Boolean]) =
  96. for {
  97. _ <- me.Task(
  98. inputManager.withMapping(
  99. MiscInput.ToggleCursor,
  100. new KeyTrigger(KeyInput.KEY_Z)
  101. )
  102. )
  103. _ <-
  104. inputManager
  105. .enumEntryObservableAction(MiscInput.ToggleCursor)
  106. .doOnNext(action =>
  107. action.binding match {
  108. case MiscInput.ToggleCursor =>
  109. if (action.value) for {
  110. value <- toggleRef.getAndUpdate(!_)
  111. _ <- me.Task(inputManager.setCursorVisible(value))
  112. } yield ()
  113. else me.Task.unit
  114. // case _ => me.Task.unit
  115. }
  116. )
  117. .completedL
  118. .startAndForget
  119. } yield ()
  120. }
  121. def generateMovementInputEvents(
  122. inputManager: InputManager,
  123. playerMovementEventBus: ActorRef[
  124. EventBus.Command[PlayerMovementEvent]
  125. ]
  126. ) = {
  127. val name = "playerMovementInputEventsGenerator"
  128. inputManager
  129. .enumObservableAction(PlayerMovementInput)
  130. // .dump("O")
  131. .doOnNext { action =>
  132. action.binding match {
  133. case PlayerMovementInput.WalkLeft =>
  134. me.Task(
  135. playerMovementEventBus ! EventBus.Publish(
  136. PlayerMovementEvent.PlayerMovedLeft(pressed = action.value),
  137. name
  138. )
  139. )
  140. case PlayerMovementInput.WalkRight =>
  141. me.Task(
  142. playerMovementEventBus ! EventBus.Publish(
  143. PlayerMovementEvent.PlayerMovedRight(pressed = action.value),
  144. name
  145. )
  146. )
  147. case PlayerMovementInput.WalkForward =>
  148. me.Task(
  149. playerMovementEventBus ! EventBus.Publish(
  150. PlayerMovementEvent.PlayerMovedForward(pressed = action.value),
  151. name
  152. )
  153. )
  154. case PlayerMovementInput.WalkBackward =>
  155. me.Task(
  156. playerMovementEventBus ! EventBus.Publish(
  157. PlayerMovementEvent.PlayerMovedBackward(pressed = action.value),
  158. name
  159. )
  160. )
  161. case PlayerMovementInput.Jump =>
  162. if (action.value) {
  163. me.Task(
  164. playerMovementEventBus ! EventBus.Publish(
  165. PlayerMovementEvent.PlayerJumped,
  166. name
  167. )
  168. )
  169. } else me.Task.unit
  170. }
  171. }
  172. }
  173. def generateAnalogMovementEvents(
  174. inputManager: InputManager,
  175. playerMovementEventBus: ActorRef[
  176. EventBus.Command[PlayerMovementEvent]
  177. ]
  178. ) = {
  179. // val name = "analogMovementEventsGenerator"
  180. inputManager
  181. .enumAnalogObservable(PlayerAnalogMovementInput)
  182. .sample(1.millis)
  183. // .doOnNext(analogEvent =>
  184. // analogEvent.binding match {
  185. // case PlayerAnalogMovementInput.TurnRight =>
  186. // me.Task(
  187. // playerMovementEventBus ! EventBus.Publish(
  188. // PlayerMovementEvent.PlayerTurnedRight,
  189. // name
  190. // )
  191. // )
  192. // case PlayerAnalogMovementInput.TurnLeft =>
  193. // me.Task(
  194. // playerMovementEventBus ! EventBus.Publish(
  195. // PlayerMovementEvent.PlayerTurnedLeft,
  196. // name
  197. // )
  198. // )
  199. // }
  200. // )
  201. }
  202. def generateCameraEvents(
  203. inputManager: InputManager,
  204. playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
  205. ) = {
  206. val name = "cameraMovementEventsGenerator"
  207. inputManager
  208. .enumAnalogObservable(PlayerCameraInput)
  209. .sample(1.millis)
  210. .doOnNext(analogEvent =>
  211. analogEvent.binding match {
  212. case PlayerCameraInput.CameraRotateLeft =>
  213. me.Task(
  214. playerCameraEventBus ! EventBus.Publish(
  215. PlayerCameraEvent.CameraLeft,
  216. name
  217. )
  218. )
  219. case PlayerCameraInput.CameraRotateRight =>
  220. me.Task(
  221. playerCameraEventBus ! EventBus.Publish(
  222. PlayerCameraEvent.CameraRight,
  223. name
  224. )
  225. )
  226. case PlayerCameraInput.CameraRotateUp =>
  227. me.Task(
  228. playerCameraEventBus ! EventBus.Publish(
  229. PlayerCameraEvent.CameraMovedUp,
  230. name
  231. )
  232. )
  233. case PlayerCameraInput.CameraRotateDown =>
  234. me.Task(
  235. playerCameraEventBus ! EventBus.Publish(
  236. PlayerCameraEvent.CameraMovedDown,
  237. name
  238. )
  239. )
  240. }
  241. )
  242. }
  243. }