mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-06-05 22:02:54 +00:00
Fixed animation mapping.
Was previously using _00, _01, _02, etc. number suffix at end of .json file. Actual sprite index is stored as the m_Name field inside this file.
This commit is contained in:
parent
9f7e452850
commit
c973030d9d
@ -17,7 +17,7 @@ fun AnimatedSpriteImage(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val spriteManager = remember { BattleSpriteManager(context) }
|
val spriteManager = remember { BattleSpriteManager(context) }
|
||||||
val animationStateMachine = remember { DigimonAnimationStateMachine(characterId) }
|
val animationStateMachine = remember { DigimonAnimationStateMachine(characterId, context) }
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
||||||
|
|||||||
@ -4,6 +4,9 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import android.content.Context
|
||||||
|
import java.io.File
|
||||||
|
import com.google.gson.Gson
|
||||||
|
|
||||||
enum class DigimonAnimationType {
|
enum class DigimonAnimationType {
|
||||||
IDLE,
|
IDLE,
|
||||||
@ -28,7 +31,8 @@ data class AnimationState(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class DigimonAnimationStateMachine(
|
class DigimonAnimationStateMachine(
|
||||||
private val characterId: String
|
private val characterId: String,
|
||||||
|
private val context: Context
|
||||||
) {
|
) {
|
||||||
var currentAnimation by mutableStateOf<DigimonAnimationType>(DigimonAnimationType.IDLE)
|
var currentAnimation by mutableStateOf<DigimonAnimationType>(DigimonAnimationType.IDLE)
|
||||||
private set
|
private set
|
||||||
@ -39,38 +43,24 @@ class DigimonAnimationStateMachine(
|
|||||||
var isPlaying by mutableStateOf(false)
|
var isPlaying by mutableStateOf(false)
|
||||||
private set
|
private set
|
||||||
|
|
||||||
// Animation mapping - maps animation types to sprite indices
|
// Animation mapping based on m_Name values
|
||||||
// For now, we'll assume the sprite indices 0-11 correspond to the 12 animation types
|
private val mNameToAnimationType = mapOf(
|
||||||
private val animationMapping = mapOf(
|
"01" to DigimonAnimationType.IDLE,
|
||||||
DigimonAnimationType.IDLE to 0,
|
"02" to DigimonAnimationType.IDLE2,
|
||||||
DigimonAnimationType.IDLE2 to 1,
|
"03" to DigimonAnimationType.WALK,
|
||||||
DigimonAnimationType.WALK to 2,
|
"04" to DigimonAnimationType.WALK2,
|
||||||
DigimonAnimationType.WALK2 to 3,
|
"05" to DigimonAnimationType.RUN,
|
||||||
DigimonAnimationType.RUN to 4,
|
"06" to DigimonAnimationType.RUN2,
|
||||||
DigimonAnimationType.RUN2 to 5,
|
"07" to DigimonAnimationType.WORKOUT,
|
||||||
DigimonAnimationType.WORKOUT to 6,
|
"08" to DigimonAnimationType.WORKOUT2,
|
||||||
DigimonAnimationType.WORKOUT2 to 7,
|
"09" to DigimonAnimationType.HAPPY,
|
||||||
DigimonAnimationType.HAPPY to 8,
|
"10" to DigimonAnimationType.SLEEP,
|
||||||
DigimonAnimationType.SLEEP to 9,
|
"11" to DigimonAnimationType.ATTACK,
|
||||||
DigimonAnimationType.ATTACK to 10,
|
"12" to DigimonAnimationType.FLEE
|
||||||
DigimonAnimationType.FLEE to 11
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Animation frame sequences - defines which frames to cycle through for each animation
|
// Cache for sprite file mappings
|
||||||
private val animationFrameSequences = mapOf(
|
private var spriteFileMappings: Map<DigimonAnimationType, List<String>> = emptyMap()
|
||||||
DigimonAnimationType.IDLE to listOf(0, 1), // Cycle between idle frames
|
|
||||||
DigimonAnimationType.IDLE2 to listOf(1, 0), // Alternative idle cycle
|
|
||||||
DigimonAnimationType.WALK to listOf(2, 3), // Walk animation frames
|
|
||||||
DigimonAnimationType.WALK2 to listOf(3, 2), // Alternative walk cycle
|
|
||||||
DigimonAnimationType.RUN to listOf(4, 5), // Run animation frames
|
|
||||||
DigimonAnimationType.RUN2 to listOf(5, 4), // Alternative run cycle
|
|
||||||
DigimonAnimationType.WORKOUT to listOf(6, 7), // Workout animation frames
|
|
||||||
DigimonAnimationType.WORKOUT2 to listOf(7, 6), // Alternative workout cycle
|
|
||||||
DigimonAnimationType.HAPPY to listOf(8), // Single happy frame
|
|
||||||
DigimonAnimationType.SLEEP to listOf(9), // Single sleep frame
|
|
||||||
DigimonAnimationType.ATTACK to listOf(10), // Single attack frame
|
|
||||||
DigimonAnimationType.FLEE to listOf(11) // Single flee frame
|
|
||||||
)
|
|
||||||
|
|
||||||
// Animation durations for each type
|
// Animation durations for each type
|
||||||
private val animationDurations = mapOf(
|
private val animationDurations = mapOf(
|
||||||
@ -84,10 +74,65 @@ class DigimonAnimationStateMachine(
|
|||||||
DigimonAnimationType.WORKOUT2 to 300L,
|
DigimonAnimationType.WORKOUT2 to 300L,
|
||||||
DigimonAnimationType.HAPPY to 400L,
|
DigimonAnimationType.HAPPY to 400L,
|
||||||
DigimonAnimationType.SLEEP to 1000L,
|
DigimonAnimationType.SLEEP to 1000L,
|
||||||
DigimonAnimationType.ATTACK to 300L, // Longer for attack animation
|
DigimonAnimationType.ATTACK to 300L,
|
||||||
DigimonAnimationType.FLEE to 150L
|
DigimonAnimationType.FLEE to 150L
|
||||||
)
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadSpriteFileMappings()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadSpriteFileMappings() {
|
||||||
|
try {
|
||||||
|
val spriteBaseDir = File(context.filesDir, "battle_sprites/extracted_assets/sprites")
|
||||||
|
val gson = Gson()
|
||||||
|
|
||||||
|
val mappings = mutableMapOf<DigimonAnimationType, MutableList<String>>()
|
||||||
|
|
||||||
|
// Initialize all animation types
|
||||||
|
DigimonAnimationType.values().forEach { animationType ->
|
||||||
|
mappings[animationType] = mutableListOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Loading sprite mappings for character: $characterId")
|
||||||
|
|
||||||
|
// Scan all sprite files for this character
|
||||||
|
val spriteFiles = spriteBaseDir.listFiles { file ->
|
||||||
|
file.name.startsWith("${characterId}_sprite_") && file.name.endsWith(".json")
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Found ${spriteFiles?.size ?: 0} sprite files for $characterId")
|
||||||
|
|
||||||
|
spriteFiles?.forEach { spriteFile ->
|
||||||
|
println("Processing sprite file: ${spriteFile.name}")
|
||||||
|
val spriteDataJson = spriteFile.readText()
|
||||||
|
val spriteData = gson.fromJson(spriteDataJson, SpriteData::class.java)
|
||||||
|
|
||||||
|
println(" m_Name: ${spriteData.m_Name}")
|
||||||
|
|
||||||
|
// Get the animation type from m_Name
|
||||||
|
val animationType = mNameToAnimationType[spriteData.m_Name]
|
||||||
|
if (animationType != null) {
|
||||||
|
// Extract the sprite index from filename (e.g., "dim000_mon01_sprite_00.json" -> "00")
|
||||||
|
val spriteIndex = spriteFile.name.substringAfter("_sprite_").substringBefore(".json")
|
||||||
|
mappings[animationType]?.add(spriteIndex)
|
||||||
|
println(" Mapped to animation type: $animationType with sprite index: $spriteIndex")
|
||||||
|
} else {
|
||||||
|
println(" Unknown m_Name: ${spriteData.m_Name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to immutable map
|
||||||
|
spriteFileMappings = mappings.mapValues { it.value.sorted() }
|
||||||
|
|
||||||
|
println("Final sprite mappings for $characterId: $spriteFileMappings")
|
||||||
|
|
||||||
|
} catch (e: Exception) {
|
||||||
|
println("Error loading sprite file mappings: ${e.message}")
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun playAnimation(animationType: DigimonAnimationType) {
|
suspend fun playAnimation(animationType: DigimonAnimationType) {
|
||||||
if (currentAnimation == animationType && isPlaying) {
|
if (currentAnimation == animationType && isPlaying) {
|
||||||
return // Already playing this animation
|
return // Already playing this animation
|
||||||
@ -96,19 +141,27 @@ class DigimonAnimationStateMachine(
|
|||||||
currentAnimation = animationType
|
currentAnimation = animationType
|
||||||
isPlaying = true
|
isPlaying = true
|
||||||
|
|
||||||
val frameSequence = animationFrameSequences[animationType] ?: listOf(0)
|
val frameSequence = spriteFileMappings[animationType] ?: listOf("00")
|
||||||
val duration = animationDurations[animationType] ?: 100L
|
val duration = animationDurations[animationType] ?: 100L
|
||||||
|
|
||||||
|
// Ensure we have at least one frame
|
||||||
|
if (frameSequence.isEmpty()) {
|
||||||
|
println("Warning: No sprite files found for animation type $animationType")
|
||||||
|
currentSpriteIndex = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// For non-looping animations like ATTACK, play once and return to IDLE
|
// For non-looping animations like ATTACK, play once and return to IDLE
|
||||||
if (animationType == DigimonAnimationType.ATTACK) {
|
if (animationType == DigimonAnimationType.ATTACK) {
|
||||||
currentSpriteIndex = frameSequence[0]
|
currentSpriteIndex = frameSequence.firstOrNull()?.toIntOrNull() ?: 0
|
||||||
delay(duration)
|
delay(duration)
|
||||||
playAnimation(DigimonAnimationType.IDLE)
|
playAnimation(DigimonAnimationType.IDLE)
|
||||||
} else {
|
} else {
|
||||||
// For looping animations, cycle through frames
|
// For looping animations, cycle through frames
|
||||||
var frameIndex = 0
|
var frameIndex = 0
|
||||||
while (isPlaying && currentAnimation == animationType) {
|
while (isPlaying && currentAnimation == animationType) {
|
||||||
currentSpriteIndex = frameSequence[frameIndex % frameSequence.size]
|
val spriteIndex = frameSequence[frameIndex % frameSequence.size]
|
||||||
|
currentSpriteIndex = spriteIndex.toIntOrNull() ?: 0
|
||||||
delay(duration)
|
delay(duration)
|
||||||
frameIndex++
|
frameIndex++
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user