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.
 
 

160 lines
4.5 KiB

package wow.doge.mygame.launcher
import cats.effect.concurrent.Deferred
import javafx.application.Platform
import javafx.beans.value.ObservableValue
import monix.bio.Task
import monix.catnap.CancelableF
import monix.execution.CancelablePromise
import monix.reactive.Observable
import monix.{eval => me}
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.StringProperty
import scalafx.scene.control.Button
import scalafx.stage.StageStyle
import wow.doge.mygame.executors.Schedulers
import wow.doge.mygame.implicits.JavaFXMonixObservables._
import wow.doge.mygame.utils.IOUtils._
import cats.effect.Resource
import cats.kernel.Eq
object Launcher {
sealed trait LauncherResult
object LauncherResult {
case object LaunchGame extends LauncherResult
case object Exit extends LauncherResult
implicit val eqForLR = Eq.fromUniversalEquals[LauncherResult]
}
class Props(
val schedulers: Schedulers,
val signal: Deferred[Task, LauncherResult]
) {
val create = Task(new Launcher(this))
}
}
class Launcher private (props: Launcher.Props) {
import Launcher._
private lazy val launchButton = new Button {
text = "Launch"
}
private lazy val launchAction =
launchButton
.observableAction()
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.LaunchGame)))
def testChangeObs(
obs: Observable[(ObservableValue[_ <: String], String, String)]
) =
obs
.doOnNext {
case (x, y, z) => monix.eval.Task.unit
}
// .subscribe()
private lazy val exitButton = new Button {
text = "Exit"
// text <-- testChangeObs
}
// exitButton.text.bind
StringProperty("") addListener ((_, _, _) => ())
private lazy val exitAction =
exitButton
.observableAction()
.doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit)))
private lazy val _scene =
DefaultUI.scene(launchButton, exitButton)
private lazy val _stage = new PrimaryStage {
scene = _scene
}
private def internal(startSignal: CancelablePromise[Unit]) =
new JFXApp {
stage = _stage
stage.initStyle(StageStyle.Undecorated)
// ResizeHelper.addResizeListener(stage)
startSignal.success(())
}
private lazy val sceneDragObservable = {
val mpo = _scene.observableMousePressed()
val mdo = _scene.observableMouseDragged()
mpo.concatMap(pressEvent =>
mdo.doOnNext(dragEvent =>
me.Task(pprint.log("emitted")) >>
me.Task(
_stage.setX(dragEvent.screenX - pressEvent.sceneX)
) >>
me.Task(
_stage.setY(
dragEvent.screenY - pressEvent.sceneY
)
)
)
)
}
// import cats.syntax.all._
// def init(delay: FiniteDuration = 2000.millis) =
// for {
// _ <- Task(Platform.setImplicitExit(false))
// x <- (Task.unit.start, Task.unit.start).parTupled
// fxAppStartFib <- Task(internal.main(Array.empty)).start
// _ <- Task.sleep(500.millis)
// sceneDragFib <- toIO(sceneDragObservable.completedL).start
// buttonActionsComposedFib <- toIO(
// Observable(launchAction, exitAction).merge
// .doOnNext(_ =>
// me.Task(internal.stage.close()).executeOn(props.schedulers.fx)
// )
// .completedL
// ).start
// c <- CancelableF[Task](
// fxAppStartFib.cancel >> buttonActionsComposedFib.cancel >> sceneDragFib.cancel
// )
// } yield (c)
def init =
Resource.make(for {
_ <- Task(Platform.setImplicitExit(false))
startSignal <- Task(CancelablePromise[Unit]())
delegate <- Task(internal(startSignal))
combinedFib <-
Task
.parZip2(
Task(delegate.main(Array.empty)),
Task.fromCancelablePromise(startSignal) >> toIO(
me.Task.parSequence(
List(
sceneDragObservable.completedL,
Observable(launchAction, exitAction).merge
.doOnNext(_ =>
me.Task(delegate.stage.close())
.executeOn(props.schedulers.fx)
)
.completedL
)
)
)
)
.start
c <- CancelableF[Task](
// Task(println("Cancelling")) >>
// combinedFib.cancel >>
// fxAppStartFib.cancel
// Task.unit
combinedFib.cancel
)
} yield c)(_.cancel)
}