Files
Terrarum/src/net/torvald/spriteanimation/SpriteAnimation.kt
2017-07-02 00:45:57 +09:00

184 lines
5.6 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.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.jme3.math.FastMath
import net.torvald.terrarum.gameactors.ActorWithPhysics
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
class SpriteAnimation(val parentActor: ActorWithPhysics) {
private lateinit var textureRegion: TextureRegionPack
var currentFrame = 0
var currentRow = 0
var nFrames: Int = 1
private set
var nRows: Int = 1
private set
var delay = 200f
private var delta = 0f
val looping = true
private var animationRunning = true
var flipHorizontal = false
var flipVertical = false
private val visible: Boolean
get() = parentActor.isVisible
private val offsetX = 0
private val offsetY = 0
var cellWidth: Int = 0
var cellHeight: Int = 0
var colorFilter = Color.WHITE
fun setSpriteImage(regionPack: TextureRegionPack) {
textureRegion = regionPack
cellWidth = regionPack.tileW
cellHeight = regionPack.tileH
}
/**
* 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: Float) {
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 = 0f
}
}
}
/**
* 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(batch: SpriteBatch, 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")
}
if (visible) {
val region = textureRegion.get(currentRow, currentFrame)
batch.color = colorFilter
if (flipHorizontal && flipVertical) {
batch.draw(region,
Math.round(posX).toFloat() + (2f * parentActor.hitboxTranslateX * parentActor.scale.toFloat() + parentActor.hitbox.width.toFloat()),
FastMath.floor(posY).toFloat() + (2f * parentActor.hitboxTranslateY * parentActor.scale.toFloat() + parentActor.hitbox.height.toFloat()),
-FastMath.floor(cellWidth * scale).toFloat(),
-FastMath.floor(cellHeight * scale).toFloat()
)
}
else if (flipHorizontal) {
batch.draw(region,
Math.round(posX).toFloat() + (2f * parentActor.hitboxTranslateX * parentActor.scale.toFloat() + parentActor.hitbox.width.toFloat()),
FastMath.floor(posY).toFloat(),
-FastMath.floor(cellWidth * scale).toFloat(),
FastMath.floor(cellHeight * scale).toFloat()
)
}
else if (flipVertical) {
batch.draw(region,
Math.round(posX).toFloat(),
FastMath.floor(posY).toFloat() + (2f * parentActor.hitboxTranslateY * parentActor.scale.toFloat() + parentActor.hitbox.height.toFloat()),
FastMath.floor(cellWidth * scale).toFloat(),
-FastMath.floor(cellHeight * scale).toFloat()
)
}
else {
batch.draw(region,
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: Float) {
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
}
}