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.
 
 

247 lines
7.2 KiB

package wow.doge.mygame.game.subsystems.input
import com.jme3.input.InputManager
import wow.doge.mygame.implicits._
import akka.actor.typed.ActorRef
import wow.doge.mygame.events.EventBus
import com.jme3.input.KeyInput
import com.jme3.input.controls.KeyTrigger
import monix.bio.UIO
import wow.doge.mygame.utils.IOUtils._
import wow.doge.mygame.subsystems.events.EntityMovementEvent.PlayerMovementEvent
import scala.concurrent.duration._
import com.jme3.input.controls.MouseAxisTrigger
import com.jme3.input.MouseInput
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
// class GameInputHandler(
// inputManager: InputManager
// // inputEventBus: InputEventBus
// ) {}
object GameInputHandler {
final case class Props(
inputManager: InputManager,
playerMovementEventBus: ActorRef[
EventBus.Command[PlayerMovementEvent]
],
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
) {
def begin =
for {
_ <- UIO(setupKeys(inputManager))
_ <- toIO(
generateMovementInputEvents(
inputManager,
playerMovementEventBus
).completedL.startAndForget
)
_ <- toIO(
generateRotateEvents(
inputManager,
playerMovementEventBus
).completedL.startAndForget
)
_ <- toIO(
generateCameraEvents(
inputManager,
playerCameraEventBus
).completedL.startAndForget
)
_ <- toIO(
myTest(
inputManager
).completedL.startAndForget
)
} yield ()
}
def setupKeys(inputManager: InputManager) =
inputManager
.withMapping(
PlayerMovementInput.WalkLeft.entryName,
new KeyTrigger(KeyInput.KEY_A)
// new KeyTrigger(KeyInput.KEY_LEFT)
)
.withMapping(
PlayerMovementInput.WalkRight.entryName,
new KeyTrigger(KeyInput.KEY_D)
// new KeyTrigger(KeyInput.KEY_RIGHT)
)
.withMapping(
PlayerMovementInput.WalkForward.entryName,
new KeyTrigger(KeyInput.KEY_W)
// new KeyTrigger(KeyInput.KEY_UP)
)
.withMapping(
PlayerMovementInput.WalkBackward.entryName,
new KeyTrigger(KeyInput.KEY_S)
// new KeyTrigger(KeyInput.KEY_DOWN)
)
.withMapping(
"Jump",
new KeyTrigger(KeyInput.KEY_SPACE)
)
.withMapping(
PlayerAnalogInput.TurnRight.entryName,
new KeyTrigger(KeyInput.KEY_RIGHT),
new MouseAxisTrigger(MouseInput.AXIS_X, true)
)
.withMapping(
PlayerAnalogInput.TurnLeft.entryName,
new KeyTrigger(KeyInput.KEY_LEFT),
new MouseAxisTrigger(MouseInput.AXIS_X, false)
)
.withMapping(
"CAMERA_UP",
// new KeyTrigger(KeyInput.KEY_LEFT),
new MouseAxisTrigger(MouseInput.AXIS_Y, false)
)
.withMapping(
"CAMERA_DOWN",
// new KeyTrigger(KeyInput.KEY_LEFT),
new MouseAxisTrigger(MouseInput.AXIS_Y, true)
)
.setCursorVisible(false)
def generateMovementInputEvents(
inputManager: InputManager,
playerMovementEventBus: ActorRef[
EventBus.Command[PlayerMovementEvent]
]
) = {
val name = "playerMovementInputEventsGenerator"
inputManager
.enumObservableAction(PlayerMovementInput)
// .dump("O")
.doOnNext { action =>
action.binding match {
case PlayerMovementInput.WalkLeft =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerMovedLeft(pressed = action.value),
name
)
)
case PlayerMovementInput.WalkRight =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerMovedRight(pressed = action.value),
name
)
)
case PlayerMovementInput.WalkForward =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerMovedForward(pressed = action.value),
name
)
)
case PlayerMovementInput.WalkBackward =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerMovedBackward(pressed = action.value),
name
)
)
// case "Jump" if action.value =>
// toTask(
// playerMovementEventBus !! EventBus.Publish(
// PlayerMovementEvent.PlayerJumped,
// name
// )
// )
// case _ => monix.eval.Task.unit
}
}
}
def myTest(inputManager: InputManager) = {
inputManager
.enumObservableAction(PlayerMovementEnum)
.sample(1.millis)
.mapEval(action =>
action.binding match {
case PlayerMovementEnum.MOVE_RIGHT =>
monix.eval.Task(println("move right")) >> monix.eval.Task.unit
case PlayerMovementEnum.MOVE_LEFT =>
monix.eval.Task(println("move left"))
}
)
}
def generateRotateEvents(
inputManager: InputManager,
playerMovementEventBus: ActorRef[
EventBus.Command[PlayerMovementEvent]
]
) = {
val name = "rotateMovementEventsGenerator"
inputManager
.enumAnalogObservable(PlayerAnalogInput)
.sample(1.millis)
.map(e => e)
.doOnNext(analogEvent =>
analogEvent.binding match {
case PlayerAnalogInput.TurnRight =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerRotatedRight,
name
)
)
case PlayerAnalogInput.TurnLeft =>
toTask(
playerMovementEventBus !! EventBus.Publish(
PlayerMovementEvent.PlayerRotatedLeft,
name
)
)
}
)
}
def generateCameraEvents(
inputManager: InputManager,
playerCameraEventBus: ActorRef[EventBus.Command[PlayerCameraEvent]]
) = {
val name = "cameraMovementEventsGenerator"
inputManager
.analogObservable("CAMERA_UP", "CAMERA_DOWN")
.sample(1.millis)
.mapEval(analogEvent =>
analogEvent.binding.name match {
case "CAMERA_UP" =>
toTask(
playerCameraEventBus !! EventBus.Publish(
PlayerCameraEvent.CameraMovedUp,
name
)
)
case "CAMERA_DOWN" =>
toTask(
playerCameraEventBus !! EventBus.Publish(
PlayerCameraEvent.CameraMovedDown,
name
)
)
case _ => monix.eval.Task.unit
}
)
}
// def bindMappings(inputManager: InputManager, mappings: ActionMapping*) = {
// inputManager
// .observableAction(mappings.map(_.name): _*)
// .doOnNext(action =>
// mappings.map(m =>
// if (action.binding.name == m.name) toTask(m.cb(action))
// else monix.eval.Task.unit
// )
// )
// }
}
// case class ActionMapping(name: String, cb: ActionEvent => Task[Unit])