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:
minjaesong
2022-03-23 17:43:56 +09:00
parent ab73511042
commit 765ece0635
21 changed files with 360 additions and 108 deletions

View 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
}
}
}

View File

@@ -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)

View File

@@ -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()
}