diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c28d47b..d8da12c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,6 +5,8 @@
+
+
()
- // Base path for attack textures (updated for new folder structure)
- private val attackTexturesPath = "battle_sprites/extracted_atksprites"
+ // Get the external storage directory for attack sprites
+ private fun getAttackTexturesPath(): String {
+ return "VBHelper/battle_sprites/extracted_atksprites"
+ }
fun getAttackSprite(characterId: String, isLarge: Boolean = false): Bitmap? {
println("AttackSpriteManager: Getting attack sprite for characterId=$characterId, isLarge=$isLarge")
@@ -55,9 +58,10 @@ class AttackSpriteManager(private val context: Context) {
return null
}
- // Load the attack sprite
- val attackFilePath = "$attackTexturesPath/$attackFileName.png"
- val attackFile = File(context.filesDir, attackFilePath)
+ // Load the attack sprite from external storage
+ val externalDir = Environment.getExternalStorageDirectory()
+ val attackFilePath = "${getAttackTexturesPath()}/$attackFileName.png"
+ val attackFile = File(externalDir, attackFilePath)
println("AttackSpriteManager: Attack file path = ${attackFile.absolutePath}")
println("AttackSpriteManager: Attack file exists = ${attackFile.exists()}")
@@ -85,8 +89,9 @@ class AttackSpriteManager(private val context: Context) {
}
try {
- // Load character data from JSON file
- val characterDataFile = File(context.filesDir, "battle_sprites/extracted_digimon_stats/character_data/CharacterData.json")
+ // Load character data from JSON file in external storage
+ val externalDir = Environment.getExternalStorageDirectory()
+ val characterDataFile = File(externalDir, "VBHelper/battle_sprites/extracted_digimon_stats/character_data/CharacterData.json")
println("AttackSpriteManager: Character data file path = ${characterDataFile.absolutePath}")
println("AttackSpriteManager: Character data file exists = ${characterDataFile.exists()}")
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/battle/BattleSpriteManager.kt b/app/src/main/java/com/github/nacabaro/vbhelper/battle/BattleSpriteManager.kt
index 316d486..f7fd5c1 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/battle/BattleSpriteManager.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/battle/BattleSpriteManager.kt
@@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.battle
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
+import android.os.Environment
import com.google.gson.Gson
import java.io.File
@@ -37,8 +38,11 @@ class BattleSpriteManager(private val context: Context) {
private val gson = Gson()
private val spriteCache = mutableMapOf()
- // Base directory where your sprites are stored
- private val spriteBaseDir = File(context.filesDir, "battle_sprites/extracted_assets")
+ // Get the external storage directory for sprite files
+ private fun getSpriteBaseDir(): File {
+ val externalDir = Environment.getExternalStorageDirectory()
+ return File(externalDir, "VBHelper/battle_sprites/extracted_assets")
+ }
fun loadSprite(spriteName: String, atlasName: String): Bitmap? {
val cacheKey = "${spriteName}_${atlasName}"
@@ -49,6 +53,7 @@ class BattleSpriteManager(private val context: Context) {
}
// Debug: Check if base directory exists
+ val spriteBaseDir = getSpriteBaseDir()
if (!spriteBaseDir.exists()) {
println("Sprite base directory does not exist: ${spriteBaseDir.absolutePath}")
return null
@@ -130,7 +135,7 @@ class BattleSpriteManager(private val context: Context) {
// Helper method to get available sprites for an atlas
fun getAvailableSprites(atlasName: String): List {
try {
- val spritesDir = File(spriteBaseDir, "sprites")
+ val spritesDir = File(getSpriteBaseDir(), "sprites")
if (!spritesDir.exists()) {
return emptyList()
}
@@ -154,7 +159,7 @@ class BattleSpriteManager(private val context: Context) {
// Helper method to get available atlases
fun getAvailableAtlases(): List {
try {
- val texturesDir = File(spriteBaseDir, "extracted_textures")
+ val texturesDir = File(getSpriteBaseDir(), "extracted_textures")
if (!texturesDir.exists()) {
return emptyList()
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/battle/HitEffectSpriteManager.kt b/app/src/main/java/com/github/nacabaro/vbhelper/battle/HitEffectSpriteManager.kt
index 33d2189..6536040 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/battle/HitEffectSpriteManager.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/battle/HitEffectSpriteManager.kt
@@ -4,13 +4,17 @@ import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Rect
+import android.os.Environment
import java.io.File
class HitEffectSpriteManager(private val context: Context) {
private val spriteCache = mutableMapOf()
- // Base directory where hit effect sprites are stored
- private val hitSpritesDir = File(context.filesDir, "battle_sprites/extracted_hit_sprites")
+ // Get the external storage directory for hit effect sprites
+ private fun getHitSpritesDir(): File {
+ val externalDir = Environment.getExternalStorageDirectory()
+ return File(externalDir, "VBHelper/battle_sprites/extracted_hit_sprites")
+ }
/**
* Load a hit sprite (hit_01.png, hit_02.png, hit_02_white.png)
@@ -26,6 +30,7 @@ class HitEffectSpriteManager(private val context: Context) {
}
try {
+ val hitSpritesDir = getHitSpritesDir()
val spriteFile = File(hitSpritesDir, "$spriteName.png")
if (!spriteFile.exists()) {
@@ -68,7 +73,7 @@ class HitEffectSpriteManager(private val context: Context) {
}
try {
- val spritesheetFile = File(hitSpritesDir, "$spritesheetName.png")
+ val spritesheetFile = File(getHitSpritesDir(), "$spritesheetName.png")
if (!spritesheetFile.exists()) {
println("Damage effect spritesheet not found: ${spritesheetFile.absolutePath}")
@@ -118,28 +123,21 @@ class HitEffectSpriteManager(private val context: Context) {
}
/**
- * Get available hit sprite names
- * @return List of available hit sprite names
+ * Get all available hit sprites
+ * @return List of hit sprite names (without .png extension)
*/
fun getAvailableHitSprites(): List {
- try {
- if (!hitSpritesDir.exists()) {
- return emptyList()
- }
-
- val hitFiles = hitSpritesDir.listFiles { file ->
- file.name.startsWith("hit_") && file.name.endsWith(".png")
- } ?: emptyArray()
-
- return hitFiles.map { file ->
- file.name.substringBefore(".png")
- }.sorted()
-
- } catch (e: Exception) {
- println("Error getting available hit sprites: ${e.message}")
- e.printStackTrace()
+ val hitSpritesDir = getHitSpritesDir()
+
+ if (!hitSpritesDir.exists()) {
return emptyList()
}
+
+ return hitSpritesDir.listFiles { file ->
+ file.name.startsWith("hit_") && file.name.endsWith(".png")
+ }?.map { file ->
+ file.name.substringBefore(".png")
+ }?.sorted() ?: emptyList()
}
/**
@@ -148,11 +146,11 @@ class HitEffectSpriteManager(private val context: Context) {
*/
fun getAvailableDamageEffectSpritesheets(): List {
try {
- if (!hitSpritesDir.exists()) {
+ if (!getHitSpritesDir().exists()) {
return emptyList()
}
- val dmgFiles = hitSpritesDir.listFiles { file ->
+ val dmgFiles = getHitSpritesDir().listFiles { file ->
file.name.startsWith("dmg_ef") && file.name.endsWith(".png")
} ?: emptyArray()
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/battle/IndividualSpriteManager.kt b/app/src/main/java/com/github/nacabaro/vbhelper/battle/IndividualSpriteManager.kt
index f4b0d25..f6b9179 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/battle/IndividualSpriteManager.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/battle/IndividualSpriteManager.kt
@@ -3,13 +3,17 @@ package com.github.nacabaro.vbhelper.battle
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
+import android.os.Environment
import java.io.File
class IndividualSpriteManager(private val context: Context) {
private val spriteCache = mutableMapOf()
- // Base directory where individual sprite PNGs are stored
- private val spriteBaseDir = File(context.filesDir, "battle_sprites/extracted_assets/sprites")
+ // Get the external storage directory for sprite files
+ private fun getSpriteBaseDir(): File {
+ val externalDir = Environment.getExternalStorageDirectory()
+ return File(externalDir, "VBHelper/battle_sprites/extracted_assets/sprites")
+ }
/**
* Load a specific sprite frame for a character
@@ -26,6 +30,7 @@ class IndividualSpriteManager(private val context: Context) {
}
// Debug: Check if base directory exists
+ val spriteBaseDir = getSpriteBaseDir()
if (!spriteBaseDir.exists()) {
println("Sprite base directory does not exist: ${spriteBaseDir.absolutePath}")
return null
@@ -68,51 +73,38 @@ class IndividualSpriteManager(private val context: Context) {
* @return List of frame numbers (1-12) that exist for this character
*/
fun getAvailableFrames(characterId: String): List {
- 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()
+ val spriteBaseDir = getSpriteBaseDir()
+ val characterDir = File(spriteBaseDir, characterId)
+
+ if (!characterDir.exists()) {
return emptyList()
}
+
+ val spriteFiles = characterDir.listFiles { file ->
+ file.name.startsWith("${characterId}_") && file.name.endsWith(".png")
+ } ?: emptyArray()
+
+ return spriteFiles.mapNotNull { file ->
+ val fileName = file.name
+ val frameMatch = Regex("${characterId}_(\\d{2})\\.png").find(fileName)
+ frameMatch?.groupValues?.get(1)?.toIntOrNull()
+ }.sorted()
}
/**
- * Get all available characters
+ * Get all available character IDs
* @return List of character IDs that have sprite directories
*/
fun getAvailableCharacters(): List {
- 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()
+ val spriteBaseDir = getSpriteBaseDir()
+
+ if (!spriteBaseDir.exists()) {
return emptyList()
}
+
+ return spriteBaseDir.listFiles { file ->
+ file.isDirectory && file.listFiles()?.any { it.name.endsWith(".png") } == true
+ }?.map { it.name }?.sorted() ?: emptyList()
}
/**
@@ -128,7 +120,7 @@ class IndividualSpriteManager(private val context: Context) {
* @return true if the character has sprite files, false otherwise
*/
fun hasCharacterSprites(characterId: String): Boolean {
- val characterDir = File(spriteBaseDir, characterId)
+ val characterDir = File(getSpriteBaseDir(), characterId)
if (!characterDir.exists()) {
return false
}
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/battle/SpriteFileManager.kt b/app/src/main/java/com/github/nacabaro/vbhelper/battle/SpriteFileManager.kt
index 5dd3699..2f663cb 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/battle/SpriteFileManager.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/battle/SpriteFileManager.kt
@@ -1,15 +1,22 @@
package com.github.nacabaro.vbhelper.battle
import android.content.Context
+import android.os.Environment
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
class SpriteFileManager(private val context: Context) {
- fun copySpriteFilesToInternalStorage() {
+ // Get the external storage directory for sprite files
+ private fun getSpriteBaseDir(): File {
+ val externalDir = Environment.getExternalStorageDirectory()
+ return File(externalDir, "VBHelper/battle_sprites")
+ }
+
+ fun copySpriteFilesToExternalStorage() {
try {
- println("Starting sprite file copy process...")
+ println("Starting sprite file copy process to external storage...")
// Debug: List what's in the assets directory
val assetManager = context.assets
@@ -47,17 +54,17 @@ class SpriteFileManager(private val context: Context) {
}
}
- // Create the base directory for battle_sprites
- val battleSpritesDir = File(context.filesDir, "battle_sprites")
+ // Create the base directory for battle_sprites in external storage
+ val battleSpritesDir = getSpriteBaseDir()
if (!battleSpritesDir.exists()) {
battleSpritesDir.mkdirs()
- println("Created battle_sprites directory: ${battleSpritesDir.absolutePath}")
+ println("Created battle_sprites directory in external storage: ${battleSpritesDir.absolutePath}")
} else {
- println("battle_sprites directory already exists: ${battleSpritesDir.absolutePath}")
+ println("battle_sprites directory already exists in external storage: ${battleSpritesDir.absolutePath}")
}
- // Copy all subdirectories from battle_sprites assets to internal storage
- println("Copying all battle_sprites subdirectories...")
+ // Copy all subdirectories from battle_sprites assets to external storage
+ println("Copying all battle_sprites subdirectories to external storage...")
battleSpritesFiles?.forEach { subdir ->
val sourcePath = "battle_sprites/$subdir"
val targetDir = File(battleSpritesDir, subdir)
@@ -65,7 +72,7 @@ class SpriteFileManager(private val context: Context) {
copyAssetDirectory(sourcePath, targetDir)
}
- println("Sprite files copied successfully to: ${battleSpritesDir.absolutePath}")
+ println("Sprite files copied successfully to external storage: ${battleSpritesDir.absolutePath}")
// Verify that attack sprites were copied
val atkspritesDir = File(battleSpritesDir, "extracted_atksprites")
@@ -95,7 +102,7 @@ class SpriteFileManager(private val context: Context) {
}
} catch (e: Exception) {
- println("Error copying sprite files: ${e.message}")
+ println("Error copying sprite files to external storage: ${e.message}")
e.printStackTrace()
}
}
@@ -180,7 +187,7 @@ class SpriteFileManager(private val context: Context) {
}
fun checkSpriteFilesExist(): Boolean {
- val battleSpritesDir = File(context.filesDir, "battle_sprites")
+ val battleSpritesDir = getSpriteBaseDir()
val extractedAssetsDir = File(battleSpritesDir, "extracted_assets")
val extractedStatsDir = File(battleSpritesDir, "extracted_digimon_stats")
val atkspritesDir = File(battleSpritesDir, "extracted_atksprites")
@@ -204,7 +211,7 @@ class SpriteFileManager(private val context: Context) {
fun clearSpriteFiles() {
try {
- val battleSpritesDir = File(context.filesDir, "battle_sprites")
+ val battleSpritesDir = getSpriteBaseDir()
if (battleSpritesDir.exists()) {
deleteDirectory(battleSpritesDir)
diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/BattlesScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/BattlesScreen.kt
index ab82952..c9e2f79 100644
--- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/BattlesScreen.kt
+++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/BattlesScreen.kt
@@ -66,9 +66,72 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.foundation.Image
import androidx.compose.ui.graphics.asImageBitmap
import android.graphics.BitmapFactory
+import android.os.Environment
import java.io.File
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.foundation.layout.width
+
+@Composable
+fun isLandscapeMode(): Boolean {
+ val configuration = LocalConfiguration.current
+ return configuration.screenWidthDp > configuration.screenHeightDp
+}
+
+@Composable
+fun getLandscapeModifier(): Modifier {
+ val configuration = LocalConfiguration.current
+ val isLandscape = configuration.screenWidthDp > configuration.screenHeightDp
+ return if (isLandscape) {
+ Modifier.width(200.dp).height(8.dp)
+ } else {
+ Modifier.fillMaxWidth().height(10.dp)
+ }
+}
+
+@Composable
+fun getLandscapeAlignment(): Alignment {
+ val configuration = LocalConfiguration.current
+ val isLandscape = configuration.screenWidthDp > configuration.screenHeightDp
+ return if (isLandscape) Alignment.Center else Alignment.TopStart
+}
+
+@Composable
+fun getLandscapeHorizontalAlignment(): Alignment.Horizontal {
+ val configuration = LocalConfiguration.current
+ val isLandscape = configuration.screenWidthDp > configuration.screenHeightDp
+ return if (isLandscape) Alignment.CenterHorizontally else Alignment.Start
+}
+
+@Composable
+fun getLandscapeFontSize(): androidx.compose.ui.unit.TextUnit {
+ val configuration = LocalConfiguration.current
+ val isLandscape = configuration.screenWidthDp > configuration.screenHeightDp
+ return if (isLandscape) 14.sp else 16.sp
+}
+
+@Composable
+fun getLandscapeBoxModifier(): Modifier {
+ val configuration = LocalConfiguration.current
+ val isLandscape = configuration.screenWidthDp > configuration.screenHeightDp
+ return if (isLandscape) {
+ Modifier
+ .width(220.dp) // Slightly wider than the progress bar to accommodate padding
+ .background(
+ color = Color.Gray.copy(alpha = 0.6f),
+ shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
+ )
+ .padding(8.dp)
+ } else {
+ Modifier
+ .fillMaxWidth()
+ .background(
+ color = Color.Gray.copy(alpha = 0.6f),
+ shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
+ )
+ .padding(8.dp)
+ }
+}
@Composable
fun AnimatedDamageNumber(
@@ -266,13 +329,13 @@ fun BattleScreen(
delay(16) // 60 FPS
}
println("Phase 2 completed, applying damage and starting Phase 3")
- battleSystem.completeAttackAnimation(opponentDamage = pendingOpponentDamage)
+ battleSystem.completeAttackAnimation(opponentDamage = pendingOpponentDamage)
// Hide damage number and reset pending damage after animation
if (showOpponentDamageNumber) {
delay(800) // Wait for damage number animation (scale up + hold + fade out)
showOpponentDamageNumber = false
- pendingOpponentDamage = 0f
+ pendingOpponentDamage = 0f
println("DEBUG: Hiding opponent damage number and resetting pending damage")
}
@@ -344,18 +407,18 @@ fun BattleScreen(
}
println("Phase 3 completed, applying damage and resetting")
println("DEBUG: pendingPlayerDamage = $pendingPlayerDamage")
- battleSystem.completeAttackAnimation(playerDamage = pendingPlayerDamage)
+ battleSystem.completeAttackAnimation(playerDamage = pendingPlayerDamage)
// Hide damage number and reset pending damage after animation
if (showPlayerDamageNumber) {
delay(800) // Wait for damage number animation (scale up + hold + fade out)
showPlayerDamageNumber = false
- pendingPlayerDamage = 0f
+ pendingPlayerDamage = 0f
println("DEBUG: Hiding player damage number and resetting pending damage")
}
- battleSystem.resetAttackState()
- battleSystem.enableAttackButton()
+ battleSystem.resetAttackState()
+ battleSystem.enableAttackButton()
// Check if battle is over
if (battleSystem.checkBattleOver()) {
@@ -733,21 +796,16 @@ fun MiddleBattleView(
// Enemy HP bar and text with background box
Box(
- modifier = Modifier
- .fillMaxWidth()
- .background(
- color = Color.Gray.copy(alpha = 0.6f),
- shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
- )
- .padding(8.dp)
+ modifier = getLandscapeBoxModifier(),
+ contentAlignment = getLandscapeAlignment()
) {
- Column {
+ Column(
+ horizontalAlignment = getLandscapeHorizontalAlignment()
+ ) {
// Enemy HP bar (top)
LinearProgressIndicator(
progress = battleSystem.opponentHP / (opponentCharacter?.baseHp?.toFloat() ?: 100f),
- modifier = Modifier
- .fillMaxWidth()
- .height(10.dp),
+ modifier = getLandscapeModifier(),
color = Color.Red,
trackColor = Color.Gray
)
@@ -757,7 +815,7 @@ fun MiddleBattleView(
// Enemy HP display numbers
Text(
text = "Enemy HP: ${battleSystem.opponentHP.toInt()}/${opponentCharacter?.baseHp ?: 100}",
- fontSize = 16.sp,
+ fontSize = getLandscapeFontSize(),
color = Color.White,
style = TextStyle(
shadow = Shadow(
@@ -962,9 +1020,7 @@ fun MiddleBattleView(
// Critical bar
LinearProgressIndicator(
progress = battleSystem.critBarProgress / 100f,
- modifier = Modifier
- .fillMaxWidth()
- .height(10.dp),
+ modifier = getLandscapeModifier(),
color = Color.Yellow,
trackColor = Color.Gray
)
@@ -973,21 +1029,16 @@ fun MiddleBattleView(
// Player HP bar and text with background box
Box(
- modifier = Modifier
- .fillMaxWidth()
- .background(
- color = Color.Gray.copy(alpha = 0.6f),
- shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
- )
- .padding(8.dp)
+ modifier = getLandscapeBoxModifier(),
+ contentAlignment = getLandscapeAlignment()
) {
- Column {
+ Column(
+ horizontalAlignment = getLandscapeHorizontalAlignment()
+ ) {
// Player HP bar
LinearProgressIndicator(
progress = battleSystem.playerHP / (activeCharacter?.baseHp?.toFloat() ?: 100f),
- modifier = Modifier
- .fillMaxWidth()
- .height(10.dp),
+ modifier = getLandscapeModifier(),
color = Color.Green,
trackColor = Color.Gray
)
@@ -997,7 +1048,7 @@ fun MiddleBattleView(
// Player HP display numbers
Text(
text = "HP: ${battleSystem.playerHP.toInt()}/${activeCharacter?.baseHp ?: 100}",
- fontSize = 16.sp,
+ fontSize = getLandscapeFontSize(),
color = Color.White,
style = TextStyle(
shadow = Shadow(
@@ -1193,31 +1244,26 @@ fun PlayerBattleView(
// Health bar and text with background box
Box(
- modifier = Modifier
- .fillMaxWidth()
- .background(
- color = Color.Gray.copy(alpha = 0.6f),
- shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
- )
- .padding(8.dp)
+ modifier = getLandscapeBoxModifier(),
+ contentAlignment = getLandscapeAlignment()
) {
- Column {
- // Health bar
- LinearProgressIndicator(
- progress = battleSystem.playerHP / (activeCharacter?.baseHp?.toFloat() ?: 100f),
- modifier = Modifier
- .fillMaxWidth()
- .height(10.dp),
- color = Color.Green,
- trackColor = Color.Gray
- )
+ Column(
+ horizontalAlignment = getLandscapeHorizontalAlignment()
+ ) {
+ // Health bar
+ LinearProgressIndicator(
+ progress = battleSystem.playerHP / (activeCharacter?.baseHp?.toFloat() ?: 100f),
+ modifier = getLandscapeModifier(),
+ color = Color.Green,
+ trackColor = Color.Gray
+ )
Spacer(modifier = Modifier.height(4.dp))
- // Health display numbers
- Text(
- text = "HP: ${battleSystem.playerHP.toInt()}/${activeCharacter?.baseHp ?: 100}",
- fontSize = 16.sp,
+ // Health display numbers
+ Text(
+ text = "HP: ${battleSystem.playerHP.toInt()}/${activeCharacter?.baseHp ?: 100}",
+ fontSize = getLandscapeFontSize(),
color = Color.White,
style = TextStyle(
shadow = Shadow(
@@ -1363,9 +1409,7 @@ fun PlayerBattleView(
// Critical bar
LinearProgressIndicator(
progress = battleSystem.critBarProgress / 100f,
- modifier = Modifier
- .fillMaxWidth()
- .height(10.dp),
+ modifier = getLandscapeModifier(),
color = Color.Yellow,
trackColor = Color.Gray
)
@@ -1422,22 +1466,22 @@ fun PlayerBattleView(
// Match is still ongoing - update HP and continue
println("Round ${apiResult.currentRound}: Player HP=${apiResult.playerHP}, Opponent HP=${apiResult.opponentHP}")
- // Set pending damage based on API result
+ // Set pending damage based on API result
if (apiResult.playerAttackDamage > 0) {
- // Player attack hit - enemy takes damage at end of player animation
- println("Player attack hit! Enemy will take ${apiResult.playerAttackDamage} damage")
- onSetPendingDamage(0f, apiResult.playerAttackDamage.toFloat()) // Opponent takes damage
- battleSystem.setAttackHitState(true)
+ // Player attack hit - enemy takes damage at end of player animation
+ println("Player attack hit! Enemy will take ${apiResult.playerAttackDamage} damage")
+ onSetPendingDamage(0f, apiResult.playerAttackDamage.toFloat()) // Opponent takes damage
+ battleSystem.setAttackHitState(true)
// Also check if enemy counter-attacks and hits
if (apiResult.opponentAttackDamage > 0) {
println("Enemy counter-attack hits! Player takes ${apiResult.opponentAttackDamage} damage")
onSetPendingDamage(apiResult.opponentAttackDamage.toFloat(), apiResult.playerAttackDamage.toFloat()) // Both take damage
}
- } else {
+ } else {
// Player attack missed - enemy counter-attacks
println("Player attack missed! Enemy counter-attacks")
- battleSystem.setAttackHitState(false)
+ battleSystem.setAttackHitState(false)
// Set up counter-attack - determine if it hits based on API result
val counterAttackHits = apiResult.opponentAttackDamage > 0
println("Setting up counter-attack: counterAttackHits=$counterAttackHits, opponentAttackDamage=${apiResult.opponentAttackDamage}")
@@ -1458,7 +1502,7 @@ fun PlayerBattleView(
battleSystem.setupCounterAttack(finalCounterAttackHits)
// Set the opponent attack hit state for Phase 3
battleSystem.handleOpponentAttackResult(finalCounterAttackHits)
- }
+ }
}
2 -> {
// Match is over - transition to results screen
@@ -1514,28 +1558,23 @@ fun EnemyBattleView(
MultiLayerAnimatedBattleBackground(modifier = Modifier.fillMaxSize())
// Top section: Enemy HP bar and HP numbers
- Column(
+ Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
) {
// Enemy HP bar and text with background box
Box(
- modifier = Modifier
- .fillMaxWidth()
- .background(
- color = Color.Gray.copy(alpha = 0.6f),
- shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
- )
- .padding(8.dp)
+ modifier = getLandscapeBoxModifier(),
+ contentAlignment = getLandscapeAlignment()
) {
- Column {
+ Column(
+ horizontalAlignment = getLandscapeHorizontalAlignment()
+ ) {
// Enemy HP bar
LinearProgressIndicator(
progress = battleSystem.opponentHP / (activeCharacter?.baseHp?.toFloat() ?: 100f),
- modifier = Modifier
- .fillMaxWidth()
- .height(10.dp),
+ modifier = getLandscapeModifier(),
color = Color.Red,
trackColor = Color.Gray
)
@@ -1545,7 +1584,7 @@ fun EnemyBattleView(
// Enemy HP display numbers
Text(
text = "Enemy HP: ${battleSystem.opponentHP.toInt()}/${activeCharacter?.baseHp ?: 100}",
- fontSize = 16.sp,
+ fontSize = getLandscapeFontSize(),
color = Color.White,
style = TextStyle(
shadow = Shadow(
@@ -1561,25 +1600,25 @@ fun EnemyBattleView(
// Middle section: Enemy Digimon
Box(
- modifier = Modifier
- .fillMaxSize()
- .padding(16.dp),
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(16.dp),
contentAlignment = Alignment.Center
- ) {
+ ) {
// Enemy Digimon
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .size(80.dp),
- contentAlignment = Alignment.CenterEnd
- ) {
- // Determine animation type based on battle state
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .size(80.dp),
+ contentAlignment = Alignment.CenterEnd
+ ) {
+ // Determine animation type based on battle state
val animationType = when {
battleSystem.isOpponentDodging -> DigimonAnimationType.WALK // Use walk animation for dodge
battleSystem.isOpponentHitDelayed -> DigimonAnimationType.SLEEP // Use sleep animation for hit effect (injured sprite)
battleSystem.attackPhase == 2 -> DigimonAnimationType.IDLE // Player attack on enemy screen
- else -> DigimonAnimationType.IDLE
- }
+ else -> DigimonAnimationType.IDLE
+ }
// Calculate vertical offset for dodge animation
val verticalOffset = if (battleSystem.isOpponentDodging) {
@@ -1608,65 +1647,65 @@ fun EnemyBattleView(
} else {
0.dp
}
-
- AnimatedSpriteImage(
- characterId = activeCharacter?.charaId ?: "dim011_mon01",
- animationType = animationType,
+
+ AnimatedSpriteImage(
+ characterId = activeCharacter?.charaId ?: "dim011_mon01",
+ animationType = animationType,
modifier = Modifier
.size(80.dp)
.offset(
x = hitOffset,
y = verticalOffset
),
- contentScale = ContentScale.Fit,
+ contentScale = ContentScale.Fit,
reloadMappings = false,
animationOffset = 375L // Offset enemy animation by half the idle duration
- )
-
- // Attack sprite visibility and positioning based on attack phase
- val shouldShowAttack = when (battleSystem.attackPhase) {
+ )
+
+ // Attack sprite visibility and positioning based on attack phase
+ val shouldShowAttack = when (battleSystem.attackPhase) {
2 -> true // Player attack on enemy screen
- else -> false
- }
-
- if (shouldShowAttack) {
+ else -> false
+ }
+
+ if (shouldShowAttack) {
val xOffset = (attackAnimationProgress * 400 - 350).dp // Player attack on enemy screen - start more to the left
// Use player's character ID for player attack
val characterId = playerCharacter?.charaId ?: "dim011_mon01"
-
- // Handle sprite transition
- LaunchedEffect(characterId, battleSystem.attackPhase) {
- if ((previousCharacterId != null && previousCharacterId != characterId) ||
- (previousAttackPhase != null && previousAttackPhase != battleSystem.attackPhase)) {
- // Character ID or attack phase changed, start transition
- isTransitioning = true
- delay(100) // Brief invisibility period
- isTransitioning = false
- }
- previousCharacterId = characterId
- previousAttackPhase = battleSystem.attackPhase
+
+ // Handle sprite transition
+ LaunchedEffect(characterId, battleSystem.attackPhase) {
+ if ((previousCharacterId != null && previousCharacterId != characterId) ||
+ (previousAttackPhase != null && previousAttackPhase != battleSystem.attackPhase)) {
+ // Character ID or attack phase changed, start transition
+ isTransitioning = true
+ delay(100) // Brief invisibility period
+ isTransitioning = false
}
-
+ previousCharacterId = characterId
+ previousAttackPhase = battleSystem.attackPhase
+ }
+
println("EnemyBattleView - Attack sprite - Phase: ${battleSystem.attackPhase}, Progress: $attackAnimationProgress, X Offset: $xOffset, CurrentView: ${battleSystem.currentView}")
-
+
if (!isTransitioning && !hideEnemyAttackSprite) {
- AttackSpriteImage(
- characterId = characterId,
- isLarge = true,
- modifier = Modifier
- .size(60.dp)
- .offset(
- x = xOffset,
- y = 0.dp
- )
+ AttackSpriteImage(
+ characterId = characterId,
+ isLarge = true,
+ modifier = Modifier
+ .size(60.dp)
+ .offset(
+ x = xOffset,
+ y = 0.dp
+ )
.scale(-1f, 1f), // Flip player attacks
- contentScale = ContentScale.Fit
- )
- }
+ contentScale = ContentScale.Fit
+ )
}
}
}
+ }
}
}
@@ -1735,10 +1774,10 @@ fun BattlesScreen() {
println("BATTLESCREEN: LaunchedEffect triggered - checking sprite files...")
val spriteFileManager = SpriteFileManager(context)
if (!spriteFileManager.checkSpriteFilesExist()) {
- println("BATTLESCREEN: Copying sprite files to internal storage...")
- spriteFileManager.copySpriteFilesToInternalStorage()
+ println("BATTLESCREEN: Copying sprite files to external storage...")
+ spriteFileManager.copySpriteFilesToExternalStorage()
} else {
- println("BATTLESCREEN: Sprite files already exist in internal storage")
+ println("BATTLESCREEN: Sprite files already exist in external storage")
}
}
@@ -2048,9 +2087,9 @@ fun BattlesScreen() {
topBar = {
// Only show TopBanner when not in battle mode
if (currentView != "battle-main" && currentView != "battle-results") {
- TopBanner(
- text = "Online battles"
- )
+ TopBanner(
+ text = "Online battles"
+ )
}
}
) { contentPadding ->
@@ -2077,6 +2116,7 @@ fun BattlesScreen() {
championButton()
ultimateButton()
megaButton()
+ /*
Button(
onClick = {
showSpriteTester = true
@@ -2098,6 +2138,8 @@ fun BattlesScreen() {
) {
Text("Clear Sprite Files")
}
+
+ */
}
}
}
@@ -2387,10 +2429,11 @@ fun AnimatedBattleBackground(
println("DEBUG: Screen dimensions = ${screenWidth.value}x${screenHeight.value}dp")
}
- // Load background image from internal storage
+ // Load background image from external storage
LaunchedEffect(Unit) {
try {
- val backgroundFile = File(context.filesDir, "battle_sprites/extracted_battlebgs/BattleBg_0015_BattleBg_0012.png")
+ val externalDir = Environment.getExternalStorageDirectory()
+ val backgroundFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/BattleBg_0015_BattleBg_0012.png")
if (backgroundFile.exists()) {
backgroundBitmap = BitmapFactory.decodeFile(backgroundFile.absolutePath)
println("Successfully loaded battle background: ${backgroundFile.absolutePath}")
@@ -2469,11 +2512,13 @@ fun MultiLayerAnimatedBattleBackground(
println("DEBUG: Multi-layer screen dimensions = ${screenWidth.value}x${screenHeight.value}dp")
}
- // Load all three background layers from internal storage
+ // Load all three background layers from external storage
LaunchedEffect(Unit) {
try {
+ val externalDir = Environment.getExternalStorageDirectory()
+
// Back layer (BattleBg_0018_BattleBg_0013.png)
- val backLayerFile = File(context.filesDir, "battle_sprites/extracted_battlebgs/BattleBg_0018_BattleBg_0013.png")
+ val backLayerFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/BattleBg_0018_BattleBg_0013.png")
if (backLayerFile.exists()) {
backLayerBitmap = BitmapFactory.decodeFile(backLayerFile.absolutePath)
println("Successfully loaded back layer background: ${backLayerFile.absolutePath}")
@@ -2482,7 +2527,7 @@ fun MultiLayerAnimatedBattleBackground(
}
// Middle layer (BattleBg_0015_BattleBg_0012.png)
- val middleLayerFile = File(context.filesDir, "battle_sprites/extracted_battlebgs/BattleBg_0015_BattleBg_0012.png")
+ val middleLayerFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/BattleBg_0015_BattleBg_0012.png")
if (middleLayerFile.exists()) {
middleLayerBitmap = BitmapFactory.decodeFile(middleLayerFile.absolutePath)
println("Successfully loaded middle layer background: ${middleLayerFile.absolutePath}")
@@ -2491,7 +2536,7 @@ fun MultiLayerAnimatedBattleBackground(
}
// Front layer (BattleBg_0005_BattleBg_0011.png)
- val frontLayerFile = File(context.filesDir, "battle_sprites/extracted_battlebgs/BattleBg_0005_BattleBg_0011.png")
+ val frontLayerFile = File(externalDir, "VBHelper/battle_sprites/extracted_battlebgs/BattleBg_0005_BattleBg_0011.png")
if (frontLayerFile.exists()) {
frontLayerBitmap = BitmapFactory.decodeFile(frontLayerFile.absolutePath)
println("Successfully loaded front layer background: ${frontLayerFile.absolutePath}")