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.
 
 

129 lines
4.3 KiB

package wow.doge.mygame.game.entities
import scala.concurrent.duration._
import akka.actor.typed.ActorRef
import akka.actor.typed.Behavior
import akka.actor.typed.LogOptions
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import akka.util.Timeout
import com.typesafe.scalalogging.Logger
import monix.eval.Task
import monix.execution.CancelableFuture
import monix.reactive.Observable
import org.slf4j.event.Level
import wow.doge.mygame.executors.Schedulers
import wow.doge.mygame.implicits._
import wow.doge.mygame.subsystems.events.PlayerCameraEvent
import wow.doge.mygame.subsystems.events.PlayerMovementEvent
import wow.doge.mygame.subsystems.movement.ImMovementActor
object PlayerMovementEventListener {
final case class State(staminaTimer: CancelableFuture[Unit])
class Props(
val movementActor: ActorRef[ImMovementActor.Command],
val statsActor: PlayerActorSupervisor.Ref,
val asyncScheduler: Schedulers.AsyncScheduler
) {
def behavior =
Behaviors.setup[PlayerMovementEvent] { ctx =>
new PlayerMovementEventListener(ctx, this)
.receive(State(CancelableFuture.unit))
}
}
}
class PlayerMovementEventListener(
ctx: ActorContext[PlayerMovementEvent],
props: PlayerMovementEventListener.Props
) {
import PlayerMovementEventListener._
import PlayerMovementEvent._
def receive(state: State): Behavior[PlayerMovementEvent] =
Behaviors.logMessages(
LogOptions()
.withLevel(Level.TRACE)
.withLogger(
Logger[PlayerMovementEventListener.type].underlying
),
Behaviors.setup[PlayerMovementEvent] { ctx =>
implicit val timeout = Timeout(1.second)
implicit val sched = ctx.system.scheduler
def makeStaminaTimer =
Task.deferAction(implicit s =>
Observable
.interval(250.millis)
.doOnNextF(_ =>
props.statsActor.askL(
PlayerActorSupervisor
.ConsumeStamina(CharacterStats.DamageStamina(1), _)
)
)
.completedL
)
def handleStamina(pressed: Boolean) =
if (pressed)
State(makeStaminaTimer.runToFuture(props.asyncScheduler.value))
else {
state.staminaTimer.cancel()
State(CancelableFuture.unit)
}
Behaviors.receiveMessage {
case PlayerMovedLeft(pressed) =>
props.movementActor ! ImMovementActor.MoveLeft(pressed)
receive(handleStamina(pressed))
case PlayerMovedRight(pressed) =>
props.movementActor ! ImMovementActor.MoveRight(pressed)
receive(handleStamina(pressed))
case PlayerMovedForward(pressed) =>
props.movementActor ! ImMovementActor.MoveUp(pressed)
receive(handleStamina(pressed))
case PlayerMovedBackward(pressed) =>
props.movementActor ! ImMovementActor.MoveDown(pressed)
receive(handleStamina(pressed))
case PlayerJumped =>
props.movementActor ! ImMovementActor.Jump
Behaviors.same
// case PlayerTurnedRight =>
// movementActor ! ImMovementActor.RotateRight
// Behaviors.same
// case PlayerTurnedLeft =>
// movementActor ! ImMovementActor.RotateLeft
// Behaviors.same
}
}
)
}
//not used
object PlayerCameraEventListener {
import PlayerCameraEvent._
def apply(playerCameraActor: ActorRef[PlayerCameraActor.Command]) =
Behaviors.logMessages(
LogOptions()
.withLevel(Level.TRACE)
.withLogger(
Logger[PlayerCameraEventListener.type].underlying
),
Behaviors.setup[PlayerCameraEvent](ctx =>
Behaviors.receiveMessagePartial {
case CameraMovedUp =>
playerCameraActor ! PlayerCameraActor.RotateUp
Behaviors.same
case CameraMovedDown =>
playerCameraActor ! PlayerCameraActor.RotateDown
Behaviors.same
case CameraLeft =>
playerCameraActor ! PlayerCameraActor.RotateLeft
Behaviors.same
case CameraRight =>
playerCameraActor ! PlayerCameraActor.RotateRight
Behaviors.same
}
)
)
}