mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-06-05 13:52:54 +00:00
Moved sprites to load from external Android storage.
Setup landscape view for battle.
This commit is contained in:
parent
f0760f9ed0
commit
bb1c29bbb4
@ -5,6 +5,8 @@
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".di.VBHelper"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -31,8 +32,10 @@ class AttackSpriteManager(private val context: Context) {
|
||||
private val gson = Gson()
|
||||
private val characterDataCache = mutableMapOf<String, CharacterData>()
|
||||
|
||||
// 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()}")
|
||||
|
||||
|
||||
@ -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<String, Bitmap>()
|
||||
|
||||
// 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<String> {
|
||||
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<String> {
|
||||
try {
|
||||
val texturesDir = File(spriteBaseDir, "extracted_textures")
|
||||
val texturesDir = File(getSpriteBaseDir(), "extracted_textures")
|
||||
if (!texturesDir.exists()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@ -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<String, Bitmap>()
|
||||
|
||||
// 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<String> {
|
||||
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<String> {
|
||||
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()
|
||||
|
||||
|
||||
@ -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<String, Bitmap>()
|
||||
|
||||
// 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<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()
|
||||
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<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()
|
||||
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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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}")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user