mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-06-05 22:02:54 +00:00
Fixed atk sprite import bug. Readjusted sprites to load from individual files instead of full spritesheets.
This commit is contained in:
parent
fb09350825
commit
71ba5e0207
@ -13,15 +13,23 @@ fun AnimatedSpriteImage(
|
||||
characterId: String,
|
||||
animationType: DigimonAnimationType = DigimonAnimationType.IDLE,
|
||||
modifier: Modifier = Modifier,
|
||||
contentScale: ContentScale = ContentScale.Fit
|
||||
contentScale: ContentScale = ContentScale.Fit,
|
||||
reloadMappings: Boolean = false
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val spriteManager = remember { BattleSpriteManager(context) }
|
||||
val spriteManager = remember { IndividualSpriteManager(context) }
|
||||
val animationStateMachine = remember { DigimonAnimationStateMachine(characterId, context) }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
||||
|
||||
// Reload mappings when reloadMappings parameter changes
|
||||
LaunchedEffect(reloadMappings) {
|
||||
if (reloadMappings) {
|
||||
animationStateMachine.reloadMappings()
|
||||
}
|
||||
}
|
||||
|
||||
// Start the animation when the component is first created
|
||||
LaunchedEffect(characterId) {
|
||||
coroutineScope.launch {
|
||||
@ -41,17 +49,16 @@ fun AnimatedSpriteImage(
|
||||
}
|
||||
|
||||
// Update sprite when animation state changes
|
||||
LaunchedEffect(animationStateMachine.currentSpriteIndex) {
|
||||
val spriteName = animationStateMachine.getCurrentSpriteName()
|
||||
val atlasName = animationStateMachine.getCurrentAtlasName()
|
||||
LaunchedEffect(animationStateMachine.currentFrameNumber) {
|
||||
val frameNumber = animationStateMachine.getCurrentFrame()
|
||||
|
||||
println("Loading animated sprite: $spriteName from atlas: $atlasName")
|
||||
bitmap = spriteManager.loadSprite(spriteName, atlasName)
|
||||
println("Loading animated sprite frame: $frameNumber for character: $characterId")
|
||||
bitmap = spriteManager.loadSpriteFrame(characterId, frameNumber)
|
||||
|
||||
if (bitmap == null) {
|
||||
println("Failed to load animated sprite: $spriteName from atlas: $atlasName")
|
||||
println("Failed to load animated sprite frame: $frameNumber for character: $characterId")
|
||||
} else {
|
||||
println("Successfully loaded animated sprite: $spriteName from atlas: $atlasName")
|
||||
println("Successfully loaded animated sprite frame: $frameNumber for character: $characterId")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,8 +31,8 @@ class AttackSpriteManager(private val context: Context) {
|
||||
private val gson = Gson()
|
||||
private val characterDataCache = mutableMapOf<String, CharacterData>()
|
||||
|
||||
// Base path for attack textures
|
||||
private val attackTexturesPath = "battle_sprites/extracted_assets/extracted_atksprites"
|
||||
// Base path for attack textures (updated for new folder structure)
|
||||
private val attackTexturesPath = "battle_sprites/extracted_atksprites"
|
||||
|
||||
fun getAttackSprite(characterId: String, isLarge: Boolean = false): Bitmap? {
|
||||
println("AttackSpriteManager: Getting attack sprite for characterId=$characterId, isLarge=$isLarge")
|
||||
|
||||
@ -6,7 +6,6 @@ import androidx.compose.runtime.setValue
|
||||
import kotlinx.coroutines.delay
|
||||
import android.content.Context
|
||||
import java.io.File
|
||||
import com.google.gson.Gson
|
||||
|
||||
enum class DigimonAnimationType {
|
||||
IDLE,
|
||||
@ -25,7 +24,7 @@ enum class DigimonAnimationType {
|
||||
|
||||
data class AnimationState(
|
||||
val type: DigimonAnimationType,
|
||||
val spriteIndex: Int, // 00, 01, 02, etc.
|
||||
val frameNumber: Int, // 1-12 for individual PNG files
|
||||
val duration: Long = 100L, // Duration in milliseconds
|
||||
val loop: Boolean = true
|
||||
)
|
||||
@ -37,30 +36,31 @@ class DigimonAnimationStateMachine(
|
||||
var currentAnimation by mutableStateOf<DigimonAnimationType>(DigimonAnimationType.IDLE)
|
||||
private set
|
||||
|
||||
var currentSpriteIndex by mutableStateOf(0)
|
||||
var currentFrameNumber by mutableStateOf(1)
|
||||
private set
|
||||
|
||||
var isPlaying by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
// Animation mapping based on m_Name values
|
||||
private val mNameToAnimationType = mapOf(
|
||||
"01" to DigimonAnimationType.IDLE,
|
||||
"02" to DigimonAnimationType.IDLE2,
|
||||
"03" to DigimonAnimationType.WALK,
|
||||
"04" to DigimonAnimationType.WALK2,
|
||||
"05" to DigimonAnimationType.RUN,
|
||||
"06" to DigimonAnimationType.RUN2,
|
||||
"07" to DigimonAnimationType.WORKOUT,
|
||||
"08" to DigimonAnimationType.WORKOUT2,
|
||||
"09" to DigimonAnimationType.HAPPY,
|
||||
"10" to DigimonAnimationType.SLEEP,
|
||||
"11" to DigimonAnimationType.ATTACK,
|
||||
"12" to DigimonAnimationType.FLEE
|
||||
// Direct mapping of frame numbers (1-12) to animation types
|
||||
// This is based on the standard Digimon sprite frame order
|
||||
private val frameToAnimationType = mapOf(
|
||||
1 to DigimonAnimationType.IDLE,
|
||||
2 to DigimonAnimationType.IDLE2,
|
||||
3 to DigimonAnimationType.WALK,
|
||||
4 to DigimonAnimationType.WALK2,
|
||||
5 to DigimonAnimationType.RUN,
|
||||
6 to DigimonAnimationType.RUN2,
|
||||
7 to DigimonAnimationType.WORKOUT,
|
||||
8 to DigimonAnimationType.WORKOUT2,
|
||||
9 to DigimonAnimationType.HAPPY,
|
||||
10 to DigimonAnimationType.SLEEP,
|
||||
11 to DigimonAnimationType.ATTACK,
|
||||
12 to DigimonAnimationType.FLEE
|
||||
)
|
||||
|
||||
// Cache for sprite file mappings
|
||||
private var spriteFileMappings: Map<DigimonAnimationType, List<String>> = emptyMap()
|
||||
// Reverse mapping for getting frame numbers for each animation type
|
||||
private val animationTypeToFrames = frameToAnimationType.entries.groupBy({ it.value }, { it.key })
|
||||
|
||||
// Animation durations for each type
|
||||
private val animationDurations = mapOf(
|
||||
@ -79,58 +79,8 @@ class DigimonAnimationStateMachine(
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
println("Initialized DigimonAnimationStateMachine for character: $characterId")
|
||||
println("Available animation types: ${animationTypeToFrames.keys}")
|
||||
}
|
||||
|
||||
suspend fun playAnimation(animationType: DigimonAnimationType) {
|
||||
@ -141,27 +91,22 @@ class DigimonAnimationStateMachine(
|
||||
currentAnimation = animationType
|
||||
isPlaying = true
|
||||
|
||||
val frameSequence = spriteFileMappings[animationType] ?: listOf("00")
|
||||
val frameNumbers = animationTypeToFrames[animationType] ?: listOf(1)
|
||||
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
|
||||
}
|
||||
println("Playing animation: $animationType with frames: $frameNumbers")
|
||||
|
||||
// For non-looping animations like ATTACK, play once and return to IDLE
|
||||
if (animationType == DigimonAnimationType.ATTACK) {
|
||||
currentSpriteIndex = frameSequence.firstOrNull()?.toIntOrNull() ?: 0
|
||||
currentFrameNumber = frameNumbers.firstOrNull() ?: 1
|
||||
delay(duration)
|
||||
playAnimation(DigimonAnimationType.IDLE)
|
||||
} else {
|
||||
// For looping animations, cycle through frames
|
||||
var frameIndex = 0
|
||||
while (isPlaying && currentAnimation == animationType) {
|
||||
val spriteIndex = frameSequence[frameIndex % frameSequence.size]
|
||||
currentSpriteIndex = spriteIndex.toIntOrNull() ?: 0
|
||||
val frameNumber = frameNumbers[frameIndex % frameNumbers.size]
|
||||
currentFrameNumber = frameNumber
|
||||
delay(duration)
|
||||
frameIndex++
|
||||
}
|
||||
@ -177,26 +122,21 @@ class DigimonAnimationStateMachine(
|
||||
currentAnimation = DigimonAnimationType.IDLE
|
||||
isPlaying = true
|
||||
|
||||
val idleFrames = spriteFileMappings[DigimonAnimationType.IDLE] ?: listOf("00")
|
||||
|
||||
val idle2Frames = spriteFileMappings[DigimonAnimationType.HAPPY] ?: listOf("08")
|
||||
val idleFrames = animationTypeToFrames[DigimonAnimationType.IDLE] ?: listOf(1)
|
||||
val idle2Frames = animationTypeToFrames[DigimonAnimationType.IDLE2] ?: listOf(2)
|
||||
|
||||
// Combine frames for cycling idle animation
|
||||
val combinedFrames = (idleFrames + idle2Frames).distinct()
|
||||
|
||||
if (combinedFrames.isEmpty()) {
|
||||
println("Warning: No idle sprite files found")
|
||||
currentSpriteIndex = 0
|
||||
return
|
||||
}
|
||||
println("Playing idle animation with frames: $combinedFrames")
|
||||
|
||||
val duration = animationDurations[DigimonAnimationType.IDLE] ?: 500L
|
||||
|
||||
// Cycle through idle frames
|
||||
var frameIndex = 0
|
||||
while (isPlaying && currentAnimation == DigimonAnimationType.IDLE) {
|
||||
val spriteIndex = combinedFrames[frameIndex % combinedFrames.size]
|
||||
currentSpriteIndex = spriteIndex.toIntOrNull() ?: 0
|
||||
val frameNumber = combinedFrames[frameIndex % combinedFrames.size]
|
||||
currentFrameNumber = frameNumber
|
||||
delay(duration)
|
||||
frameIndex++
|
||||
}
|
||||
@ -206,11 +146,17 @@ class DigimonAnimationStateMachine(
|
||||
isPlaying = false
|
||||
}
|
||||
|
||||
fun getCurrentSpriteName(): String {
|
||||
return "${characterId}_sprite_${String.format("%02d", currentSpriteIndex)}"
|
||||
fun getCurrentFrame(): Int {
|
||||
return currentFrameNumber
|
||||
}
|
||||
|
||||
fun getCurrentAtlasName(): String {
|
||||
fun getCurrentCharacterId(): String {
|
||||
return characterId
|
||||
}
|
||||
|
||||
// Method to reload mappings (useful for testing)
|
||||
fun reloadMappings() {
|
||||
println("Reloading mappings for character: $characterId")
|
||||
// No need to reload since we use direct frame mapping
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,142 @@
|
||||
package com.github.nacabaro.vbhelper.battle
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import java.io.File
|
||||
|
||||
class IndividualSpriteManager(private val context: Context) {
|
||||
private val spriteCache = mutableMapOf<String, Bitmap>()
|
||||
|
||||
// Base directory where individual sprite PNGs are stored
|
||||
private val spriteBaseDir = File(context.filesDir, "battle_sprites/extracted_assets/sprites")
|
||||
|
||||
/**
|
||||
* Load a specific sprite frame for a character
|
||||
* @param characterId The character ID (e.g., "dim012_mon03")
|
||||
* @param frameNumber The frame number (1-12)
|
||||
* @return Bitmap of the sprite frame, or null if not found
|
||||
*/
|
||||
fun loadSpriteFrame(characterId: String, frameNumber: Int): Bitmap? {
|
||||
val cacheKey = "${characterId}_frame_${frameNumber}"
|
||||
|
||||
// Check cache first
|
||||
if (spriteCache.containsKey(cacheKey)) {
|
||||
return spriteCache[cacheKey]
|
||||
}
|
||||
|
||||
// Debug: Check if base directory exists
|
||||
if (!spriteBaseDir.exists()) {
|
||||
println("Sprite base directory does not exist: ${spriteBaseDir.absolutePath}")
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
// Construct the sprite file path
|
||||
val spriteFileName = "${characterId}_${String.format("%02d", frameNumber)}.png"
|
||||
val spriteFile = File(spriteBaseDir, "$characterId/$spriteFileName")
|
||||
|
||||
if (!spriteFile.exists()) {
|
||||
println("Sprite file not found: ${spriteFile.absolutePath}")
|
||||
return null
|
||||
}
|
||||
|
||||
// Load the PNG file directly
|
||||
val bitmap = BitmapFactory.decodeFile(spriteFile.absolutePath)
|
||||
if (bitmap == null) {
|
||||
println("Failed to decode sprite file: ${spriteFile.absolutePath}")
|
||||
return null
|
||||
}
|
||||
|
||||
println("Successfully loaded sprite frame: $spriteFileName (${bitmap.width}x${bitmap.height})")
|
||||
|
||||
// Cache the result
|
||||
spriteCache[cacheKey] = bitmap
|
||||
|
||||
return bitmap
|
||||
|
||||
} catch (e: Exception) {
|
||||
println("Error loading sprite frame: ${e.message}")
|
||||
e.printStackTrace()
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available sprite frames for a character
|
||||
* @param characterId The character ID
|
||||
* @return List of frame numbers (1-12) that exist for this character
|
||||
*/
|
||||
fun getAvailableFrames(characterId: String): List<Int> {
|
||||
try {
|
||||
val characterDir = File(spriteBaseDir, characterId)
|
||||
if (!characterDir.exists()) {
|
||||
println("Character directory not found: ${characterDir.absolutePath}")
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val spriteFiles = characterDir.listFiles { file ->
|
||||
file.name.startsWith("${characterId}_") && file.name.endsWith(".png")
|
||||
} ?: emptyArray()
|
||||
|
||||
return spriteFiles.mapNotNull { file ->
|
||||
// Extract frame number from filename (e.g., "dim012_mon03_01.png" -> 1)
|
||||
val frameNumberStr = file.name.substringAfter("_").substringBefore(".png")
|
||||
frameNumberStr.toIntOrNull()
|
||||
}.sorted()
|
||||
|
||||
} catch (e: Exception) {
|
||||
println("Error getting available frames: ${e.message}")
|
||||
e.printStackTrace()
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available characters
|
||||
* @return List of character IDs that have sprite directories
|
||||
*/
|
||||
fun getAvailableCharacters(): List<String> {
|
||||
try {
|
||||
if (!spriteBaseDir.exists()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
val characterDirs = spriteBaseDir.listFiles { file ->
|
||||
file.isDirectory && file.name.matches(Regex("dim\\d+_mon\\d+.*"))
|
||||
} ?: emptyArray()
|
||||
|
||||
return characterDirs.map { it.name }.sorted()
|
||||
|
||||
} catch (e: Exception) {
|
||||
println("Error getting available characters: ${e.message}")
|
||||
e.printStackTrace()
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the sprite cache
|
||||
*/
|
||||
fun clearCache() {
|
||||
spriteCache.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a character has sprite files
|
||||
* @param characterId The character ID to check
|
||||
* @return true if the character has sprite files, false otherwise
|
||||
*/
|
||||
fun hasCharacterSprites(characterId: String): Boolean {
|
||||
val characterDir = File(spriteBaseDir, characterId)
|
||||
if (!characterDir.exists()) {
|
||||
return false
|
||||
}
|
||||
|
||||
val spriteFiles = characterDir.listFiles { file ->
|
||||
file.name.startsWith("${characterId}_") && file.name.endsWith(".png")
|
||||
} ?: emptyArray()
|
||||
|
||||
return spriteFiles.isNotEmpty()
|
||||
}
|
||||
}
|
||||
@ -9,26 +9,90 @@ class SpriteFileManager(private val context: Context) {
|
||||
|
||||
fun copySpriteFilesToInternalStorage() {
|
||||
try {
|
||||
// Create the base directory for extracted_assets
|
||||
val extractedAssetsDir = File(context.filesDir, "battle_sprites/extracted_assets")
|
||||
if (!extractedAssetsDir.exists()) {
|
||||
extractedAssetsDir.mkdirs()
|
||||
println("Starting sprite file copy process...")
|
||||
|
||||
// Debug: List what's in the assets directory
|
||||
val assetManager = context.assets
|
||||
val battleSpritesFiles = assetManager.list("battle_sprites")
|
||||
println("battle_sprites directory in assets contains: ${battleSpritesFiles?.joinToString(", ")}")
|
||||
|
||||
val extractedAssetsFiles = assetManager.list("battle_sprites/extracted_assets")
|
||||
println("battle_sprites/extracted_assets directory in assets contains: ${extractedAssetsFiles?.joinToString(", ")}")
|
||||
|
||||
// Check specifically for extracted_atksprites in assets (now directly under battle_sprites)
|
||||
val atkspritesInAssets = assetManager.list("battle_sprites/extracted_atksprites")
|
||||
println("extracted_atksprites in assets contains: ${atkspritesInAssets?.size ?: 0} files")
|
||||
if (atkspritesInAssets != null && atkspritesInAssets.isNotEmpty()) {
|
||||
println("First few attack files in assets: ${atkspritesInAssets.take(5).joinToString(", ")}")
|
||||
}
|
||||
|
||||
// Create the base directory for extracted_digimon_stats
|
||||
val extractedStatsDir = File(context.filesDir, "battle_sprites/extracted_digimon_stats")
|
||||
if (!extractedStatsDir.exists()) {
|
||||
extractedStatsDir.mkdirs()
|
||||
// Check for extracted_battlebgs in assets (now directly under battle_sprites)
|
||||
val battlebgsInAssets = assetManager.list("battle_sprites/extracted_battlebgs")
|
||||
println("extracted_battlebgs in assets contains: ${battlebgsInAssets?.size ?: 0} files")
|
||||
if (battlebgsInAssets != null && battlebgsInAssets.isNotEmpty()) {
|
||||
println("First few battle background files in assets: ${battlebgsInAssets.take(5).joinToString(", ")}")
|
||||
}
|
||||
|
||||
// Copy extracted_assets files from assets to internal storage
|
||||
copyAssetDirectory("battle_sprites/extracted_assets", extractedAssetsDir)
|
||||
// Try to list all possible subdirectories in battle_sprites
|
||||
println("Checking all possible subdirectories in battle_sprites...")
|
||||
battleSpritesFiles?.forEach { subdir ->
|
||||
try {
|
||||
val subdirFiles = assetManager.list("battle_sprites/$subdir")
|
||||
println(" $subdir contains: ${subdirFiles?.size ?: 0} files")
|
||||
if (subdirFiles != null && subdirFiles.isNotEmpty()) {
|
||||
println(" First few files: ${subdirFiles.take(3).joinToString(", ")}")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println(" Error listing $subdir: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
// Copy extracted_digimon_stats files from assets to internal storage
|
||||
copyAssetDirectory("battle_sprites/extracted_digimon_stats", extractedStatsDir)
|
||||
// Create the base directory for battle_sprites
|
||||
val battleSpritesDir = File(context.filesDir, "battle_sprites")
|
||||
if (!battleSpritesDir.exists()) {
|
||||
battleSpritesDir.mkdirs()
|
||||
println("Created battle_sprites directory: ${battleSpritesDir.absolutePath}")
|
||||
} else {
|
||||
println("battle_sprites directory already exists: ${battleSpritesDir.absolutePath}")
|
||||
}
|
||||
|
||||
println("Sprite files copied successfully to: ${extractedAssetsDir.absolutePath}")
|
||||
println("Stats files copied successfully to: ${extractedStatsDir.absolutePath}")
|
||||
// Copy all subdirectories from battle_sprites assets to internal storage
|
||||
println("Copying all battle_sprites subdirectories...")
|
||||
battleSpritesFiles?.forEach { subdir ->
|
||||
val sourcePath = "battle_sprites/$subdir"
|
||||
val targetDir = File(battleSpritesDir, subdir)
|
||||
println("Copying $sourcePath to ${targetDir.absolutePath}")
|
||||
copyAssetDirectory(sourcePath, targetDir)
|
||||
}
|
||||
|
||||
println("Sprite files copied successfully to: ${battleSpritesDir.absolutePath}")
|
||||
|
||||
// Verify that attack sprites were copied
|
||||
val atkspritesDir = File(battleSpritesDir, "extracted_atksprites")
|
||||
if (atkspritesDir.exists()) {
|
||||
val attackFiles = atkspritesDir.listFiles()
|
||||
println("Attack sprites directory exists with ${attackFiles?.size ?: 0} files")
|
||||
if (attackFiles != null && attackFiles.isNotEmpty()) {
|
||||
println("First few attack files: ${attackFiles.take(5).map { it.name }}")
|
||||
}
|
||||
} else {
|
||||
println("WARNING: extracted_atksprites directory does not exist!")
|
||||
// List what's actually in the battle_sprites directory
|
||||
val battleSpritesContents = battleSpritesDir.listFiles()
|
||||
println("battle_sprites directory contains: ${battleSpritesContents?.map { it.name }?.joinToString(", ")}")
|
||||
}
|
||||
|
||||
// Verify that battle backgrounds were copied
|
||||
val battlebgsDir = File(battleSpritesDir, "extracted_battlebgs")
|
||||
if (battlebgsDir.exists()) {
|
||||
val bgFiles = battlebgsDir.listFiles()
|
||||
println("Battle backgrounds directory exists with ${bgFiles?.size ?: 0} files")
|
||||
if (bgFiles != null && bgFiles.isNotEmpty()) {
|
||||
println("First few battle background files: ${bgFiles.take(5).map { it.name }}")
|
||||
}
|
||||
} else {
|
||||
println("WARNING: extracted_battlebgs directory does not exist!")
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
println("Error copying sprite files: ${e.message}")
|
||||
@ -41,6 +105,9 @@ class SpriteFileManager(private val context: Context) {
|
||||
val assetManager = context.assets
|
||||
val files = assetManager.list(assetPath) ?: return
|
||||
|
||||
println("Copying asset directory: $assetPath (${files.size} items)")
|
||||
println("Files found: ${files.joinToString(", ")}")
|
||||
|
||||
for (file in files) {
|
||||
val assetFilePath = if (assetPath.isEmpty()) file else "$assetPath/$file"
|
||||
val targetFile = File(targetDir, file)
|
||||
@ -50,10 +117,12 @@ class SpriteFileManager(private val context: Context) {
|
||||
targetFile.parentFile!!.mkdirs()
|
||||
}
|
||||
|
||||
// Check if it's a directory
|
||||
// Check if it's a directory by trying to list its contents
|
||||
try {
|
||||
val subFiles = assetManager.list(assetFilePath)
|
||||
if (subFiles != null && subFiles.isNotEmpty()) {
|
||||
// It's a directory, create it and copy contents
|
||||
println("Copying subdirectory: $assetFilePath (${subFiles.size} files)")
|
||||
if (!targetFile.exists()) {
|
||||
targetFile.mkdirs()
|
||||
}
|
||||
@ -62,9 +131,36 @@ class SpriteFileManager(private val context: Context) {
|
||||
// It's a file, copy it
|
||||
copyAssetFile(assetFilePath, targetFile)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// If we can't list contents, it's probably a file
|
||||
println("Treating $assetFilePath as file (could not list contents)")
|
||||
copyAssetFile(assetFilePath, targetFile)
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling for extracted_atksprites - try to copy it directly if it wasn't found
|
||||
if (assetPath == "battle_sprites/extracted_assets") {
|
||||
println("Special handling: Checking for extracted_atksprites directory...")
|
||||
try {
|
||||
val atkspritesFiles = assetManager.list("battle_sprites/extracted_assets/extracted_atksprites")
|
||||
if (atkspritesFiles != null && atkspritesFiles.isNotEmpty()) {
|
||||
println("Found extracted_atksprites with ${atkspritesFiles.size} files")
|
||||
val atkspritesDir = File(targetDir, "extracted_atksprites")
|
||||
if (!atkspritesDir.exists()) {
|
||||
atkspritesDir.mkdirs()
|
||||
}
|
||||
copyAssetDirectory("battle_sprites/extracted_assets/extracted_atksprites", atkspritesDir)
|
||||
} else {
|
||||
println("extracted_atksprites directory not found in assets")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
println("Error checking extracted_atksprites: ${e.message}")
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
println("Error copying asset directory $assetPath: ${e.message}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,34 +180,34 @@ class SpriteFileManager(private val context: Context) {
|
||||
}
|
||||
|
||||
fun checkSpriteFilesExist(): Boolean {
|
||||
val extractedAssetsDir = File(context.filesDir, "battle_sprites/extracted_assets")
|
||||
val extractedStatsDir = File(context.filesDir, "battle_sprites/extracted_digimon_stats")
|
||||
val battleSpritesDir = File(context.filesDir, "battle_sprites")
|
||||
val extractedAssetsDir = File(battleSpritesDir, "extracted_assets")
|
||||
val extractedStatsDir = File(battleSpritesDir, "extracted_digimon_stats")
|
||||
val atkspritesDir = File(battleSpritesDir, "extracted_atksprites")
|
||||
val battlebgsDir = File(battleSpritesDir, "extracted_battlebgs")
|
||||
|
||||
val battleSpritesExist = battleSpritesDir.exists() && battleSpritesDir.listFiles()?.isNotEmpty() == true
|
||||
val assetsExist = extractedAssetsDir.exists() && extractedAssetsDir.listFiles()?.isNotEmpty() == true
|
||||
val statsExist = extractedStatsDir.exists() && extractedStatsDir.listFiles()?.isNotEmpty() == true
|
||||
val atkspritesExist = atkspritesDir.exists() && atkspritesDir.listFiles()?.isNotEmpty() == true
|
||||
val battlebgsExist = battlebgsDir.exists() && battlebgsDir.listFiles()?.isNotEmpty() == true
|
||||
|
||||
return assetsExist && statsExist
|
||||
println("Checking sprite files exist:")
|
||||
println(" battle_sprites exists: $battleSpritesExist")
|
||||
println(" extracted_assets exists: $assetsExist")
|
||||
println(" extracted_digimon_stats exists: $statsExist")
|
||||
println(" extracted_atksprites exists: $atkspritesExist")
|
||||
println(" extracted_battlebgs exists: $battlebgsExist")
|
||||
|
||||
return battleSpritesExist && assetsExist && statsExist && atkspritesExist && battlebgsExist
|
||||
}
|
||||
|
||||
fun clearSpriteFiles() {
|
||||
try {
|
||||
val extractedAssetsDir = File(context.filesDir, "battle_sprites/extracted_assets")
|
||||
val extractedStatsDir = File(context.filesDir, "battle_sprites/extracted_digimon_stats")
|
||||
|
||||
if (extractedAssetsDir.exists()) {
|
||||
deleteDirectory(extractedAssetsDir)
|
||||
println("Cleared extracted_assets directory")
|
||||
}
|
||||
|
||||
if (extractedStatsDir.exists()) {
|
||||
deleteDirectory(extractedStatsDir)
|
||||
println("Cleared extracted_digimon_stats directory")
|
||||
}
|
||||
|
||||
// Also clear the battle_sprites directory if it's empty
|
||||
val battleSpritesDir = File(context.filesDir, "battle_sprites")
|
||||
if (battleSpritesDir.exists() && battleSpritesDir.listFiles()?.isEmpty() == true) {
|
||||
battleSpritesDir.delete()
|
||||
|
||||
if (battleSpritesDir.exists()) {
|
||||
deleteDirectory(battleSpritesDir)
|
||||
println("Cleared battle_sprites directory")
|
||||
}
|
||||
|
||||
|
||||
@ -6,34 +6,33 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.github.nacabaro.vbhelper.battle.BattleSpriteManager
|
||||
|
||||
@Composable
|
||||
fun SpriteImage(
|
||||
spriteName: String,
|
||||
atlasName: String,
|
||||
characterId: String,
|
||||
frameNumber: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
contentScale: ContentScale = ContentScale.Fit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val spriteManager = remember { BattleSpriteManager(context) }
|
||||
val spriteManager = remember { IndividualSpriteManager(context) }
|
||||
|
||||
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
||||
|
||||
LaunchedEffect(spriteName, atlasName) {
|
||||
println("Loading sprite: $spriteName from atlas: $atlasName")
|
||||
bitmap = spriteManager.loadSprite(spriteName, atlasName)
|
||||
LaunchedEffect(characterId, frameNumber) {
|
||||
println("Loading sprite frame: $frameNumber for character: $characterId")
|
||||
bitmap = spriteManager.loadSpriteFrame(characterId, frameNumber)
|
||||
if (bitmap == null) {
|
||||
println("Failed to load sprite: $spriteName from atlas: $atlasName")
|
||||
println("Failed to load sprite frame: $frameNumber for character: $characterId")
|
||||
} else {
|
||||
println("Successfully loaded sprite: $spriteName from atlas: $atlasName")
|
||||
println("Successfully loaded sprite frame: $frameNumber for character: $characterId")
|
||||
}
|
||||
}
|
||||
|
||||
bitmap?.let { bmp ->
|
||||
Image(
|
||||
bitmap = bmp.asImageBitmap(),
|
||||
contentDescription = "Sprite: $spriteName",
|
||||
contentDescription = "Sprite: $characterId frame $frameNumber",
|
||||
modifier = modifier,
|
||||
contentScale = contentScale
|
||||
)
|
||||
|
||||
@ -45,7 +45,6 @@ import com.github.nacabaro.vbhelper.battle.APIBattleCharacter
|
||||
import android.util.Log
|
||||
import com.github.nacabaro.vbhelper.components.TopBanner
|
||||
import com.github.nacabaro.vbhelper.battle.RetrofitHelper
|
||||
import com.github.nacabaro.vbhelper.battle.SpriteImage
|
||||
import com.github.nacabaro.vbhelper.battle.AttackSpriteImage
|
||||
import com.github.nacabaro.vbhelper.battle.SpriteFileManager
|
||||
import com.github.nacabaro.vbhelper.battle.ArenaBattleSystem
|
||||
@ -286,7 +285,8 @@ fun PlayerBattleView(
|
||||
modifier = Modifier
|
||||
.size(80.dp)
|
||||
.scale(-1f, 1f), // Flip player Digimon horizontally
|
||||
contentScale = ContentScale.Fit
|
||||
contentScale = ContentScale.Fit,
|
||||
reloadMappings = false
|
||||
)
|
||||
|
||||
// Attack sprite visibility and positioning based on attack phase
|
||||
@ -500,7 +500,8 @@ fun OpponentBattleView(
|
||||
characterId = activeCharacter?.charaId ?: "dim011_mon01",
|
||||
animationType = animationType,
|
||||
modifier = Modifier.size(80.dp),
|
||||
contentScale = ContentScale.Fit
|
||||
contentScale = ContentScale.Fit,
|
||||
reloadMappings = false
|
||||
)
|
||||
|
||||
// Attack sprite visibility and positioning based on attack phase
|
||||
@ -642,12 +643,13 @@ fun BattlesScreen() {
|
||||
|
||||
// Initialize sprite files on first load
|
||||
LaunchedEffect(Unit) {
|
||||
println("BATTLESCREEN: LaunchedEffect triggered - checking sprite files...")
|
||||
val spriteFileManager = SpriteFileManager(context)
|
||||
if (!spriteFileManager.checkSpriteFilesExist()) {
|
||||
println("Copying sprite files to internal storage...")
|
||||
println("BATTLESCREEN: Copying sprite files to internal storage...")
|
||||
spriteFileManager.copySpriteFilesToInternalStorage()
|
||||
} else {
|
||||
println("Sprite files already exist in internal storage")
|
||||
println("BATTLESCREEN: Sprite files already exist in internal storage")
|
||||
}
|
||||
}
|
||||
|
||||
@ -856,7 +858,8 @@ fun BattlesScreen() {
|
||||
characterId = testCharacterId,
|
||||
animationType = currentTestAnimation,
|
||||
modifier = Modifier.size(120.dp),
|
||||
contentScale = ContentScale.Fit
|
||||
contentScale = ContentScale.Fit,
|
||||
reloadMappings = false
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user