From c10da7ccf9ea91c95cde84b01e02e8099159ec83 Mon Sep 17 00:00:00 2001 From: James Daly Date: Thu, 18 Jul 2019 22:24:56 -0400 Subject: [PATCH] Added a hero to the game who can move around and animates --- Builder/src/fmon/builder/MapBuilder.scala | 2 + FakeMon/src/fmon/Config.scala | 6 +- FakeMon/src/fmon/config.yaml | 2 + FakeMon/src/fmon/draw/AnimatedImageView.scala | 35 ++++++++ FakeMon/src/fmon/world/Actor.scala | 10 +++ FakeMon/src/fmon/world/ui/GameView.fxml | 5 +- FakeMon/src/fmon/world/ui/GameView.scala | 79 ++++++++++++++++++- 7 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 FakeMon/src/fmon/draw/AnimatedImageView.scala create mode 100644 FakeMon/src/fmon/world/Actor.scala diff --git a/Builder/src/fmon/builder/MapBuilder.scala b/Builder/src/fmon/builder/MapBuilder.scala index d77e08a..ce2deea 100644 --- a/Builder/src/fmon/builder/MapBuilder.scala +++ b/Builder/src/fmon/builder/MapBuilder.scala @@ -264,6 +264,8 @@ object MapBuilder { val scene: Scene = new Scene(root) primaryStage.setScene(scene) + primaryStage.width = 1280 + primaryStage.height = 800 primaryStage.show() } } diff --git a/FakeMon/src/fmon/Config.scala b/FakeMon/src/fmon/Config.scala index 455aa47..dc3ef7c 100644 --- a/FakeMon/src/fmon/Config.scala +++ b/FakeMon/src/fmon/Config.scala @@ -10,7 +10,9 @@ case class Config( val weakMult: Double, val immuneMult: Double, val maxBoost: Int, - val tileSize: Int + val tileSize: Int, + val moveSpeed: Double, + val yOffset: Int ) { } @@ -26,4 +28,6 @@ object Config { def immuneMult = config.immuneMult def maxBoost = config.maxBoost def tileSize = config.tileSize + def moveSpeed = config.moveSpeed + def yOffset = config.yOffset } \ No newline at end of file diff --git a/FakeMon/src/fmon/config.yaml b/FakeMon/src/fmon/config.yaml index 27a7cac..dfdabd1 100644 --- a/FakeMon/src/fmon/config.yaml +++ b/FakeMon/src/fmon/config.yaml @@ -7,3 +7,5 @@ immuneMult: 0.0 maxBoost: 6 newday: 02:00 tileSize: 48 +yOffset: -4 +moveSpeed: 2.0 diff --git a/FakeMon/src/fmon/draw/AnimatedImageView.scala b/FakeMon/src/fmon/draw/AnimatedImageView.scala new file mode 100644 index 0000000..a0ccdaa --- /dev/null +++ b/FakeMon/src/fmon/draw/AnimatedImageView.scala @@ -0,0 +1,35 @@ +package fmon.draw + +import scalafx.scene.image.ImageView + +import scalafx.Includes._ +import scalafx.animation.Transition +import scalafx.util.Duration + +class AnimatedImageView extends ImageView { + def this(img: Drawable, dur: Duration) { + this() + animate(img, dur) + } + + var drawable: Drawable = _ + var duration: Duration = _ + + private var animation: SpriteAnimation = _ + + def animate(img: Drawable, dur: Duration) { + drawable = img + duration = dur + animation = new SpriteAnimation(this, drawable, duration) + animation.cycleCount = Transition.Indefinite + animation.play() + } + + def pause(): Unit = animation.pause() + def play(): Unit = animation.play() + def playFromStart(): Unit = animation.playFromStart() + def stop(): Unit = { + animation.stop() + animation.interpolate(0) + } +} \ No newline at end of file diff --git a/FakeMon/src/fmon/world/Actor.scala b/FakeMon/src/fmon/world/Actor.scala new file mode 100644 index 0000000..44d268f --- /dev/null +++ b/FakeMon/src/fmon/world/Actor.scala @@ -0,0 +1,10 @@ +package fmon.world + +import fmon.draw._ + +class Actor(val sprite: Sprite, var x: Double, var y: Double) { + def pose: String = sprite.pose + def pose_=(p: String) = { + sprite.pose = p + } +} \ No newline at end of file diff --git a/FakeMon/src/fmon/world/ui/GameView.fxml b/FakeMon/src/fmon/world/ui/GameView.fxml index 4944f2c..5943167 100644 --- a/FakeMon/src/fmon/world/ui/GameView.fxml +++ b/FakeMon/src/fmon/world/ui/GameView.fxml @@ -1,16 +1,17 @@ + - - + + diff --git a/FakeMon/src/fmon/world/ui/GameView.scala b/FakeMon/src/fmon/world/ui/GameView.scala index 059d8b2..3c443f9 100644 --- a/FakeMon/src/fmon/world/ui/GameView.scala +++ b/FakeMon/src/fmon/world/ui/GameView.scala @@ -7,28 +7,47 @@ import javafx.fxml.FXML import javafx.fxml.FXMLLoader import javafx.fxml.JavaFXBuilderFactory import javafx.scene.{control => jfxsc, layout => jfxsl, Parent, Scene} +import javafx.scene.input.KeyEvent import javafx.stage.Stage import scalafx.Includes._ +import scalafx.animation.AnimationTimer import scalafx.beans.property._ import scalafx.collections.ObservableBuffer import scalafx.scene.control._ import scalafx.scene.image.ImageView -import scalafx.scene.input.MouseEvent +import scalafx.scene.input.{KeyCode, MouseEvent} import scalafx.scene.paint.Color import scalafx.scene.layout._ import scalafx.stage.FileChooser import scalafx.stage.Modality +import scalafx.util.Duration import FileChooser.ExtensionFilter import fmon._ +import fmon.draw._ +import fmon.util.Direction import fmon.world._ import fmon.util.YamlHelper +import Direction._ class GameView { @FXML var scroller: jfxsc.ScrollPane = _ @FXML var background: jfxsl.TilePane = _ @FXML var doodads: jfxsl.TilePane = _ + @FXML var characterPane: jfxsl.AnchorPane = _ + + var hero: Actor = _ + var heroImg: AnimatedImageView = _ + var currDir: Option[Direction.Value] = None + + var lastTime = 0L + val timer = AnimationTimer(t => { + if (lastTime != 0L) { + act(new Duration((t - lastTime) * 0.000001)) + } + lastTime = t + }) def loadLevel(level: GameMap): Unit = { background.prefColumns = level.width @@ -43,6 +62,61 @@ class GameView { new ImageView(level.doodad(x, y).icon.croppedImage()).delegate } doodads.children ++= dtiles + + val heroFile = raw"C:\Users\James\Documents\Design\Project\Progena\Resources\characters\Actor1.png" + hero = new Actor(CharSet(new File(heroFile), 1), 5, 4) + + heroImg = new AnimatedImageView(hero.sprite, new Duration(600)) { + x = hero.x * Config.tileSize + y = hero.y * Config.tileSize + Config.yOffset + } + characterPane.children += heroImg + timer.start() + } + + def onKeyDown(k: KeyEvent): Unit = { + k.code match { + case KeyCode.W | KeyCode.Up => setDir(North) + case KeyCode.D | KeyCode.Right => setDir(East) + case KeyCode.A | KeyCode.Left => setDir(West) + case KeyCode.S | KeyCode.Down => setDir(South) + case _ => () + } + } + + def onKeyUp(k: KeyEvent): Unit = { + k.code match { + case KeyCode.W | KeyCode.Up => clearDir(North) + case KeyCode.D | KeyCode.Right => clearDir(East) + case KeyCode.A | KeyCode.Left => clearDir(West) + case KeyCode.S | KeyCode.Down => clearDir(South) + case _ => () + } + } + + def setDir(dir: Direction.Value): Unit = { + hero.pose = dir.toString() + currDir = Some(dir) + heroImg.play() + } + + def clearDir(dir: Direction.Value): Unit = { + if (currDir == Some(dir)) { + currDir = None + heroImg.stop() + } + } + + def act(dur: Duration): Unit = { + currDir match { + case Some(North) => hero.y -= dur.toSeconds() * Config.moveSpeed + case Some(East) => hero.x += dur.toSeconds() * Config.moveSpeed + case Some(West) => hero.x -= dur.toSeconds() * Config.moveSpeed + case Some(South) => hero.y += dur.toSeconds() * Config.moveSpeed + case _ => () + } + heroImg.x = hero.x * Config.tileSize + heroImg.y = hero.y * Config.tileSize } } @@ -65,6 +139,9 @@ object GameView { val scene: Scene = new Scene(root) primaryStage.setScene(scene) + primaryStage.width = 1280 + primaryStage.height = 800 + //primaryStage.maximized = true primaryStage.show() } }