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.

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