Fixed the animations to occur sequentially rather than all at once

This commit is contained in:
James Daly 2019-06-19 22:11:05 -04:00
parent e008892c13
commit 11b03b02d2
2 changed files with 89 additions and 45 deletions

View File

@ -29,8 +29,8 @@ class Game extends Application {
implicit val rng = new scala.util.Random() implicit val rng = new scala.util.Random()
val form1 = Form("Diabolo") val form1 = Form("Diabolo")
val form2 = Form("Chanilla") val form2 = Form("Chanilla")
val movepool1 = IndexedSeq(Move("eruption"), Move("willowisp"), Move("thunderbolt"), Move("thunderwave"), Move("blastburn")) val movepool1 = IndexedSeq(Move("eruption"), Move("willowisp"), Move("thunderbolt"), Move("thunderwave"), Move("thundershock"))
val movepool2 = IndexedSeq(Move("razorwind")) val movepool2 = IndexedSeq(Move("tackle"))
val p1 = TrainerID("Jaeda", Gender.Female, 0) val p1 = TrainerID("Jaeda", Gender.Female, 0)
val p2 = TrainerID("Wild Monster", Gender.Male, 0) val p2 = TrainerID("Wild Monster", Gender.Male, 0)
val party1 = new Party(p1, new MonsterPtr(Monster.generate("Allied Mon", p1, 500, form1, movepool1)), IndexedSeq()) val party1 = new Party(p1, new MonsterPtr(Monster.generate("Allied Mon", p1, 500, form1, movepool1)), IndexedSeq())

View File

@ -1,5 +1,8 @@
package fmon.battle package fmon.battle
import java.util.concurrent.locks.{Condition, ReentrantLock}
import javafx.application.Platform
import javafx.fxml.FXML import javafx.fxml.FXML
import javafx.fxml.FXMLLoader import javafx.fxml.FXMLLoader
import javafx.fxml.JavaFXBuilderFactory import javafx.fxml.JavaFXBuilderFactory
@ -8,6 +11,7 @@ import javafx.scene.image.ImageView
import scalafx.Includes._ import scalafx.Includes._
import scalafx.animation._ import scalafx.animation._
import scalafx.concurrent.Task
import scalafx.geometry.{Point2D, Pos} import scalafx.geometry.{Point2D, Pos}
import scalafx.scene.{Group, Parent} import scalafx.scene.{Group, Parent}
import scalafx.scene.control._ import scalafx.scene.control._
@ -36,6 +40,10 @@ class BattleUI extends SignalConsumer {
private var engine: BattleEngine = _ private var engine: BattleEngine = _
private var numPlaying = 0
private val lock = new ReentrantLock()
private val finishedPlaying = lock.newCondition()
def setEngine(engine: BattleEngine): Unit = { def setEngine(engine: BattleEngine): Unit = {
this.engine = engine this.engine = engine
updateUI() updateUI()
@ -51,64 +59,100 @@ class BattleUI extends SignalConsumer {
enemyMonController.update(enemy) enemyMonController.update(enemy)
} }
def requestUpdateUI(): Unit = {
val task = Task(updateUI)
Platform.runLater(task)
}
def onMove(move: Move): Unit = { def onMove(move: Move): Unit = {
implicit val rng = engine.rng implicit val rng = engine.rng
implicit val reader = engine implicit val reader = engine
val action = Action(engine.player.lead, move, engine.player.pollTarget(move, engine.player.lead, engine.enemy)) val action = Action(engine.player.lead, move, engine.player.pollTarget(move, engine.player.lead, engine.enemy))
engine.playTurn(action) val task = Task(engine.playTurn(action))
updateUI() val thread = new Thread(task)
thread.setDaemon(true)
thread.start()
} }
def !(msg: Signal): Unit = { def !(msg: Signal): Unit = {
msg match { lock.lock()
case Message(text) => messages.text = s"${messages.text()}${text}\n" try {
case DamageMsg(dmg, target, element) => playDamage(dmg, target, element) msg match {
case Message(text) => messages.text = s"${messages.text()}${text}\n"
case DamageMsg(dmg, target, element) => playDamage(dmg, target, element)
}
while (numPlaying > 0) {
finishedPlaying.await()
}
requestUpdateUI()
} catch {
case e: Exception => e.printStackTrace()
} finally {
lock.unlock()
} }
} }
private def playDamage(damage: Int, target: Monster, element: Element): Unit = { private def playDamage(damage: Int, target: Monster, element: Element): Unit = {
val r = 25 numPlaying += 1
val color = Color.AliceBlue def helper = {
val center = findCenter(target) val r = 25
val color = Color.AliceBlue
val circle = new Circle { val center = findCenter(target)
radius = r
fill = color val circle = new Circle {
} radius = r
val points = new Group((0 until 6).map(i => {
new Polygon {
points ++= Seq(-r/2, r, 0, 2*r, +r/2, r)
fill = color fill = color
transforms += new Rotate(60 * i, 0, 0, 0, Rotate.ZAxis)
} }
}): _*) val points = new Group((0 until 6).map(i => {
val label = new Label(s"${damage}") { new Polygon {
font = Font(24) points ++= Seq(-r/2, r, 0, 2*r, +r/2, r)
alignment = Pos.Center fill = color
} transforms += new Rotate(60 * i, 0, 0, 0, Rotate.ZAxis)
val group = new Group(circle, points, label)
group.translateX = center.x
group.translateY = center.y
val animation = new SequentialTransition(group, Seq(
// Fade In
new FadeTransition{
fromValue = 0.0
toValue = 1.0
duration = Duration(250)
},
// Fade Out
new FadeTransition{
fromValue = 1.0
toValue = 0.0
duration = Duration(750)
} }
)) }): _*)
animation.onFinished = handle{ val label = new Label(s"${damage}") {
animationPane.children -= group font = Font(24)
alignment = Pos.Center
}
val group = new Group(circle, points, label)
group.translateX = center.x
group.translateY = center.y
val animation = new SequentialTransition(group, Seq(
// Fade In
new FadeTransition{
fromValue = 0.0
toValue = 1.0
duration = Duration(250)
},
// Fade Out
new FadeTransition{
fromValue = 1.0
toValue = 0.0
duration = Duration(750)
}
))
animation.onFinished = handle{
animationPane.children -= group
finishPlay()
}
animation.play()
animationPane.children += group
}
val task = Task(helper)
Platform.runLater(task)
}
private def finishPlay(): Unit = {
lock.lock()
try {
numPlaying -= 1
updateUI()
finishedPlaying.signal()
} finally {
lock.unlock()
} }
animation.play()
animationPane.children += group
} }
private def findCenter(monster: Monster): Point2D = { private def findCenter(monster: Monster): Point2D = {