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.

153 lines
4.5 KiB

  1. package wow.doge.mygame.launcher
  2. import scala.concurrent.duration.FiniteDuration
  3. import scalafx.application.JFXApp
  4. import scalafx.application.JFXApp.PrimaryStage
  5. import wow.doge.mygame.executors.Schedulers
  6. import cats.effect.Resource
  7. import monix.bio.Task
  8. import scala.concurrent.duration._
  9. import javafx.application.Platform
  10. import scalafx.scene.control.Button
  11. import cats.effect.concurrent.Deferred
  12. import wow.doge.mygame.utils.IOUtils._
  13. import monix.eval.{Task => ETask}
  14. import monix.reactive.Observable
  15. import monix.bio.Fiber
  16. import scalafx.stage.StageStyle
  17. import scalafx.Includes._
  18. import wow.doge.mygame.utils.ResizeHelper
  19. import scalafx.scene.Scene
  20. import scalafx.scene.layout.VBox
  21. import wow.doge.mygame.implicits.JavaFXMonixObservables._
  22. import monix.catnap.cancelables.SingleAssignCancelableF
  23. import monix.catnap.CancelableF
  24. // import wow.doge.mygame.implicits.JavaFXMonixObservables._
  25. // import scala.language.implicitConversions
  26. // object Stage {
  27. // implicit def sfxStage2jfx(v: Stage): jfxs.Stage = if (v != null) v.delegate else null
  28. // }
  29. object Launcher {
  30. sealed trait LauncherResult
  31. object LauncherResult {
  32. case object LaunchGame extends LauncherResult
  33. case object Exit extends LauncherResult
  34. }
  35. class Props(
  36. val schedulers: Schedulers,
  37. val signal: Deferred[Task, LauncherResult]
  38. ) {
  39. // val resource2
  40. // : Resource[Task, (LauncherApp, Task[Ref[Task, Stage]], Fiber[Unit])] =
  41. // Resource.make(for {
  42. // app <- Task(new LauncherApp(this))
  43. // fib <- app.init.start
  44. // } yield ((app, app.stageRef, fib)))(_._3.cancel)
  45. val create = Task(new Launcher(this))
  46. val resource: Resource[Task, Launcher] =
  47. Resource.make(for {
  48. app <- Task(new Launcher(this))
  49. // fib <- app.init.start
  50. } yield (app))(_ => Task.unit)
  51. }
  52. }
  53. class Launcher private (props: Launcher.Props) {
  54. import Launcher._
  55. private lazy val launchButton = new Button {
  56. text = "Launch"
  57. }
  58. // private lazy val launchButtonObs =
  59. private lazy val launchAction =
  60. launchButton
  61. .observableAction()
  62. .doOnNext(_ => toTask(props.signal.complete(LauncherResult.LaunchGame)))
  63. private lazy val exitButton = new Button {
  64. text = "Exit"
  65. }
  66. // private lazy val exitButtonObs =
  67. private lazy val exitAction =
  68. exitButton
  69. .observableAction()
  70. .doOnNext(_ => toTask(props.signal.complete(LauncherResult.Exit)))
  71. private lazy val _scene =
  72. // new Scene {
  73. // content = new VBox
  74. // }
  75. DefaultUI.scene(launchButton, exitButton)
  76. private lazy val _stage = new PrimaryStage {
  77. scene = _scene
  78. }
  79. private lazy val internal = new JFXApp {
  80. stage = _stage
  81. stage.initStyle(StageStyle.Undecorated)
  82. // ResizeHelper.addResizeListener(stage)
  83. }
  84. private lazy val sceneDragObservable = {
  85. lazy val mpo = _scene.observableMousePressed()
  86. lazy val mdo = _scene.observableMouseDragged()
  87. mpo.mergeMap(pressEvent =>
  88. mdo.doOnNext(dragEvent =>
  89. ETask(
  90. _stage.setX(dragEvent.screenX - pressEvent.sceneX)
  91. ) >>
  92. ETask(
  93. _stage.setY(
  94. dragEvent.screenY - pressEvent.sceneY
  95. )
  96. )
  97. )
  98. )
  99. }
  100. // var stage = internal.stage
  101. // lazy val stageRef = Ref.of[Task, Stage](internal.stage)
  102. // stage: => PrimaryStage
  103. def init(delay: FiniteDuration = 2000.millis) =
  104. for {
  105. _ <- Task(Platform.setImplicitExit(false))
  106. fib <- Task(internal.main(Array.empty)).start
  107. _ <- Task.sleep(500.millis)
  108. // _ <- Task {
  109. // // lazy val _stage = new CustomStageBuilder()
  110. // // .setWindowTitle("CustomStage example")
  111. // // .setWindowColor("rgb(34,54,122)")
  112. // // .build()
  113. // internal.stage.scene =
  114. // DefaultUI.scene(internal.stage, launchButton, exitButton)
  115. // // _stage.setScene(DefaultUI.scene(launchButton, exitButton))
  116. // // JFXApp.Stage = _stage
  117. // }.executeOn(props.schedulers.fx)
  118. // c <- SingleAssignCancelableF[Task]
  119. sceneDragFib <- toIO(sceneDragObservable.completedL).start
  120. fib2 <- toIO(
  121. Observable(launchAction, exitAction).merge
  122. .doOnNext(_ =>
  123. ETask(internal.stage.close()).executeOn(props.schedulers.fx)
  124. )
  125. // .doOnNext(_ => toTask(fib.cancel))
  126. .completedL
  127. ).start
  128. c <- CancelableF[Task](fib.cancel >> fib2.cancel >> sceneDragFib.cancel)
  129. // _ <- Task {
  130. // internal.stage = stage
  131. // }.executeOn(props.schedulers.fx)
  132. // .delayExecution(delay)
  133. } yield (c)
  134. }