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.
237 lines
7.3 KiB
237 lines
7.3 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 cats.implicits._
|
|
import com.jme3.asset.AssetManager
|
|
import com.jme3.bullet.BulletAppState
|
|
import com.jme3.bullet.PhysicsSpace
|
|
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.shape.Box
|
|
import com.softwaremill.tagging._
|
|
import io.odin.Logger
|
|
import monix.bio.IO
|
|
import monix.bio.Task
|
|
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.state.MyMaterial
|
|
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
|
|
|
|
object PlayerControllerTags {
|
|
sealed trait PlayerTag
|
|
sealed trait PlayerCameraNode
|
|
sealed trait PlayerCameraPivotNode
|
|
}
|
|
|
|
object PlayerController {
|
|
sealed trait Error
|
|
case class CouldNotCreatePlayerNode(reason: String) extends Error
|
|
case class GenericError(reason: String) extends Error
|
|
|
|
class Props(
|
|
enqueueR: Function1[() => Unit, Unit],
|
|
rootNode: Node @@ GameAppTags.RootNode,
|
|
loggerL: Logger[Task],
|
|
physicsSpace: PhysicsSpace,
|
|
initialPlayerPos: ImVector3f = ImVector3f.ZERO,
|
|
spawnProtocol: ActorRef[SpawnProtocol.Command],
|
|
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 timeout: Timeout, scheduler: Scheduler) {
|
|
val create: IO[Error, Unit] =
|
|
(for {
|
|
playerActor <- AkkaUtils.spawnActorL(
|
|
spawnProtocol,
|
|
"playerActorSupervisor",
|
|
new PlayerActorSupervisor.Props(
|
|
playerEventBus,
|
|
// playerCameraEventBus,
|
|
tickEventBus,
|
|
new ImMovementActor.Props(
|
|
enqueueR,
|
|
playerPhysicsControl,
|
|
camera
|
|
).behavior,
|
|
// wireWith(PlayerCameraEventListener.apply _)
|
|
// PlayerCameraEventListener()
|
|
new PlayerCameraActor.Props(
|
|
cameraPivotNode,
|
|
enqueueR,
|
|
playerNode.getWorldTranslation _
|
|
).behavior
|
|
).behavior(playerPhysicsControl)
|
|
)
|
|
_ <- Task(rootNode += playerNode)
|
|
_ <- IO {
|
|
physicsSpace += playerNode
|
|
physicsSpace += playerPhysicsControl
|
|
// rootNode += cameraNode
|
|
cameraPivotNode += cameraNode
|
|
// playerNode += cameraPivotNode
|
|
rootNode += cameraPivotNode
|
|
|
|
}
|
|
|
|
} yield ())
|
|
.onErrorHandleWith(e => IO.raiseError(GenericError(e.getMessage())))
|
|
.executeOn(appScheduler)
|
|
}
|
|
|
|
def apply(
|
|
app: SimpleAppExt,
|
|
modelPath: os.RelPath,
|
|
cam: Camera
|
|
)(assetManager: AssetManager, bulletAppState: BulletAppState) = {
|
|
lazy val playerPos = ImVector3f.ZERO
|
|
lazy val playerPhysicsControl = new BetterCharacterControl(1.5f, 6f, 1f)
|
|
.withJumpForce(ImVector3f(0, 5f, 0))
|
|
lazy 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.UNIT_Y)
|
|
|
|
def defaultPlayerNode(
|
|
assetManager: AssetManager,
|
|
modelPath: os.RelPath,
|
|
playerPos: ImVector3f,
|
|
// camNode: CameraNode,
|
|
playerPhysicsControl: BetterCharacterControl
|
|
) =
|
|
Either
|
|
.catchNonFatal(
|
|
Node("PlayerNode")
|
|
.withChildren(
|
|
// camNode,
|
|
assetManager
|
|
.loadModel(modelPath)
|
|
.asInstanceOf[Node]
|
|
.withRotate(0, FastMath.PI, 0)
|
|
)
|
|
.withLocalTranslation(playerPos)
|
|
.withControl(playerPhysicsControl)
|
|
)
|
|
.map(_.taggedWith[PlayerControllerTags.PlayerTag])
|
|
.leftMap(e => PlayerController.CouldNotCreatePlayerNode(e.getMessage()))
|
|
|
|
def defaultNpcNode(
|
|
assetManager: AssetManager,
|
|
// modelPath: os.RelPath,
|
|
initialPos: ImVector3f,
|
|
npcPhysicsControl: BetterCharacterControl,
|
|
npcName: String
|
|
) =
|
|
Either
|
|
.catchNonFatal(
|
|
Node(npcName)
|
|
.withChildren(
|
|
// assetManager
|
|
// .loadModel(modelPath)
|
|
// .asInstanceOf[Node]
|
|
// .withRotate(0, FastMath.PI, 0)
|
|
defaultMesh.withMaterial(defaultTexture(assetManager))
|
|
)
|
|
.withLocalTranslation(initialPos)
|
|
.withControl(npcPhysicsControl)
|
|
)
|
|
// .map(_.taggedWith[PlayerControllerTags.PlayerTag])
|
|
// .leftMap(e => PlayerController.CouldNotCreatePlayerNode(e.getMessage()))
|
|
|
|
def defaultPlayerPhysicsControl =
|
|
new BetterCharacterControl(1.5f, 6f, 1f)
|
|
.withJumpForce(ImVector3f(0, 5f, 0))
|
|
}
|
|
}
|
|
|
|
object Methods {}
|
|
|
|
// camNode <- IO(
|
|
// _cameraNode.getOrElse(defaultCamerNode(camera, initialPlayerPos))
|
|
// )
|
|
// playerPhysicsControl <- IO(
|
|
// _playerPhysicsControl
|
|
// .getOrElse(defaultPlayerPhysicsControl)
|
|
// .taggedWith[PlayerTag]
|
|
// )
|
|
// playerNode <- IO.fromEither(
|
|
// _playerNode.fold(
|
|
// defaultPlayerNode(
|
|
// assetManager,
|
|
// modelPath,
|
|
// initialPlayerPos,
|
|
// camNode,
|
|
// playerPhysicsControl
|
|
// )
|
|
// )(_.asRight)
|
|
// )
|