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

package wow.doge.mygame.game.subsystems.input
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import cats.effect.concurrent.Ref
import com.jme3.input.InputManager
import com.jme3.input.KeyInput
import com.jme3.input.MouseInput
import com.jme3.input.controls.KeyTrigger
import com.jme3.input.controls.MouseAxisTrigger
import monix.bio.Task
import monix.{eval => me}
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.EventBus
import wow.doge.mygame.subsystems.events.EventsModule.GameEventBus
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.subsystems.events.PlayerEvent
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
import wow.doge.mygame.utils.IOUtils._
import monix.bio.UIO
object GameInputHandler {
class Props(
inputManager: InputManager,
playerEventBus: GameEventBus[PlayerEvent]
// playerCameraEventBus: GameEventBus[PlayerCameraEvent]
// tickEventBus: GameEventBus[TickEvent]
) {
def begin =
for {
_ <- UIO(setupMovementKeys(inputManager))
// _ <- UIO(setupAnalogMovementKeys)
_ <- UIO(setupCameraKeys())
_ <- toIO(
me.Task.parSequence(
Seq(
playerMovementInputEventsGenerator(
inputManager,
playerEventBus
).completedL,
// generateAnalogMovementEvents(
// inputManager,
// playerEventBus
// ).completedL,
generateCameraEvents(
inputManager,
playerEventBus
).completedL,
Ref
.of[me.Task, Boolean](false)
.flatMap(value => cursorToggle(value))
)
)
).startAndForget
} yield ()
def setupMovementKeys(inputManager: InputManager) =
inputManager.withEnumMappings(PlayerMovementInput) {
case PlayerMovementInput.WalkRight =>
new KeyTrigger(KeyInput.KEY_D) :: Nil
case PlayerMovementInput.WalkLeft =>
new KeyTrigger(KeyInput.KEY_A) :: Nil
case PlayerMovementInput.WalkForward =>
new KeyTrigger(KeyInput.KEY_W) :: Nil
case PlayerMovementInput.WalkBackward =>
new KeyTrigger(KeyInput.KEY_S) :: Nil
case PlayerMovementInput.Jump =>
new KeyTrigger(KeyInput.KEY_SPACE) :: Nil
}
def setupAnalogMovementKeys() =
inputManager.withEnumMappings(PlayerAnalogMovementInput) {
case PlayerAnalogMovementInput.TurnRight =>
Seq(new KeyTrigger(KeyInput.KEY_D))
case PlayerAnalogMovementInput.TurnLeft =>
Seq(new KeyTrigger(KeyInput.KEY_A))
}
def setupCameraKeys() =
inputManager.withEnumMappings(PlayerCameraInput) {
case PlayerCameraInput.CameraRotateLeft =>
Seq(
new KeyTrigger(KeyInput.KEY_LEFT),
new MouseAxisTrigger(MouseInput.AXIS_X, false)
)
case PlayerCameraInput.CameraRotateRight =>
Seq(
new KeyTrigger(KeyInput.KEY_RIGHT),
new MouseAxisTrigger(MouseInput.AXIS_X, true)
)
case PlayerCameraInput.CameraRotateUp =>
Seq(
new KeyTrigger(KeyInput.KEY_UP),
new MouseAxisTrigger(MouseInput.AXIS_Y, false)
)
case PlayerCameraInput.CameraRotateDown =>
Seq(
new KeyTrigger(KeyInput.KEY_DOWN),
new MouseAxisTrigger(MouseInput.AXIS_Y, true)
)
}
def cursorToggle(toggleRef: Ref[me.Task, Boolean]) =
for {
_ <- me.Task(
inputManager.withMapping(
MiscInput.ToggleCursor,
new KeyTrigger(KeyInput.KEY_Z)
)
)
_ <-
inputManager
.enumEntryObservableAction(MiscInput.ToggleCursor)
.doOnNext(action =>
action.binding match {
case MiscInput.ToggleCursor =>
if (action.value) for {
value <- toggleRef.getAndUpdate(!_)
_ <- me.Task(inputManager.setCursorVisible(value))
} yield ()
else me.Task.unit
// case _ => me.Task.unit
}
)
.completedL
} yield ()
}
def methodName(implicit enclosing: sourcecode.Enclosing) =
enclosing.value.split(" ")(0).split("""\.""").last
def playerMovementInputEventsGenerator(
inputManager: InputManager,
playerEventBus: GameEventBus[PlayerEvent]
) = {
val name = methodName
inputManager
.enumObservableAction(PlayerMovementInput)
// .dump("O")
.doOnNext { action =>
action.binding match {
case PlayerMovementInput.WalkLeft =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerMovementEvent.PlayerMovedLeft(pressed = action.value),
name
)
)
case PlayerMovementInput.WalkRight =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerMovementEvent.PlayerMovedRight(pressed = action.value),
name
)
)
case PlayerMovementInput.WalkForward =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerMovementEvent.PlayerMovedForward(pressed = action.value),
name
)
)
case PlayerMovementInput.WalkBackward =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerMovementEvent.PlayerMovedBackward(pressed = action.value),
name
)
)
case PlayerMovementInput.Jump =>
if (action.value) {
me.Task(
playerEventBus ! EventBus.Publish(
PlayerMovementEvent.PlayerJumped,
name
)
)
} else me.Task.unit
}
}
}
def generateAnalogMovementEvents(
inputManager: InputManager,
playerEventBus: GameEventBus[PlayerEvent]
) = {
// val name = "analogMovementEventsGenerator"
inputManager
.enumAnalogObservable(PlayerAnalogMovementInput)
.sample(1.millis)
// .doOnNext(analogEvent =>
// analogEvent.binding match {
// case PlayerAnalogMovementInput.TurnRight =>
// me.Task(
// playerMovementEventBus ! EventBus.Publish(
// PlayerMovementEvent.PlayerTurnedRight,
// name
// )
// )
// case PlayerAnalogMovementInput.TurnLeft =>
// me.Task(
// playerMovementEventBus ! EventBus.Publish(
// PlayerMovementEvent.PlayerTurnedLeft,
// name
// )
// )
// }
// )
}
def generateCameraEvents(
inputManager: InputManager,
playerEventBus: ActorRef[EventBus.Command[PlayerEvent]]
) = {
val name = "cameraMovementEventsGenerator"
inputManager
.enumAnalogObservable(PlayerCameraInput)
.sample(1.millis)
.doOnNext(analogEvent =>
analogEvent.binding match {
case PlayerCameraInput.CameraRotateLeft =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerCameraEvent.CameraLeft,
name
)
)
case PlayerCameraInput.CameraRotateRight =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerCameraEvent.CameraRight,
name
)
)
case PlayerCameraInput.CameraRotateUp =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerCameraEvent.CameraMovedUp,
name
)
)
case PlayerCameraInput.CameraRotateDown =>
me.Task(
playerEventBus ! EventBus.Publish(
PlayerCameraEvent.CameraMovedDown,
name
)
)
}
)
}
}