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