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.
190 lines
5.8 KiB
190 lines
5.8 KiB
package wow.doge.mygame.game.entities
|
|
|
|
import akka.actor.typed.ActorRef
|
|
import akka.actor.typed.Scheduler
|
|
import akka.actor.typed.SpawnProtocol
|
|
import akka.util.Timeout
|
|
import com.jme3.bullet.BulletAppState
|
|
import com.jme3.bullet.control.BetterCharacterControl
|
|
import com.jme3.math.FastMath
|
|
import com.jme3.renderer.Camera
|
|
import com.jme3.scene.CameraNode
|
|
import com.jme3.scene.Geometry
|
|
import com.jme3.scene.Node
|
|
import com.jme3.scene.Spatial
|
|
import com.jme3.scene.shape.Box
|
|
import com.softwaremill.tagging._
|
|
import io.odin.Logger
|
|
import monix.bio.IO
|
|
import monix.bio.Task
|
|
import wow.doge.mygame.AppError
|
|
import wow.doge.mygame.game.GameAppTags
|
|
import wow.doge.mygame.game.SimpleAppExt
|
|
import wow.doge.mygame.implicits._
|
|
import wow.doge.mygame.math.ImVector3f
|
|
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.movement.ImMovementActor
|
|
import wow.doge.mygame.utils.AkkaUtils
|
|
import wow.doge.mygame.utils.wrappers.jme._
|
|
object PlayerControllerTags {
|
|
sealed trait PlayerTag
|
|
sealed trait PlayerCameraNode
|
|
sealed trait PlayerCameraPivotNode
|
|
}
|
|
|
|
object PlayerController {
|
|
sealed trait Error
|
|
case class CouldNotCreatePlayerModel(reason: AssetManager.Error) extends Error
|
|
|
|
class Props(
|
|
enqueueR: Function1[() => Unit, Unit],
|
|
rootNode: AppNode2 @@ GameAppTags.RootNode,
|
|
loggerL: Logger[Task],
|
|
// physicsSpace: com.jme3.bullet.PhysicsSpace,
|
|
physicsSpace: PhysicsSpace,
|
|
initialPlayerPos: ImVector3f = ImVector3f.Zero,
|
|
playerEventBus: GameEventBus[PlayerEvent],
|
|
playerPhysicsControl: BetterCharacterControl,
|
|
// appScheduler: monix.execution.Scheduler,
|
|
playerNode: Node @@ PlayerControllerTags.PlayerTag,
|
|
cameraNode: CameraNode @@ PlayerControllerTags.PlayerCameraNode,
|
|
cameraPivotNode: Node @@ PlayerControllerTags.PlayerCameraPivotNode,
|
|
tickEventBus: GameEventBus[TickEvent],
|
|
camera: Camera
|
|
)(implicit
|
|
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
timeout: Timeout,
|
|
scheduler: Scheduler
|
|
) {
|
|
val playerActorBehavior = {
|
|
val movementActorBeh = new ImMovementActor.Props(
|
|
enqueueR,
|
|
camera
|
|
).behavior(playerPhysicsControl)
|
|
val cameraActorBeh = new PlayerCameraActor.Props(
|
|
cameraPivotNode,
|
|
enqueueR,
|
|
playerNode.getWorldTranslation _
|
|
).behavior
|
|
new PlayerActorSupervisor.Props(
|
|
playerEventBus,
|
|
tickEventBus,
|
|
movementActorBeh,
|
|
cameraActorBeh
|
|
).behavior
|
|
}
|
|
val create: IO[AppError, ActorRef[PlayerActorSupervisor.Command]] =
|
|
(for {
|
|
playerActor <-
|
|
AkkaUtils.spawnActorL(playerActorBehavior, "playerActorSupervisor")
|
|
_ <- (for {
|
|
_ <- rootNode += playerNode
|
|
_ <- physicsSpace += playerNode
|
|
_ <- physicsSpace += playerPhysicsControl
|
|
_ = cameraPivotNode += cameraNode
|
|
_ <- rootNode += cameraPivotNode
|
|
} yield ()).mapError(AppError.AppNodeError)
|
|
} yield playerActor)
|
|
|
|
}
|
|
|
|
def apply(
|
|
app: SimpleAppExt,
|
|
modelPath: os.RelPath,
|
|
cam: Camera
|
|
)(assetManager: AssetManager, bulletAppState: BulletAppState) = {
|
|
val playerPos = ImVector3f.Zero
|
|
val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
|
|
.withJumpForce(ImVector3f(0, 5f, 0))
|
|
val playerNode = new Node("PlayerNode")
|
|
.withChildren(
|
|
assetManager
|
|
.loadModel(modelPath)
|
|
.asInstanceOf[Node]
|
|
.withRotate(0, FastMath.PI, 0)
|
|
)
|
|
.withLocalTranslation(playerPos)
|
|
.withControl(playerPhysicsControl)
|
|
|
|
{
|
|
bulletAppState.physicsSpace += playerNode
|
|
bulletAppState.physicsSpace += playerPhysicsControl
|
|
}
|
|
|
|
{
|
|
app.rootNode += playerNode
|
|
}
|
|
|
|
playerPhysicsControl
|
|
}
|
|
|
|
object Defaults {
|
|
def defaultMesh = {
|
|
val b = Box(1, 1, 1)
|
|
val geom = Geometry("playerGeom", b)
|
|
geom
|
|
}
|
|
// def defaultTexture(assetManager: AssetManager) =
|
|
// MyMaterial(
|
|
// assetManager = assetManager,
|
|
// path = os.rel / "Common" / "MatDefs" / "Misc" / "Unshaded.j3md"
|
|
// )
|
|
|
|
// new CameraControl(cam) {
|
|
// override def controlUpdate(tpf: Float) = {
|
|
// this.getCamera().setRotation(spatial.getWorldRotation())
|
|
// cameraPivotNode.setLocalTranslation(
|
|
// playerNode.getWorldTranslation()
|
|
// )
|
|
// this.getCamera().setLocation(spatial.getWorldTranslation())
|
|
// }
|
|
// }
|
|
|
|
def defaultCamerNode(
|
|
cam: Camera,
|
|
// playerNode: Node,
|
|
// cameraPivotNode: Node,
|
|
playerPos: ImVector3f
|
|
) =
|
|
new CameraNode("CameraNode", cam)
|
|
// .withControlDir(ControlDirection.SpatialToCamera)
|
|
.withLocalTranslation(ImVector3f(0, 1.5f, 10))
|
|
.withLookAt(playerPos, ImVector3f.UnitY)
|
|
|
|
def defaultPlayerNode(
|
|
playerPos: ImVector3f,
|
|
playerModel: Node,
|
|
// camNode: CameraNode,
|
|
playerPhysicsControl: BetterCharacterControl
|
|
) =
|
|
Node("PlayerNode")
|
|
.withChildren(playerModel)
|
|
.withLocalTranslation(playerPos)
|
|
.withControl(playerPhysicsControl)
|
|
.taggedWith[PlayerControllerTags.PlayerTag]
|
|
|
|
def defaultNpcNode(
|
|
// assetManager: AssetManager,
|
|
npcModel: Spatial,
|
|
initialPos: ImVector3f,
|
|
npcPhysicsControl: BetterCharacterControl,
|
|
npcName: String
|
|
) =
|
|
// Either
|
|
// .catchNonFatal(
|
|
Node(npcName)
|
|
.withChildren(
|
|
// defaultMesh.withMaterial(defaultTexture(assetManager))
|
|
npcModel
|
|
)
|
|
.withLocalTranslation(initialPos)
|
|
.withControl(npcPhysicsControl)
|
|
// )
|
|
|
|
def defaultPlayerPhysicsControl =
|
|
new BetterCharacterControl(1.5f, 6f, 1f)
|
|
.withJumpForce(ImVector3f(0, 5f, 0))
|
|
}
|
|
}
|