mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-10 05:41:51 +09:00
Former-commit-id: 5f03cdbec6058f90ef1354db5ee1c6dac9755feb Former-commit-id: f132b6c4e1a51146fb7522686e24008640e88c45
186 lines
5.0 KiB
Kotlin
186 lines
5.0 KiB
Kotlin
/* Original code author: Sean Laurvick
|
|
* This code is based on the original author's code written in Lua.
|
|
*/
|
|
|
|
package net.torvald.spriteanimation
|
|
|
|
import com.jme3.math.FastMath
|
|
import net.torvald.terrarum.gameactors.ActorWithSprite
|
|
import org.newdawn.slick.Graphics
|
|
import org.newdawn.slick.Image
|
|
import org.newdawn.slick.SlickException
|
|
import org.newdawn.slick.SpriteSheet
|
|
|
|
class SpriteAnimation(val parentActor: ActorWithSprite, val cellWidth: Int, val cellHeight: Int) {
|
|
|
|
private var spriteImage: SpriteSheet? = null
|
|
var currentFrame = 0
|
|
var currentRow = 0
|
|
var nFrames: Int = 1
|
|
private set
|
|
var nRows: Int = 1
|
|
private set
|
|
var delay = 200
|
|
private var delta = 0
|
|
val looping = true
|
|
private var animationRunning = true
|
|
private var flipHorizontal = false
|
|
private var flipVertical = false
|
|
private val visible: Boolean
|
|
get() = parentActor.isVisible
|
|
|
|
private val offsetX = 0
|
|
private val offsetY = 0
|
|
|
|
private var prevScale = 1f
|
|
private var currentImage: Image? = null
|
|
|
|
/**
|
|
* Sets spritesheet.
|
|
* MUST be called AFTER setDimension.
|
|
* @param imagePath path to the sprite sheet image.
|
|
* *
|
|
* @throws SlickException
|
|
*/
|
|
fun setSpriteImage(imagePath: String) {
|
|
spriteImage = SpriteSheet(imagePath, cellWidth, cellHeight)
|
|
}
|
|
|
|
fun setSpriteImage(image: Image) {
|
|
spriteImage = SpriteSheet(image, cellWidth, cellHeight)
|
|
}
|
|
|
|
/**
|
|
* Sets sheet rows and animation frames. Will default to
|
|
* 1, 1 (still image of top left from the sheet) if not called.
|
|
* @param nRows
|
|
* *
|
|
* @param nFrames
|
|
*/
|
|
fun setRowsAndFrames(nRows: Int, nFrames: Int) {
|
|
this.nRows = nRows
|
|
this.nFrames = nFrames
|
|
}
|
|
|
|
fun update(delta: Int) {
|
|
if (animationRunning) {
|
|
//skip this if animation is stopped
|
|
this.delta += delta
|
|
|
|
//check if it's time to advance the frame
|
|
if (this.delta >= this.delay) {
|
|
//if set to not loop, keep the frame at the last frame
|
|
if (this.currentFrame == this.nFrames && !this.looping) {
|
|
this.currentFrame = this.nFrames - 1
|
|
}
|
|
|
|
//advance one frame, then reset delta counter
|
|
this.currentFrame = this.currentFrame % this.nFrames
|
|
this.delta = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Render to specific coordinates. Will assume bottom-center point as image position.
|
|
* Will round to integer.
|
|
* @param g
|
|
* *
|
|
* @param posX bottom-center point
|
|
* *
|
|
* @param posY bottom-center point
|
|
* *
|
|
* @param scale
|
|
*/
|
|
@JvmOverloads fun render(g: Graphics, posX: Float, posY: Float, scale: Float = 1f) {
|
|
if (cellWidth == 0 || cellHeight == 0) {
|
|
throw Error("Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor")
|
|
}
|
|
|
|
// Null checking
|
|
if (currentImage == null) {
|
|
currentImage = getScaledSprite(scale)
|
|
}
|
|
|
|
if (visible) {
|
|
// re-scale image if scale has been changed
|
|
if (prevScale != scale) {
|
|
currentImage = getScaledSprite(scale)
|
|
prevScale = scale
|
|
}
|
|
|
|
val flippedImage = currentImage!!.getFlippedCopy(flipHorizontal, flipVertical)
|
|
flippedImage.draw(
|
|
Math.round(posX).toFloat(),
|
|
FastMath.floor(posY).toFloat(),
|
|
FastMath.floor(cellWidth * scale).toFloat(),
|
|
FastMath.floor(cellHeight * scale).toFloat()
|
|
)
|
|
}
|
|
}
|
|
|
|
fun switchRow(newRow: Int) {
|
|
currentRow = newRow % nRows
|
|
|
|
//if beyond the frame index then reset
|
|
if (currentFrame > nFrames) {
|
|
reset()
|
|
}
|
|
}
|
|
|
|
fun setSpriteDelay(newDelay: Int) {
|
|
if (newDelay > 0) {
|
|
delay = newDelay
|
|
}
|
|
else {
|
|
throw IllegalArgumentException("Delay equal or less than zero")
|
|
}
|
|
}
|
|
|
|
fun reset() {
|
|
currentFrame = 1
|
|
}
|
|
|
|
fun start() {
|
|
//starts the animation
|
|
animationRunning = true
|
|
}
|
|
|
|
fun start(selectFrame: Int) {
|
|
//starts the animation
|
|
animationRunning = true
|
|
|
|
//optional: seleft the frame no which to start the animation
|
|
currentFrame = selectFrame
|
|
}
|
|
|
|
fun stop() {
|
|
animationRunning = false
|
|
}
|
|
|
|
fun stop(selectFrame: Int) {
|
|
animationRunning = false
|
|
|
|
currentFrame = selectFrame
|
|
}
|
|
|
|
fun flip(horizontal: Boolean, vertical: Boolean) {
|
|
flipHorizontal = horizontal
|
|
flipVertical = vertical
|
|
}
|
|
|
|
fun flippedHorizontal(): Boolean {
|
|
return flipHorizontal
|
|
}
|
|
|
|
fun flippedVertical(): Boolean {
|
|
return flipVertical
|
|
}
|
|
|
|
private fun getScaledSprite(scale: Float): Image {
|
|
val selectedImage = spriteImage!!.getSprite(currentFrame, currentRow)
|
|
selectedImage.filter = Image.FILTER_NEAREST
|
|
return selectedImage.getScaledCopy(scale)
|
|
}
|
|
}
|