forked from nova/jmonkey-test
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.
278 lines
8.3 KiB
278 lines
8.3 KiB
package wow.doge.mygame.subsystems.movement
|
|
|
|
import akka.actor.typed.Behavior
|
|
import akka.actor.typed.PostStop
|
|
import akka.actor.typed.scaladsl.ActorContext
|
|
import akka.actor.typed.scaladsl.Behaviors
|
|
import com.jme3.math.Vector3f
|
|
import com.jme3.renderer.Camera
|
|
import com.jme3.scene.Geometry
|
|
import com.softwaremill.quicklens._
|
|
import wow.doge.mygame.game.subsystems.movement.CanMove
|
|
import wow.doge.mygame.implicits._
|
|
import wow.doge.mygame.math.ImVector3f
|
|
|
|
final case class CardinalDirection(
|
|
left: Boolean = false,
|
|
right: Boolean = false,
|
|
up: Boolean = false,
|
|
down: Boolean = false
|
|
)
|
|
|
|
sealed trait RotateDir
|
|
object RotateDir {
|
|
case object Left extends RotateDir
|
|
case object Right extends RotateDir
|
|
}
|
|
|
|
object ImMovementActor {
|
|
sealed trait Command
|
|
case object Tick extends Command
|
|
|
|
sealed trait Movement extends Command
|
|
final case class MoveLeft(pressed: Boolean) extends Movement
|
|
final case class MoveUp(pressed: Boolean) extends Movement
|
|
final case class MoveRight(pressed: Boolean) extends Movement
|
|
final case class MoveDown(pressed: Boolean) extends Movement
|
|
case object Jump extends Movement
|
|
|
|
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(), new Vector3f)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
)(implicit cm: CanMove[T]) {
|
|
import ImMovementActor._
|
|
|
|
def receive(
|
|
state: ImMovementActor.State,
|
|
walkDirBuf: Vector3f
|
|
): Behavior[Command] =
|
|
Behaviors
|
|
.receiveMessage[Command] {
|
|
case m: Movement =>
|
|
m match {
|
|
case MoveLeft(pressed) =>
|
|
stopIfNotPressed(pressed)
|
|
receive(
|
|
state = state.modify(_.cardinalDir.left).setTo(pressed),
|
|
walkDirBuf
|
|
)
|
|
case MoveUp(pressed) =>
|
|
stopIfNotPressed(pressed)
|
|
receive(
|
|
state = state.modify(_.cardinalDir.up).setTo(pressed),
|
|
walkDirBuf
|
|
)
|
|
case MoveRight(pressed) =>
|
|
stopIfNotPressed(pressed)
|
|
receive(
|
|
state = state.modify(_.cardinalDir.right).setTo(pressed),
|
|
walkDirBuf
|
|
)
|
|
case MoveDown(pressed) =>
|
|
stopIfNotPressed(pressed)
|
|
receive(
|
|
state = state.modify(_.cardinalDir.down).setTo(pressed),
|
|
walkDirBuf
|
|
)
|
|
case Jump =>
|
|
cm.jump(movable)
|
|
Behaviors.same
|
|
}
|
|
|
|
case Tick =>
|
|
val camDir =
|
|
props.camera.getDirection().clone().normalizeLocal.multLocal(0.6f)
|
|
val camLeft =
|
|
props.camera.getLeft().clone().normalizeLocal.multLocal(0.4f)
|
|
val dir = state.cardinalDir
|
|
walkDirBuf.set(0, 0, 0)
|
|
if (dir.up) {
|
|
ctx.log.traceP("up")
|
|
walkDirBuf += camDir
|
|
}
|
|
if (dir.left) {
|
|
ctx.log.traceP("left")
|
|
walkDirBuf += camLeft
|
|
}
|
|
if (dir.right) {
|
|
ctx.log.traceP("right")
|
|
walkDirBuf += -camLeft
|
|
}
|
|
if (dir.down) {
|
|
ctx.log.traceP("down")
|
|
walkDirBuf += -camDir
|
|
}
|
|
walkDirBuf *= 25f *= (1f / 144)
|
|
cm.move(movable, walkDirBuf.immutable, 20f)
|
|
Behaviors.same
|
|
}
|
|
.receiveSignal {
|
|
case (_, PostStop) =>
|
|
ctx.log.debugP("Stopped")
|
|
Behaviors.same
|
|
}
|
|
|
|
def stopIfNotPressed(pressed: Boolean) = if (!pressed) cm.stop(movable)
|
|
|
|
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) {
|
|
ctx.log.traceP("up")
|
|
mutWalkDir += camDir
|
|
}
|
|
if (dir.left) {
|
|
ctx.log.traceP("left")
|
|
mutWalkDir += camLeft
|
|
}
|
|
if (dir.right) {
|
|
ctx.log.traceP("right")
|
|
mutWalkDir += -camLeft
|
|
}
|
|
if (dir.down) {
|
|
ctx.log.traceP("down")
|
|
mutWalkDir += -camDir
|
|
}
|
|
mutWalkDir.immutable
|
|
}
|
|
walkDir
|
|
}
|
|
}
|
|
|
|
// old/unused
|
|
object MovementActor {
|
|
sealed trait Command
|
|
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
|
|
|
|
class Props(val app: com.jme3.app.Application, val geom: Geometry)
|
|
|
|
/**
|
|
* Internal state of the actor
|
|
*
|
|
* @param cardinalDir Immutable, can be shared as is
|
|
* @param walkDirection scratch space to avoid allocations on every tick. Do not share outside the actor
|
|
*/
|
|
final case class State(
|
|
cardinalDir: CardinalDirection = CardinalDirection(),
|
|
walkDirection: Vector3f = Vector3f.UNIT_X
|
|
)
|
|
|
|
def apply(props: Props): Behavior[Command] =
|
|
Behaviors.setup(ctx => new MovementActor(ctx, props).receive(State()))
|
|
|
|
}
|
|
class MovementActor(
|
|
ctx: ActorContext[MovementActor.Command],
|
|
props: MovementActor.Props
|
|
) {
|
|
import MovementActor._
|
|
import com.softwaremill.quicklens._
|
|
def receive(state: MovementActor.State): 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 =>
|
|
val camDir =
|
|
props.app.getCamera.getDirection().clone().multLocal(0.6f)
|
|
val camLeft = props.app.getCamera.getLeft().clone().multLocal(0.4f)
|
|
val walkDir = state.walkDirection.set(0, 0, 0)
|
|
// val walkDir = new Vector3f
|
|
val dir = state.cardinalDir
|
|
if (dir.up) {
|
|
ctx.log.debugP("up")
|
|
// ctx.log.debugP(Thread.currentThread().getName())
|
|
// walkDir.addLocal(0, 0, -1)
|
|
walkDir += camDir
|
|
}
|
|
if (dir.left) {
|
|
ctx.log.debugP("left")
|
|
// walkDir.addLocal(-1, 0, 0)
|
|
walkDir.addLocal(camLeft)
|
|
}
|
|
if (dir.right) {
|
|
ctx.log.debugP("right")
|
|
// walkDir.addLocal(1, 0, 0)
|
|
walkDir.addLocal(camLeft.negateLocal())
|
|
}
|
|
if (dir.down) {
|
|
ctx.log.debugP("down")
|
|
walkDir.addLocal(camDir.negateLocal())
|
|
// walkDir.addLocal(0, 0, 1)
|
|
}
|
|
// (dir.up, dir.down, dir.left, dir.right) match {
|
|
// case (true, false, true, false) =>
|
|
// case _ =>
|
|
// }
|
|
|
|
walkDir.multLocal(2f)
|
|
|
|
// walkDir.multLocal(100f)
|
|
// .multLocal(tpf)
|
|
|
|
// val v = props.geom.getLocalTranslation()
|
|
// props.geom.setLocalTranslation(
|
|
// (v += walkDir)
|
|
// )
|
|
props.app.enqueue(new Runnable {
|
|
override def run(): Unit = {
|
|
// geom.setLocalTranslation(walkDir)
|
|
|
|
val v = props.geom.getLocalTranslation()
|
|
props.geom.setLocalTranslation(
|
|
(v += walkDir)
|
|
)
|
|
}
|
|
})
|
|
Behaviors.same
|
|
// receive(state = state.modify(_.walkDirection).setTo(walkDir))
|
|
|
|
}
|
|
}
|
|
}
|