mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-13 15:16:07 +09:00
discarding the idea of baking assembledsprite onto a spritesheet; revert to the commit right before this to completely scrap the efforts
This commit is contained in:
162
src/net/torvald/spriteanimation/AssembledSpriteAnimation.kt
Normal file
162
src/net/torvald/spriteanimation/AssembledSpriteAnimation.kt
Normal file
@@ -0,0 +1,162 @@
|
||||
package net.torvald.spriteanimation
|
||||
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException
|
||||
import com.jme3.math.FastMath
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.Second
|
||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||
import net.torvald.terrarum.printStackTrace
|
||||
import net.torvald.terrarum.savegame.ByteArray64Reader
|
||||
import net.torvald.terrarum.savegame.EntryID
|
||||
import net.torvald.terrarum.savegame.SimpleFileSystem
|
||||
import net.torvald.terrarum.serialise.Common
|
||||
import net.torvald.terrarum.spriteassembler.ADProperties
|
||||
import net.torvald.terrarum.spriteassembler.AssembleFrameBase
|
||||
import net.torvald.terrarum.spriteassembler.AssembleSheetPixmap
|
||||
import java.io.InputStream
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
/**
|
||||
* This class should not be serialised; save its Animation Description Language instead.
|
||||
*
|
||||
* Created by minjaesong on 2022-03-23.
|
||||
*/
|
||||
class AssembledSpriteAnimation(
|
||||
@Transient val adp: ADProperties,
|
||||
parentActor: ActorWithBody,
|
||||
@Transient val disk: SimpleFileSystem?, // specify if the resources for the animation is contained in the disk archive
|
||||
@Transient val bodypartToFileMap: EntryID? // which file in the disk contains bodypart-to-fileid mapping for this particular instance of sprite animation
|
||||
) : SpriteAnimation(parentActor) {
|
||||
|
||||
constructor(adp: ADProperties, parentActor: ActorWithBody) : this(adp, parentActor, null, null)
|
||||
|
||||
var currentFrame = 0 // while this number is zero-based, the frame number on the ADP is one-based
|
||||
var currentAnimation = "" // e.g. ANIM_IDLE ANIM_RUN (no frame numbers!)
|
||||
set(value) {
|
||||
field = value
|
||||
currentFrame = 0
|
||||
}
|
||||
|
||||
// @Transient var init = false
|
||||
|
||||
override val currentDelay: Second
|
||||
get() = (if (overrideDelay > 0f) overrideDelay else adp.animations[currentAnimation]?.delay ?: 1f).coerceAtLeast(1f / 16f)
|
||||
|
||||
var overrideDelay = 0f // set to 0f to not use this field
|
||||
|
||||
@Transient private val res = HashMap<String, TextureRegion?>()
|
||||
|
||||
init {
|
||||
// init = true
|
||||
|
||||
val fileGetter = if (disk != null) {
|
||||
val bodypartMapping = Properties()
|
||||
bodypartMapping.load(ByteArray64Reader(disk.getFile(bodypartToFileMap!!)!!.bytes, Common.CHARSET))
|
||||
|
||||
AssembleSheetPixmap.getVirtualDiskFileGetter(bodypartMapping, disk)
|
||||
}
|
||||
else AssembleSheetPixmap.getAssetsDirFileGetter(adp)
|
||||
|
||||
adp.bodyparts.forEach { res[it] = getPartTexture(fileGetter, it) }
|
||||
}
|
||||
|
||||
private var delta = 0f
|
||||
|
||||
override fun update(delta: Float) {
|
||||
this.delta += delta
|
||||
|
||||
//println("delta accumulation: $delta, currentDelay: $currentDelay")
|
||||
|
||||
//check if it's time to advance the frame
|
||||
while (this.delta >= currentDelay) {
|
||||
// advance frame
|
||||
currentFrame = (currentFrame + 1) % (adp.animations[currentAnimation]?.frames ?: 2)
|
||||
|
||||
// discount counter
|
||||
this.delta -= currentDelay
|
||||
}
|
||||
}
|
||||
|
||||
override fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float) {
|
||||
if (parentActor.isVisible) {
|
||||
|
||||
val tx = (parentActor.hitboxTranslateX) * scale
|
||||
val txF = (parentActor.hitboxTranslateX + parentActor.baseHitboxW) * scale
|
||||
val ty = (parentActor.hitboxTranslateY + (adp.frameHeight - parentActor.baseHitboxH)) * scale
|
||||
val tyF = (parentActor.hitboxTranslateY + parentActor.baseHitboxH) * scale
|
||||
|
||||
adp.animations[currentAnimation]!!.let { theAnim ->
|
||||
val skeleton = theAnim.skeleton.joints.reversed()
|
||||
val transforms = adp.getTransform("${currentAnimation}_${1+currentFrame}")
|
||||
val bodypartOrigins = adp.bodypartJoints
|
||||
|
||||
AssembleFrameBase.makeTransformList(skeleton, transforms).forEach { (name, bodypartPos) ->
|
||||
if (false) { // inject item's image
|
||||
|
||||
}
|
||||
else {
|
||||
res[name]?.let { image ->
|
||||
val imgCentre = bodypartOrigins[name]!!.invertX()
|
||||
val drawPos = adp.origin + bodypartPos + imgCentre
|
||||
|
||||
if (flipHorizontal && flipVertical) {
|
||||
batch.draw(image,
|
||||
FastMath.floor(posX).toFloat() + txF + drawPos.x,
|
||||
FastMath.floor(posY).toFloat() + tyF + drawPos.y,
|
||||
-FastMath.floor(adp.frameWidth * scale).toFloat(),
|
||||
-FastMath.floor(adp.frameHeight * scale).toFloat()
|
||||
)
|
||||
}
|
||||
else if (flipHorizontal && !flipVertical) {
|
||||
batch.draw(image,
|
||||
FastMath.floor(posX).toFloat() + txF + drawPos.x,
|
||||
FastMath.floor(posY).toFloat() - ty + drawPos.y,
|
||||
-FastMath.floor(adp.frameWidth * scale).toFloat(),
|
||||
FastMath.floor(adp.frameHeight * scale).toFloat()
|
||||
)
|
||||
}
|
||||
else if (!flipHorizontal && flipVertical) {
|
||||
batch.draw(image,
|
||||
FastMath.floor(posX).toFloat() - tx + drawPos.x,
|
||||
FastMath.floor(posY).toFloat() + tyF + drawPos.y,
|
||||
FastMath.floor(adp.frameWidth * scale).toFloat(),
|
||||
-FastMath.floor(adp.frameHeight * scale).toFloat()
|
||||
)
|
||||
}
|
||||
else {
|
||||
batch.draw(image,
|
||||
FastMath.floor(posX).toFloat() - tx + drawPos.x,
|
||||
FastMath.floor(posY).toFloat() - ty + drawPos.y,
|
||||
FastMath.floor(adp.frameWidth * scale).toFloat(),
|
||||
FastMath.floor(adp.frameHeight * scale).toFloat()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
res.values.forEach { try { it?.texture?.dispose() } catch (_: GdxRuntimeException) {} }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun getPartTexture(getFile: (String) -> InputStream?, partName: String): TextureRegion? {
|
||||
getFile(partName)?.let {
|
||||
val bytes = it.readAllBytes()
|
||||
return TextureRegion(Texture(Pixmap(bytes, 0, bytes.size)))
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,12 +32,12 @@ interface HasAssembledSprite {
|
||||
* reassembleSprite(this.sprite, this.spriteGlow)
|
||||
* ```
|
||||
*/
|
||||
fun reassembleSprite(sprite: SpriteAnimation?, spriteGlow: SpriteAnimation? = null, item: GameItem?) {
|
||||
/*fun reassembleSprite(sprite: SpriteAnimation?, spriteGlow: SpriteAnimation? = null, item: GameItem?) {
|
||||
if (animDesc != null && sprite != null)
|
||||
_rebuild(animDesc!!, sprite, null)
|
||||
if (animDescGlow != null && spriteGlow != null)
|
||||
_rebuild(animDescGlow!!, spriteGlow, null)
|
||||
}
|
||||
}*/
|
||||
|
||||
/*fun reassembleSprite(disk: SimpleFileSystem, sprite: SpriteAnimation?, anim: ADProperties?, spriteGlow: SpriteAnimation? = null, animGlow: ADProperties? = null) {
|
||||
if (anim != null && sprite != null)
|
||||
@@ -46,7 +46,7 @@ interface HasAssembledSprite {
|
||||
_rebuild(disk, animGlow, spriteGlow)
|
||||
}*/
|
||||
|
||||
private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation, item: GameItem?) {
|
||||
/*private fun _rebuild(ad: ADProperties, sprite: SpriteAnimation, item: GameItem?) {
|
||||
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
|
||||
|
||||
val pixmap = AssembleSheetPixmap.fromAssetsDir(ad, item)
|
||||
@@ -70,7 +70,7 @@ interface HasAssembledSprite {
|
||||
sprite.nRows = newAnimDelays.size
|
||||
}
|
||||
|
||||
/*private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
|
||||
private fun _rebuild(disk: SimpleFileSystem, ad: ADProperties, sprite: SpriteAnimation) {
|
||||
// TODO injecting held item/armour pictures? Would it be AssembleSheetPixmap's job?
|
||||
|
||||
val pixmap = if (disk.getEntry(-1025) != null) AssembleSheetPixmap.fromVirtualDisk(disk, ad) else AssembleSheetPixmap.fromAssetsDir(ad)
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
/* 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.badlogic.gdx.utils.Disposable
|
||||
import com.jme3.math.FastMath
|
||||
@@ -14,8 +9,31 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
|
||||
/**
|
||||
* This class should not be serialised; save its Animation Description Language instead.
|
||||
*
|
||||
* Created by minjaesong on 2022-03-23.
|
||||
*/
|
||||
class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
abstract class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
protected abstract val currentDelay: Second
|
||||
abstract fun update(delta: Float)
|
||||
abstract fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f)
|
||||
|
||||
var flipHorizontal = false
|
||||
var flipVertical = false
|
||||
|
||||
open fun flip(horizontal: Boolean, vertical: Boolean) {
|
||||
flipHorizontal = horizontal
|
||||
flipVertical = vertical
|
||||
}
|
||||
}
|
||||
|
||||
/* Original code author: Sean Laurvick
|
||||
* This code is based on the original author's code written in Lua.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class should not be serialised; save its Animation Description Language instead.
|
||||
*/
|
||||
class SheetSpriteAnimation(parentActor: ActorWithBody) : SpriteAnimation(parentActor) {
|
||||
|
||||
internal lateinit var textureRegion: TextureRegionPack; private set
|
||||
|
||||
@@ -27,7 +45,7 @@ class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
var nRows: Int = 1
|
||||
internal set
|
||||
|
||||
private val currentDelay: Second
|
||||
override val currentDelay: Second
|
||||
get() = delays[currentRow].coerceAtLeast(1f / 16f) // animation delay cannot be too short
|
||||
|
||||
/**
|
||||
@@ -46,8 +64,7 @@ class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
|
||||
var looping = true
|
||||
private var animationRunning = true
|
||||
var flipHorizontal = false
|
||||
var flipVertical = false
|
||||
|
||||
private val visible: Boolean
|
||||
get() = parentActor.isVisible
|
||||
|
||||
@@ -57,8 +74,6 @@ class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
var cellWidth: Int = 0
|
||||
var cellHeight: Int = 0
|
||||
|
||||
var colorFilter = Color.WHITE
|
||||
|
||||
fun setSpriteImage(regionPack: TextureRegionPack) {
|
||||
textureRegion = regionPack
|
||||
|
||||
@@ -86,7 +101,7 @@ class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
nFrames = framesCount
|
||||
}
|
||||
|
||||
fun update(delta: Float) {
|
||||
override fun update(delta: Float) {
|
||||
if (animationRunning) {
|
||||
//skip this if animation is stopped
|
||||
this.delta += delta
|
||||
@@ -122,7 +137,7 @@ class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
* *
|
||||
* @param scale
|
||||
*/
|
||||
fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float = 1f) {
|
||||
override fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float) {
|
||||
assert(cellWidth > 0 || cellHeight > 0) {
|
||||
"Sprite width or height is set to zero! ($cellWidth, $cellHeight); master: $parentActor"
|
||||
}
|
||||
@@ -206,11 +221,6 @@ class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disposable {
|
||||
currentFrame = selectFrame
|
||||
}
|
||||
|
||||
fun flip(horizontal: Boolean, vertical: Boolean) {
|
||||
flipHorizontal = horizontal
|
||||
flipVertical = vertical
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
textureRegion.dispose()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user