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.
 
 

92 lines
2.8 KiB

package wow.doge.mygame.state
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.Behaviors
import com.softwaremill.quicklens._
import wow.doge.mygame.implicits._
import com.jme3.renderer.Camera
import wow.doge.mygame.math.ImVector3f
trait CanMove[-A] {
def getDirection(cam: Camera, cardinalDir: CardinalDirection): ImVector3f
def move(inst: A, direction: ImVector3f): Unit
}
object ImMovementActor {
sealed trait Command
// final case class Tick(tpf: Float) extends Command
final case class Tick(tpf: Float) extends Command
sealed trait Movement extends Command
final case class MovedLeft(pressed: Boolean) extends Movement
final case class MovedUp(pressed: Boolean) extends Movement
final case class MovedRight(pressed: Boolean) extends Movement
final case class MovedDown(pressed: Boolean) extends Movement
final case class Props[T: CanMove](
app: com.jme3.app.Application,
movable: T
)
/**
* Internal state of the actor
*
* @param cardinalDir Immutable, can be shared as is
* @param walkDirection Immutable
*/
final case class State(
cardinalDir: CardinalDirection = CardinalDirection()
)
def apply[T: CanMove](props: Props[T]): Behavior[Command] =
Behaviors.setup(ctx => {
ctx.log.info("Hello from MovementActor")
new ImMovementActor(ctx, props).receive(State())
})
}
class ImMovementActor[T](
ctx: ActorContext[ImMovementActor.Command],
props: ImMovementActor.Props[T]
) {
import ImMovementActor._
def receive(
state: ImMovementActor.State
)(implicit cm: CanMove[T]): Behavior[Command] =
Behaviors.receiveMessage { msg =>
msg match {
case m: Movement =>
m match {
case MovedLeft(pressed) =>
receive(state = state.modify(_.cardinalDir.left).setTo(pressed))
case MovedUp(pressed) =>
receive(state = state.modify(_.cardinalDir.up).setTo(pressed))
case MovedRight(pressed) =>
receive(state = state.modify(_.cardinalDir.right).setTo(pressed))
case MovedDown(pressed) =>
receive(state = state.modify(_.cardinalDir.down).setTo(pressed))
}
case Tick(tpf) =>
val walkDir =
cm.getDirection(props.app.getCamera(), state.cardinalDir)
if (walkDir != ImVector3f.ZERO) {
val tmp = walkDir * 25f * tpf
// props.app.enqueue(new Runnable {
// override def run(): Unit = {
// cm.move(props.movable, tmp)
// }
// })
props.app.enqueueF {
cm.move(props.movable, tmp)
}
}
Behaviors.same
// receive(state = state.modify(_.walkDirection).setTo(walkDir))
}
}
}