forked from nova/jmonkey-test
Rohan Sircar
3 years ago
34 changed files with 1292 additions and 927 deletions
-
18build.sbt
-
1project/plugins.sbt
-
17src/main/scala/wow/doge/mygame/AppError.scala
-
250src/main/scala/wow/doge/mygame/MainApp.scala
-
56src/main/scala/wow/doge/mygame/game/GameApp.scala
-
12src/main/scala/wow/doge/mygame/game/GameAppActor.scala
-
11src/main/scala/wow/doge/mygame/game/SimpleAppExt.scala
-
294src/main/scala/wow/doge/mygame/game/appstates/PlayerMovementState.scala
-
71src/main/scala/wow/doge/mygame/game/controls/CameraMovementControls.scala
-
42src/main/scala/wow/doge/mygame/game/entities/NpcActorSupervisor.scala
-
295src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor.scala
-
149src/main/scala/wow/doge/mygame/game/entities/player/PlayerActorSupervisor2.scala
-
15src/main/scala/wow/doge/mygame/game/entities/player/PlayerCameraActor.scala
-
116src/main/scala/wow/doge/mygame/game/entities/player/PlayerController.scala
-
8src/main/scala/wow/doge/mygame/game/entities/player/PlayerEventListeners.scala
-
55src/main/scala/wow/doge/mygame/game/subsystems/input/GameInputHandler.scala
-
10src/main/scala/wow/doge/mygame/game/subsystems/movement/CanMove.scala
-
296src/main/scala/wow/doge/mygame/game/subsystems/movement/MovementActor.scala
-
163src/main/scala/wow/doge/mygame/implicits/package.scala
-
6src/main/scala/wow/doge/mygame/math/ImVector3f.scala
-
64src/main/scala/wow/doge/mygame/subsystems/events/EventBus.scala
-
12src/main/scala/wow/doge/mygame/subsystems/events/Events.scala
-
29src/main/scala/wow/doge/mygame/subsystems/events/EventsModule.scala
-
18src/main/scala/wow/doge/mygame/subsystems/events/PlayerEvents.scala
-
18src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptCachingActor.scala
-
4src/main/scala/wow/doge/mygame/subsystems/scriptsystem/ScriptSystemModule.scala
-
17src/main/scala/wow/doge/mygame/types/package.scala
-
7src/main/scala/wow/doge/mygame/utils/AkkaUtils.scala
-
4src/main/scala/wow/doge/mygame/utils/GenericTimerActor.scala
-
7src/main/scala/wow/doge/mygame/utils/IOUtils.scala
-
18src/main/scala/wow/doge/mygame/utils/wrappers/jme/Node.scala
-
90src/main/scala/wow/doge/mygame/utils/wrappers/jme/PhysicsSpace.scala
-
5src/test/scala/wow/doge/mygame/ActorTimeoutTest.scala
-
41src/test/scala/wow/doge/mygame/ReaderT_Test.scala
@ -1,3 +1,2 @@ |
|||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") |
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.15.0") |
||||
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23") |
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.9.23") |
||||
addCompilerPlugin("com.olegpy" %% "better-monadic-for" % "0.3.1") |
|
@ -1,294 +0,0 @@ |
|||||
package wow.doge.mygame.state |
|
||||
|
|
||||
import scala.concurrent.duration.DurationInt |
|
||||
|
|
||||
import akka.actor.typed.ActorRef |
|
||||
import akka.actor.typed.Behavior |
|
||||
import akka.actor.typed.scaladsl.ActorContext |
|
||||
import akka.actor.typed.scaladsl.Behaviors |
|
||||
import akka.actor.typed.scaladsl.TimerScheduler |
|
||||
import com.jme3.input.InputManager |
|
||||
import com.jme3.input.KeyInput |
|
||||
import com.jme3.input.controls.KeyTrigger |
|
||||
import com.jme3.math.Vector3f |
|
||||
import com.jme3.scene.Geometry |
|
||||
import wow.doge.mygame.implicits._ |
|
||||
import wow.doge.mygame.subsystems.movement.ImMovementActor |
|
||||
|
|
||||
class PlayerMovementState( |
|
||||
// movementActor: ActorRef[MovementActor.Command], |
|
||||
// movementActorTimer: ActorRef[MovementActorTimer.Command], |
|
||||
imMovementActor: ActorRef[ImMovementActor.Command] |
|
||||
// geom: Geometry, |
|
||||
// camNode: CameraNode, |
|
||||
// playerNode: Node |
|
||||
// gameAppActor: ActorRef[GameAppActor.Command] |
|
||||
) extends MyBaseState |
|
||||
// with ActionListener |
|
||||
{ |
|
||||
|
|
||||
protected lazy val mat = MyMaterial( |
|
||||
assetManager = assetManager, |
|
||||
path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md" |
|
||||
) |
|
||||
|
|
||||
override protected def init(): Unit = { |
|
||||
|
|
||||
// setupKeys(inputManager) |
|
||||
// println("playermovementstate " + Thread.currentThread().getName()) |
|
||||
|
|
||||
// geom.setMaterial(mat) |
|
||||
|
|
||||
// camNode.setControlDir(ControlDirection.SpatialToCamera) |
|
||||
// // lazy val camNode = new CameraNode("CameraNode", simpleApp.getCamera()) |
|
||||
// // camNode.setCamera(simpleApp.getCamera()) |
|
||||
// discard { |
|
||||
// playerNode |
|
||||
// .child(camNode) |
|
||||
// .child(geom) |
|
||||
// // playerNode.children(Seq(camNode, geom)) |
|
||||
// } |
|
||||
// discard { rootNode.withChild(playerNode) } |
|
||||
// camNode.setLocalTranslation( |
|
||||
// new Vector3f(0, 1.5f, 10) |
|
||||
// ) |
|
||||
// camNode.lookAt(playerNode.getLocalTranslation(), Vector3f.UNIT_Y) |
|
||||
|
|
||||
// movementActorTimer ! MovementActorTimer.Start(geom, cam) |
|
||||
// movementActorTimer ! MovementActorTimer.Start |
|
||||
} |
|
||||
|
|
||||
override def update(tpf: Float) = { |
|
||||
// movementActor ! MovementActor.Tick(tpf, geom, cam) |
|
||||
// imMovementActor ! ImMovementActor.Tick(tpf) |
|
||||
|
|
||||
// movementActorTimer ! MovementActorTimer.Update(tpf) |
|
||||
} |
|
||||
|
|
||||
override def stop(): Unit = {} |
|
||||
// override protected def cleanup(app: Application): Unit = { |
|
||||
// // gameAppActor ! GameAppActor.Stop |
|
||||
// super.cleanup(app) |
|
||||
// } |
|
||||
|
|
||||
def setupKeys(inputManager: InputManager) = { |
|
||||
|
|
||||
inputManager |
|
||||
.withMapping( |
|
||||
"Left", |
|
||||
// new KeyTrigger(KeyInput.KEY_A), |
|
||||
new KeyTrigger(KeyInput.KEY_LEFT) |
|
||||
) |
|
||||
.withMapping( |
|
||||
"Right", |
|
||||
// new KeyTrigger(KeyInput.KEY_D), |
|
||||
new KeyTrigger(KeyInput.KEY_RIGHT) |
|
||||
) |
|
||||
.withMapping( |
|
||||
"Up", |
|
||||
// new KeyTrigger(KeyInput.KEY_W), |
|
||||
new KeyTrigger(KeyInput.KEY_UP) |
|
||||
) |
|
||||
.withMapping( |
|
||||
"Down", |
|
||||
// new KeyTrigger(KeyInput.KEY_S), |
|
||||
new KeyTrigger(KeyInput.KEY_DOWN) |
|
||||
) |
|
||||
.withMapping( |
|
||||
"Space", |
|
||||
new KeyTrigger(KeyInput.KEY_SPACE), |
|
||||
new KeyTrigger(KeyInput.KEY_H) |
|
||||
) |
|
||||
.withMapping( |
|
||||
"Reset", |
|
||||
new KeyTrigger(KeyInput.KEY_R), |
|
||||
new KeyTrigger(KeyInput.KEY_RETURN) |
|
||||
) |
|
||||
// .withListener(this, "Left") |
|
||||
// .withListener(this, "Right") |
|
||||
// .withListener(this, "Up") |
|
||||
// .withListener(this, "Down") |
|
||||
// .withListener(this, "Space") |
|
||||
// .withListener(this, "Reset") |
|
||||
} |
|
||||
|
|
||||
// def onAction(binding: String, value: Boolean, tpf: Float) = |
|
||||
// binding match { |
|
||||
// case "Left" => imMovementActor ! ImMovementActor.MovedLeft(value) |
|
||||
// case "Right" => imMovementActor ! ImMovementActor.MovedRight(value) |
|
||||
// case "Up" => imMovementActor ! ImMovementActor.MovedUp(value) |
|
||||
// case "Down" => imMovementActor ! ImMovementActor.MovedDown(value) |
|
||||
// case "Space" => |
|
||||
// case _ => |
|
||||
// } |
|
||||
|
|
||||
override protected def onEnable(): Unit = {} |
|
||||
|
|
||||
override protected def onDisable(): Unit = {} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
final case class CardinalDirection( |
|
||||
left: Boolean = false, |
|
||||
right: Boolean = false, |
|
||||
up: Boolean = false, |
|
||||
down: Boolean = false |
|
||||
) |
|
||||
|
|
||||
object MovementActor { |
|
||||
sealed trait Command |
|
||||
// final case class Tick(tpf: Float, geom: Geometry, cam: Camera) extends 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 class Props(app: com.jme3.app.Application, 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)) |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
object MovementActorTimer { |
|
||||
sealed trait Command |
|
||||
final case object Start extends Command |
|
||||
final case object Update extends Command |
|
||||
private case object Send extends Command |
|
||||
case object TimerKey |
|
||||
|
|
||||
final case class Props( |
|
||||
timers: TimerScheduler[MovementActorTimer.Command], |
|
||||
target: ActorRef[MovementActor.Command] |
|
||||
) |
|
||||
final case class State() |
|
||||
def apply(target: ActorRef[MovementActor.Command]) = |
|
||||
Behaviors.withTimers[Command] { timers => |
|
||||
new MovementActorTimer(Props(timers, target)).idle() |
|
||||
} |
|
||||
} |
|
||||
class MovementActorTimer( |
|
||||
props: MovementActorTimer.Props |
|
||||
) { |
|
||||
import MovementActorTimer._ |
|
||||
// import com.softwaremill.quicklens._ |
|
||||
|
|
||||
def idle(): Behavior[Command] = |
|
||||
Behaviors.receiveMessage { msg => |
|
||||
msg match { |
|
||||
case Start => |
|
||||
props.timers.startTimerWithFixedDelay( |
|
||||
Send, |
|
||||
10.millis |
|
||||
) |
|
||||
active() |
|
||||
case _ => Behaviors.unhandled |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
def active(): Behavior[Command] = |
|
||||
Behaviors.receiveMessage { msg => |
|
||||
msg match { |
|
||||
case Update => active() |
|
||||
case Send => |
|
||||
props.target ! MovementActor.Tick |
|
||||
Behaviors.same |
|
||||
case _ => Behaviors.unhandled |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,71 @@ |
|||||
|
package wow.doge.mygame.game.controls |
||||
|
|
||||
|
import com.jme3.math.Quaternion |
||||
|
import com.jme3.scene.Node |
||||
|
import com.jme3.scene.control.AbstractControl |
||||
|
import com.jme3.renderer.RenderManager |
||||
|
import com.jme3.renderer.ViewPort |
||||
|
import monix.reactive.Observable |
||||
|
import wow.doge.mygame.game.subsystems.input.PlayerCameraInput |
||||
|
import com.jme3.scene.Spatial |
||||
|
import monix.{eval => me} |
||||
|
import com.jme3.math.FastMath |
||||
|
import com.jme3.math.Vector3f |
||||
|
import monix.execution.Cancelable |
||||
|
import monix.execution.Scheduler |
||||
|
|
||||
|
class CameraMovementControl( |
||||
|
rotationBuf: Quaternion, |
||||
|
obs: Observable[PlayerCameraInput], |
||||
|
rotateFn: Quaternion => Unit |
||||
|
)(implicit s: Scheduler) |
||||
|
extends AbstractControl { |
||||
|
private var _event: PlayerCameraInput = null |
||||
|
private var _subscriptionToken: Cancelable = null |
||||
|
|
||||
|
override def controlUpdate(tpf: Float): Unit = |
||||
|
if (_event != null) |
||||
|
_event match { |
||||
|
case PlayerCameraInput.CameraRotateLeft => |
||||
|
val rot = rotationBuf |
||||
|
.fromAngleAxis(1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y) |
||||
|
rotateFn(rot) |
||||
|
case PlayerCameraInput.CameraRotateRight => |
||||
|
val rot = rotationBuf |
||||
|
.fromAngleAxis(-1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_Y) |
||||
|
rotateFn(rot) |
||||
|
case PlayerCameraInput.CameraRotateUp => |
||||
|
val rot = rotationBuf |
||||
|
.fromAngleAxis(-1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_X) |
||||
|
rotateFn(rot) |
||||
|
case PlayerCameraInput.CameraRotateDown => |
||||
|
val rot = rotationBuf |
||||
|
.fromAngleAxis(1 * FastMath.DEG_TO_RAD, Vector3f.UNIT_X) |
||||
|
rotateFn(rot) |
||||
|
} |
||||
|
|
||||
|
override def controlRender( |
||||
|
x$1: RenderManager, |
||||
|
x$2: ViewPort |
||||
|
): Unit = {} |
||||
|
override def setSpatial(spatial: Spatial): Unit = { |
||||
|
super.setSpatial(spatial) |
||||
|
if (this.spatial != null) |
||||
|
_subscriptionToken = |
||||
|
obs.doOnNext(event => me.Task { _event = event }).subscribe() |
||||
|
else { |
||||
|
_subscriptionToken.cancel() |
||||
|
_subscriptionToken = null |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
class FollowControl(playerNode: Node) extends AbstractControl { |
||||
|
override def controlUpdate(tpf: Float): Unit = |
||||
|
this.spatial.setLocalTranslation(playerNode.getLocalTranslation()) |
||||
|
override def controlRender( |
||||
|
rm: RenderManager, |
||||
|
vp: ViewPort |
||||
|
): Unit = {} |
||||
|
} |
@ -0,0 +1,149 @@ |
|||||
|
package wow.doge.mygame.game.entities.player |
||||
|
|
||||
|
import scala.concurrent.duration._ |
||||
|
|
||||
|
import akka.actor.typed.ActorRef |
||||
|
import akka.actor.typed.Behavior |
||||
|
import akka.actor.typed.LogOptions |
||||
|
import akka.actor.typed.PostStop |
||||
|
import akka.actor.typed.SupervisorStrategy |
||||
|
import akka.actor.typed.scaladsl.ActorContext |
||||
|
import akka.actor.typed.scaladsl.Behaviors |
||||
|
import com.typesafe.scalalogging.Logger |
||||
|
import org.slf4j.event.Level |
||||
|
import wow.doge.mygame.Dispatchers |
||||
|
import wow.doge.mygame.game.entities.PlayerCameraActor |
||||
|
import wow.doge.mygame.game.entities.PlayerCameraEventListener |
||||
|
import wow.doge.mygame.game.entities.PlayerMovementEventListener |
||||
|
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.PlayerEvent |
||||
|
import wow.doge.mygame.subsystems.events.TickEvent |
||||
|
import wow.doge.mygame.subsystems.events.TickEvent.RenderTick |
||||
|
import wow.doge.mygame.subsystems.movement.ImMovementActor |
||||
|
|
||||
|
object PlayerActorSupervisor2 { |
||||
|
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 |
||||
|
sealed trait Camera |
||||
|
case object RotateLeft extends Camera |
||||
|
case object RotateRight extends Camera |
||||
|
case object RotateUp extends Camera |
||||
|
case object RotateDown extends Camera |
||||
|
class Props( |
||||
|
val playerEventBus: GameEventBus[PlayerEvent], |
||||
|
val tickEventBus: GameEventBus[TickEvent], |
||||
|
val imMovementActorBehavior: Behavior[ImMovementActor.Command], |
||||
|
val playerCameraActorBehavior: Behavior[PlayerCameraActor.Command] |
||||
|
) { |
||||
|
def behavior = |
||||
|
Behaviors.logMessages( |
||||
|
LogOptions() |
||||
|
.withLevel(Level.TRACE) |
||||
|
.withLogger( |
||||
|
Logger[PlayerActorSupervisor2].underlying |
||||
|
), |
||||
|
Behaviors |
||||
|
.setup[Command] { ctx => |
||||
|
ctx.log.infoP("Starting PlayerActor") |
||||
|
|
||||
|
// spawn children actors |
||||
|
val movementActor = |
||||
|
ctx.spawn( |
||||
|
Behaviors |
||||
|
.supervise(imMovementActorBehavior) |
||||
|
.onFailure[Exception]( |
||||
|
SupervisorStrategy.restart.withLimit(2, 100.millis) |
||||
|
), |
||||
|
"playerMovementActor", |
||||
|
Dispatchers.jmeDispatcher |
||||
|
) |
||||
|
|
||||
|
val playerCameraActor = |
||||
|
ctx.spawn( |
||||
|
playerCameraActorBehavior, |
||||
|
"playerCameraActor", |
||||
|
Dispatchers.jmeDispatcher |
||||
|
) |
||||
|
|
||||
|
val playerCameraEl = ctx.spawn( |
||||
|
PlayerCameraEventListener(playerCameraActor), |
||||
|
"playerCameraActorEl" |
||||
|
) |
||||
|
|
||||
|
val playerMovementEl = ctx.spawn( |
||||
|
Behaviors |
||||
|
.supervise(PlayerMovementEventListener(movementActor)) |
||||
|
.onFailure[Exception]( |
||||
|
SupervisorStrategy.restart.withLimit(2, 100.millis) |
||||
|
), |
||||
|
"playerMovementEventHandler" |
||||
|
) |
||||
|
|
||||
|
val renderTickEl = { |
||||
|
val behavior: Behavior[RenderTick.type] = |
||||
|
Behaviors.setup(ctx => |
||||
|
Behaviors |
||||
|
.receiveMessage[RenderTick.type] { |
||||
|
case RenderTick => |
||||
|
movementActor ! ImMovementActor.Tick |
||||
|
// playerCameraActor ! PlayerCameraActor.Tick |
||||
|
Behaviors.same |
||||
|
} |
||||
|
.receiveSignal { |
||||
|
case (_, PostStop) => |
||||
|
ctx.log.infoP("stopped") |
||||
|
Behaviors.same |
||||
|
} |
||||
|
) |
||||
|
ctx.spawn(behavior, "playerMovementTickListener") |
||||
|
} |
||||
|
|
||||
|
//init listeners |
||||
|
playerEventBus ! EventBus.Subscribe(playerMovementEl) |
||||
|
tickEventBus ! EventBus.Subscribe(renderTickEl) |
||||
|
playerEventBus ! EventBus.Subscribe(playerCameraEl) |
||||
|
|
||||
|
new PlayerActorSupervisor2( |
||||
|
ctx, |
||||
|
this, |
||||
|
Children(movementActor) |
||||
|
).receive |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
case class Children( |
||||
|
movementActor: ActorRef[ImMovementActor.Command] |
||||
|
) |
||||
|
} |
||||
|
class PlayerActorSupervisor2( |
||||
|
ctx: ActorContext[PlayerActorSupervisor2.Command], |
||||
|
props: PlayerActorSupervisor2.Props, |
||||
|
children: PlayerActorSupervisor2.Children |
||||
|
) { |
||||
|
import PlayerActorSupervisor2._ |
||||
|
def receive = |
||||
|
Behaviors |
||||
|
.receiveMessage[Command] { |
||||
|
case m @ MoveDown(pressed) => |
||||
|
// children.movementActor ! m |
||||
|
Behaviors.same |
||||
|
case _ => |
||||
|
// children.movementActor ! ImMovementActor.MovedDown(true) |
||||
|
Behaviors.same |
||||
|
} |
||||
|
.receiveSignal { |
||||
|
case (_, PostStop) => |
||||
|
ctx.log.infoP("stopped") |
||||
|
Behaviors.same |
||||
|
} |
||||
|
} |
@ -0,0 +1,17 @@ |
|||||
|
package wow.doge.mygame |
||||
|
|
||||
|
import wow.doge.mygame.utils.wrappers.jme.AppNode2 |
||||
|
import com.softwaremill.tagging._ |
||||
|
import wow.doge.mygame.game.GameAppTags |
||||
|
import monix.execution.Scheduler |
||||
|
import io.estatico.newtype.macros.newtype |
||||
|
|
||||
|
package object types { |
||||
|
type RootNode = AppNode2 @@ GameAppTags.RootNode |
||||
|
type GuiNode = AppNode2 @@ GameAppTags.GuiNode |
||||
|
@newtype case class AsyncScheduler(value: Scheduler) |
||||
|
@newtype case class IoScheduler(value: Scheduler) |
||||
|
@newtype case class FxScheduler(value: Scheduler) |
||||
|
@newtype case class JmeScheduler(value: Scheduler) |
||||
|
@newtype case class AkkaScheduler(value: akka.actor.typed.Scheduler) |
||||
|
} |
@ -1,12 +1,17 @@ |
|||||
package wow.doge.mygame.utils |
package wow.doge.mygame.utils |
||||
|
|
||||
import monix.bio.IO |
import monix.bio.IO |
||||
|
import monix.bio.Task |
||||
|
import monix.eval.Coeval |
||||
|
|
||||
object IOUtils { |
object IOUtils { |
||||
def toTask[T](bio: monix.bio.IO[Throwable, T]) = |
|
||||
|
def toTask[T](bio: IO[Throwable, T]) = |
||||
monix.eval.Task.deferAction(implicit s => bio.to[monix.eval.Task]) |
monix.eval.Task.deferAction(implicit s => bio.to[monix.eval.Task]) |
||||
|
|
||||
def toIO[T](task: monix.eval.Task[T]) = |
def toIO[T](task: monix.eval.Task[T]) = |
||||
IO.deferAction(implicit s => IO.from(task)) |
IO.deferAction(implicit s => IO.from(task)) |
||||
|
|
||||
|
def fromCoevalEither[L, R](coeval: Coeval[Either[L, R]]) = |
||||
|
coeval.to[Task].hideErrors.rethrow |
||||
|
|
||||
} |
} |
@ -1,57 +1,91 @@ |
|||||
package wow.doge.mygame.utils.wrappers.jme |
package wow.doge.mygame.utils.wrappers.jme |
||||
|
import com.jme3.bullet.control.PhysicsControl |
||||
|
import com.jme3.bullet.joints.PhysicsJoint |
||||
import com.jme3.{bullet => jmeb} |
import com.jme3.{bullet => jmeb} |
||||
import com.jme3.{scene => jmes} |
import com.jme3.{scene => jmes} |
||||
import monix.bio.UIO |
import monix.bio.UIO |
||||
import wow.doge.mygame.implicits._ |
import wow.doge.mygame.implicits._ |
||||
|
|
||||
final class PhysicsSpace(space: jmeb.PhysicsSpace) { |
final class PhysicsSpace(space: jmeb.PhysicsSpace) { |
||||
def add(anyObject: Any) = UIO(space.add(anyObject)) |
|
||||
|
def add[T](addable: T)(implicit P: PhysicsSpaceAddable[T]) = |
||||
|
UIO(P.addToSpace(addable, space)) |
||||
|
|
||||
def remove(anyObject: Any) = |
|
||||
UIO { |
|
||||
space.remove(anyObject) |
|
||||
space |
|
||||
} |
|
||||
|
def remove(anyObject: Any) = UIO(space.remove(anyObject)) |
||||
|
|
||||
def addAll(spatial: jmes.Spatial) = UIO(space.addAll(spatial)) |
def addAll(spatial: jmes.Spatial) = UIO(space.addAll(spatial)) |
||||
|
|
||||
def removeAll(spatial: jmes.Spatial) = |
|
||||
UIO { |
|
||||
space.removeAll(spatial) |
|
||||
space |
|
||||
} |
|
||||
|
def removeAll(spatial: jmes.Spatial) = UIO(space.removeAll(spatial)) |
||||
|
|
||||
def collisionObservable = space.collisionObservable() |
def collisionObservable = space.collisionObservable() |
||||
|
|
||||
|
// space.enqueue(() => ()) |
||||
|
|
||||
def physicsTickObservable = space.physicsTickObservable() |
def physicsTickObservable = space.physicsTickObservable() |
||||
|
|
||||
|
def prePhysicsTickObservable = space.prePhysicsTickObservable() |
||||
} |
} |
||||
object PhysicsSpace { |
object PhysicsSpace { |
||||
implicit final class PhysicsSpaceOps(private val space: PhysicsSpace) |
implicit final class PhysicsSpaceOps(private val space: PhysicsSpace) |
||||
extends AnyVal { |
extends AnyVal { |
||||
def +=(anyObject: Any) = space.add(anyObject) |
|
||||
|
def +=[T: PhysicsSpaceAddable](addable: T) = space.add(addable) |
||||
|
|
||||
def :+(anyObject: Any) = { |
|
||||
space.add(anyObject) |
|
||||
space |
|
||||
} |
|
||||
def -(anyObject: Any) = { |
|
||||
space.remove(anyObject) |
|
||||
space |
|
||||
} |
|
||||
|
def :+[T: PhysicsSpaceAddable](addable: T) = |
||||
|
for { |
||||
|
_ <- space.add(addable) |
||||
|
} yield space |
||||
|
def -(anyObject: Any) = |
||||
|
for { |
||||
|
_ <- space.remove(anyObject) |
||||
|
} yield space |
||||
|
|
||||
def -=(anyObject: Any) = space.remove(anyObject) |
def -=(anyObject: Any) = space.remove(anyObject) |
||||
|
|
||||
def +=(spatial: jmes.Spatial) = space.addAll(spatial) |
def +=(spatial: jmes.Spatial) = space.addAll(spatial) |
||||
|
|
||||
def :+(spatial: jmes.Spatial) = { |
|
||||
space.addAll(spatial) |
|
||||
space |
|
||||
} |
|
||||
|
// def :+(spatial: jmes.Spatial) = { |
||||
|
// space.addAll(spatial) |
||||
|
// space |
||||
|
// } |
||||
|
|
||||
def -(spatial: jmes.Spatial) = { |
|
||||
space.removeAll(spatial) |
|
||||
space |
|
||||
} |
|
||||
|
// def -(spatial: jmes.Spatial) = { |
||||
|
// space.removeAll(spatial) |
||||
|
// space |
||||
|
// } |
||||
|
|
||||
def -=(spatial: jmes.Spatial) = space.removeAll(spatial) |
def -=(spatial: jmes.Spatial) = space.removeAll(spatial) |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
trait PhysicsSpaceAddable[-T] { |
||||
|
def addToSpace(inst: T, space: jmeb.PhysicsSpace): Unit |
||||
|
} |
||||
|
|
||||
|
object PhysicsSpaceAddable { |
||||
|
implicit val physicsSpaceAddableForPhysControl = |
||||
|
new PhysicsSpaceAddable[PhysicsControl] { |
||||
|
|
||||
|
override def addToSpace( |
||||
|
inst: PhysicsControl, |
||||
|
space: jmeb.PhysicsSpace |
||||
|
): Unit = space.add(inst) |
||||
|
|
||||
|
} |
||||
|
implicit val physicsSpaceAddableForSpatial = |
||||
|
new PhysicsSpaceAddable[jmes.Spatial] { |
||||
|
|
||||
|
override def addToSpace( |
||||
|
inst: jmes.Spatial, |
||||
|
space: jmeb.PhysicsSpace |
||||
|
): Unit = space.add(inst) |
||||
|
|
||||
|
} |
||||
|
implicit val physicsSpaceAddableForPhysJoint = |
||||
|
new PhysicsSpaceAddable[PhysicsJoint] { |
||||
|
|
||||
|
override def addToSpace( |
||||
|
inst: PhysicsJoint, |
||||
|
space: jmeb.PhysicsSpace |
||||
|
): Unit = space.add(inst) |
||||
|
|
||||
|
} |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue