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.
 
 

143 lines
3.9 KiB

package wow.doge.mygame.game
import scala.collection.immutable.Queue
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import com.jme3.app.SimpleApplication
import com.jme3.app.state.AppState
import com.jme3.bullet.BulletAppState
import monix.bio.Task
import monix.execution.CancelableFuture
import monix.execution.CancelablePromise
import monix.execution.Scheduler
import monix.execution.atomic.Atomic
import wow.doge.mygame.executors.GUIExecutorService
import wow.doge.mygame.executors.Schedulers
class SimpleAppExt(
schedulers: Schedulers,
val bulletAppState: BulletAppState,
appStates: AppState*
) extends SimpleApplication(appStates: _*) {
import SimpleAppExt._
/**
* A non blocking synchronized queue using an immutable scala queue and monix's atomic class
*/
private val taskQueue2 = Atomic(Queue.empty[MyTask[_]])
private val startSignal: CancelablePromise[Unit] = CancelablePromise()
private val terminationSignal: CancelablePromise[Unit] = CancelablePromise()
var cancelToken: Option[() => Future[Unit]] = None
def started: CancelableFuture[Unit] = startSignal.future
def whenTerminated: CancelableFuture[Unit] = terminationSignal.future
// override def physicsSpace: PhysicsSpace = ???
override def simpleInitApp(): Unit = {
stateManager.attach(bulletAppState)
startSignal.success(())
}
override def simpleUpdate(tpf: Float): Unit = {}
override def stop(waitFor: Boolean): Unit =
cancelToken match {
case Some(value) =>
value().foreach { _ =>
pprint.log("Called cancel in simpleapp")
super.stop(true)
terminationSignal.success(())
}
case None =>
pprint.log("Called cancel in simpleapp")
super.stop(true)
terminationSignal.success(())
}
def enqueueFuture[T](cb: () => T): CancelableFuture[T] = {
val p = CancelablePromise[T]()
taskQueue2.transform(_ :+ MyTask(p, cb))
p.future
}
def enqueueL[T](cb: () => T): Task[T] =
Task.deferFuture(enqueueFuture(cb))
override protected def runQueuedTasks(): Unit = {
taskQueue2.transform { current =>
current.dequeueOption.fold(current) {
case (MyTask(p, cb), updated) =>
p.success(cb())
updated
}
}
super.runQueuedTasks()
}
object JMEExecutorService extends GUIExecutorService {
override def execute(command: Runnable): Unit =
enqueue(command)
}
val scheduler = Scheduler(JMEExecutorService)
}
object SimpleAppExt {
private[game] case class MyTask[T](p: CancelablePromise[T], cb: () => T)
}
// val ship = ed.createEntity()
// val mbState = stateManager().state[EntityDataState]().map(_.getEntityData())
// val mbState = Try(
// stateManager()
// .state[TestAppState]()
// .entity
// ).toOption.flatten.toRight(println("empty"))
// // .flatMap(_.entity)
// val x = mbState.flatMap(
// _.query
// .filter[TestComponent]("name", new Object())
// // .filterOr[TestEntity](
// // Filters
// // .fieldEquals(classOf[TestEntity], "", null)
// // )
// .component[Tag]()
// .component[TestComponent]()
// .result
// .toRight(println("failed"))
// )
// rootNode
// .child(geom)
// .child(geom)
// .child(geom)
// .child(geom)
// .child(geom)
// .child(geom)
// .child(geom)
// .child(geom)
// Future(println("hello"))(jmeEC(this))
// val wbActor: Future[ActorRef[Greeter.Greet]] = actorSystem.ask(
// SpawnProtocol.Spawn(
// behavior = Greeter(),
// name = "listener",
// DispatcherSelector.fromConfig("jme-dispatcher"),
// _
// )
// )
// wbActor.map(a => a.ask(Greeter.Greet("hello", _)).map(println))
// Task(Promise[T]()).flatMap { p =>
// Task(taskQueue2.transform(_ :+ MyTask(p, cb))) >>
// Task.fromCancelablePromise(p)
// }
// Task.fromCancelablePromise {
// val p = Promise[T]()
// taskQueue2.transform(_ :+ MyTask(p, cb))
// p
// }