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.
 
 

176 lines
5.0 KiB

package wow.doge.mygame.subsystems.movement
import akka.actor.typed.Behavior
import akka.actor.typed.scaladsl.ActorContext
import akka.actor.typed.scaladsl.Behaviors
import com.jme3.math.Vector3f
import com.jme3.renderer.Camera
import com.softwaremill.quicklens._
import wow.doge.mygame.game.subsystems.movement.CanMove
import wow.doge.mygame.implicits._
import wow.doge.mygame.math.ImVector3f
import wow.doge.mygame.state.CardinalDirection
sealed trait RotateDir
object RotateDir {
case object Left extends RotateDir
case object Right extends RotateDir
}
object ImMovementActor {
sealed trait Command
// final case class Tick(tpf: Float) extends Command
final case object Tick 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 object Jump extends Movement
// final case object RotateRight extends Movement
// final case object RotateLeft extends Movement
final class Props(
val enqueueR: Function1[() => Unit, Unit],
// playerMovementEventBus: ActorRef[
// EventBus.Command[PlayerMovementEvent]
// ]
val camera: Camera
) {
def behavior[T: CanMove](movable: T): Behavior[Command] =
Behaviors.setup(ctx =>
new ImMovementActor(ctx, this, movable).receive(State())
)
}
/**
* Internal state of the actor
*
* @param cardinalDir The four directions the character can move
*/
final case class State(cardinalDir: CardinalDirection = CardinalDirection())
}
class ImMovementActor[T](
ctx: ActorContext[ImMovementActor.Command],
props: ImMovementActor.Props,
val movable: T
) {
import ImMovementActor._
import Methods._
def receive(
state: ImMovementActor.State
)(implicit cm: CanMove[T]): Behavior[Command] =
Behaviors.receiveMessage {
case m: Movement =>
m match {
case MovedLeft(pressed) =>
props.enqueueR(() => stopIfNotPressed(pressed, movable))
receive(state = state.modify(_.cardinalDir.left).setTo(pressed))
case MovedUp(pressed) =>
props.enqueueR(() => stopIfNotPressed(pressed, movable))
receive(state = state.modify(_.cardinalDir.up).setTo(pressed))
case MovedRight(pressed) =>
props.enqueueR(() => stopIfNotPressed(pressed, movable))
receive(state = state.modify(_.cardinalDir.right).setTo(pressed))
case MovedDown(pressed) =>
props.enqueueR(() => stopIfNotPressed(pressed, movable))
receive(state = state.modify(_.cardinalDir.down).setTo(pressed))
case Jump =>
props.enqueueR(() => cm.jump(movable))
Behaviors.same
}
case Tick =>
val walkDir =
getDirection2(state.cardinalDir, ctx.log.traceP)
// if (walkDir != ImVector3f.ZERO) {
val tmp = walkDir * 25f * (1f / 144)
props.enqueueR { () =>
cm.move(movable, tmp)
}
// }
Behaviors.same
}
def getDirection2(
cardinalDir: CardinalDirection,
debug: sourcecode.Text[String] => sourcecode.Text[String]
) = {
val camDir =
props.camera.getDirection().clone().normalizeLocal.multLocal(0.6f)
val camLeft = props.camera.getLeft().clone().normalizeLocal.multLocal(0.4f)
val dir = cardinalDir
val walkDir = {
val mutWalkDir = new Vector3f()
if (dir.up) {
debug("up")
mutWalkDir += camDir
}
if (dir.left) {
debug("left")
mutWalkDir += camLeft
}
if (dir.right) {
debug("right")
mutWalkDir += -camLeft
}
if (dir.down) {
debug("down")
mutWalkDir += -camDir
}
mutWalkDir.immutable
}
walkDir
}
}
object Methods {
def getDirection(cardinalDir: CardinalDirection, trace: String => Unit) = {
val zero = ImVector3f.Zero
val dir = cardinalDir
val walkDir = {
val mutWalkDir = new Vector3f()
if (dir.left) {
trace("left")
mutWalkDir += zero +=: new Vector3f(-1, 0, 0)
}
if (dir.right) {
trace("right")
mutWalkDir += zero +=: new Vector3f(1, 0, 0)
}
if (dir.up) {
trace("up")
mutWalkDir += zero +=: new Vector3f(0, 0, -1)
}
if (dir.down) {
trace("down")
mutWalkDir += zero +=: new Vector3f(0, 0, 1)
}
mutWalkDir.immutable
}
walkDir
}
def stopIfNotPressed[T](pressed: Boolean, movable: T)(implicit
cm: CanMove[T]
) =
if (!pressed) cm.stop(movable)
}
// props.app
// .enqueueScala { () =>
// 1
// }
// .map(println)(scala.concurrent.ExecutionContext.global)
// monix.eval.Task
// .fromFuture(
// props.app
// .enqueueScala { () =>
// 1
// }
// )
// .flatMap(i => monix.eval.Task(println(i)))
// .runToFuture(monix.execution.Scheduler.Implicits.global)