mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-06-05 22:02:54 +00:00
Added dodge and attack hit animations.
This commit is contained in:
parent
c404f4f436
commit
f0f1d9830e
@ -43,6 +43,46 @@ class ArenaBattleSystem {
|
|||||||
private var _critBarProgress by mutableStateOf(0)
|
private var _critBarProgress by mutableStateOf(0)
|
||||||
val critBarProgress: Int get() = _critBarProgress
|
val critBarProgress: Int get() = _critBarProgress
|
||||||
|
|
||||||
|
// Dodge animation states
|
||||||
|
private var _isDodging by mutableStateOf(false)
|
||||||
|
val isDodging: Boolean get() = _isDodging
|
||||||
|
|
||||||
|
private var _dodgeProgress by mutableStateOf(0f)
|
||||||
|
val dodgeProgress: Float get() = _dodgeProgress
|
||||||
|
|
||||||
|
private var _dodgeDirection by mutableStateOf(1f) // 1f = up, -1f = down
|
||||||
|
val dodgeDirection: Float get() = _dodgeDirection
|
||||||
|
|
||||||
|
private var _isHit by mutableStateOf(false)
|
||||||
|
val isHit: Boolean get() = _isHit
|
||||||
|
|
||||||
|
private var _hitProgress by mutableStateOf(0f)
|
||||||
|
val hitProgress: Float get() = _hitProgress
|
||||||
|
|
||||||
|
// Separate states for player and opponent
|
||||||
|
private var _isPlayerDodging by mutableStateOf(false)
|
||||||
|
val isPlayerDodging: Boolean get() = _isPlayerDodging
|
||||||
|
|
||||||
|
private var _isOpponentDodging by mutableStateOf(false)
|
||||||
|
val isOpponentDodging: Boolean get() = _isOpponentDodging
|
||||||
|
|
||||||
|
private var _isPlayerHit by mutableStateOf(false)
|
||||||
|
val isPlayerHit: Boolean get() = _isPlayerHit
|
||||||
|
|
||||||
|
private var _isOpponentHit by mutableStateOf(false)
|
||||||
|
val isOpponentHit: Boolean get() = _isOpponentHit
|
||||||
|
|
||||||
|
// Counter-attack tracking
|
||||||
|
private var _shouldCounterAttack by mutableStateOf(false)
|
||||||
|
val shouldCounterAttack: Boolean get() = _shouldCounterAttack
|
||||||
|
|
||||||
|
private var _counterAttackIsHit by mutableStateOf(false)
|
||||||
|
val counterAttackIsHit: Boolean get() = _counterAttackIsHit
|
||||||
|
|
||||||
|
// Separate tracking for opponent attack result
|
||||||
|
private var _opponentAttackIsHit by mutableStateOf(false)
|
||||||
|
val opponentAttackIsHit: Boolean get() = _opponentAttackIsHit
|
||||||
|
|
||||||
fun startPlayerAttack() {
|
fun startPlayerAttack() {
|
||||||
Log.d(TAG, "Starting player attack")
|
Log.d(TAG, "Starting player attack")
|
||||||
_attackPhase = 1
|
_attackPhase = 1
|
||||||
@ -121,6 +161,18 @@ class ArenaBattleSystem {
|
|||||||
_isPlayerAttacking = false
|
_isPlayerAttacking = false
|
||||||
_attackIsHit = false
|
_attackIsHit = false
|
||||||
_currentView = 0
|
_currentView = 0
|
||||||
|
_isDodging = false
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
_dodgeDirection = 1f
|
||||||
|
_isHit = false
|
||||||
|
_hitProgress = 0f
|
||||||
|
_isPlayerDodging = false
|
||||||
|
_isOpponentDodging = false
|
||||||
|
_isPlayerHit = false
|
||||||
|
_isOpponentHit = false
|
||||||
|
_shouldCounterAttack = false
|
||||||
|
_counterAttackIsHit = false
|
||||||
|
_opponentAttackIsHit = false
|
||||||
Log.d(TAG, "Reset attack state")
|
Log.d(TAG, "Reset attack state")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,4 +189,139 @@ class ArenaBattleSystem {
|
|||||||
_critBarProgress = progress
|
_critBarProgress = progress
|
||||||
//Log.d(TAG, "Updated crit bar progress: $progress")
|
//Log.d(TAG, "Updated crit bar progress: $progress")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dodge animation methods
|
||||||
|
fun startDodge() {
|
||||||
|
_isDodging = true
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
_dodgeDirection = 1f // Start moving up
|
||||||
|
Log.d(TAG, "Started dodge animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setDodgeProgress(progress: Float) {
|
||||||
|
_dodgeProgress = progress
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setDodgeDirection(direction: Float) {
|
||||||
|
_dodgeDirection = direction
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endDodge() {
|
||||||
|
_isDodging = false
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
Log.d(TAG, "Ended dodge animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hit animation methods
|
||||||
|
fun startHit() {
|
||||||
|
_isHit = true
|
||||||
|
_hitProgress = 0f
|
||||||
|
Log.d(TAG, "Started hit animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setHitProgress(progress: Float) {
|
||||||
|
_hitProgress = progress
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endHit() {
|
||||||
|
_isHit = false
|
||||||
|
_hitProgress = 0f
|
||||||
|
Log.d(TAG, "Ended hit animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player-specific dodge methods
|
||||||
|
fun startPlayerDodge() {
|
||||||
|
_isPlayerDodging = true
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
_dodgeDirection = 1f
|
||||||
|
Log.d(TAG, "Started player dodge animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endPlayerDodge() {
|
||||||
|
_isPlayerDodging = false
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
Log.d(TAG, "Ended player dodge animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opponent-specific dodge methods
|
||||||
|
fun startOpponentDodge() {
|
||||||
|
_isOpponentDodging = true
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
_dodgeDirection = 1f
|
||||||
|
Log.d(TAG, "Started opponent dodge animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endOpponentDodge() {
|
||||||
|
_isOpponentDodging = false
|
||||||
|
_dodgeProgress = 0f
|
||||||
|
Log.d(TAG, "Ended opponent dodge animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player-specific hit methods
|
||||||
|
fun startPlayerHit() {
|
||||||
|
_isPlayerHit = true
|
||||||
|
_hitProgress = 0f
|
||||||
|
Log.d(TAG, "Started player hit animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endPlayerHit() {
|
||||||
|
_isPlayerHit = false
|
||||||
|
_hitProgress = 0f
|
||||||
|
Log.d(TAG, "Ended player hit animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opponent-specific hit methods
|
||||||
|
fun startOpponentHit() {
|
||||||
|
_isOpponentHit = true
|
||||||
|
_hitProgress = 0f
|
||||||
|
Log.d(TAG, "Started opponent hit animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun endOpponentHit() {
|
||||||
|
_isOpponentHit = false
|
||||||
|
_hitProgress = 0f
|
||||||
|
Log.d(TAG, "Ended opponent hit animation")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined method to handle attack result
|
||||||
|
fun handleAttackResult(isHit: Boolean) {
|
||||||
|
_attackIsHit = isHit
|
||||||
|
if (isHit) {
|
||||||
|
// Player attack hit - opponent gets hit
|
||||||
|
startOpponentHit()
|
||||||
|
} else {
|
||||||
|
// Player attack missed - opponent dodges
|
||||||
|
startOpponentDodge()
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Handled player attack result: ${if (isHit) "HIT" else "DODGE"}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to handle opponent attack result
|
||||||
|
fun handleOpponentAttackResult(isHit: Boolean) {
|
||||||
|
_opponentAttackIsHit = isHit
|
||||||
|
if (isHit) {
|
||||||
|
// Opponent attack hit - player gets hit
|
||||||
|
startPlayerHit()
|
||||||
|
} else {
|
||||||
|
// Opponent attack missed - player dodges
|
||||||
|
startPlayerDodge()
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Handled opponent attack result: ${if (isHit) "HIT" else "DODGE"}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Counter-attack methods
|
||||||
|
fun setupCounterAttack(isHit: Boolean) {
|
||||||
|
_shouldCounterAttack = true
|
||||||
|
_counterAttackIsHit = isHit
|
||||||
|
Log.d(TAG, "Setup counter-attack: ${if (isHit) "HIT" else "DODGE"}, isHit=$isHit")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startCounterAttack() {
|
||||||
|
_attackPhase = 3
|
||||||
|
_attackProgress = 0f
|
||||||
|
_isPlayerAttacking = false
|
||||||
|
_currentView = 1
|
||||||
|
_opponentAttackIsHit = _counterAttackIsHit
|
||||||
|
Log.d(TAG, "Started counter-attack with opponentAttackIsHit=$_opponentAttackIsHit, counterAttackIsHit=$_counterAttackIsHit")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -37,6 +37,8 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
@ -52,6 +54,8 @@ import com.github.nacabaro.vbhelper.battle.DigimonAnimationType
|
|||||||
import com.github.nacabaro.vbhelper.battle.AnimatedSpriteImage
|
import com.github.nacabaro.vbhelper.battle.AnimatedSpriteImage
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import kotlin.math.sin
|
||||||
|
import kotlin.math.PI
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -65,6 +69,7 @@ fun BattleScreen(
|
|||||||
context: android.content.Context? = null
|
context: android.content.Context? = null
|
||||||
) {
|
) {
|
||||||
val battleSystem = remember { ArenaBattleSystem() }
|
val battleSystem = remember { ArenaBattleSystem() }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
// Initialize HP when battle starts
|
// Initialize HP when battle starts
|
||||||
LaunchedEffect(activeCharacter, opponentCharacter) {
|
LaunchedEffect(activeCharacter, opponentCharacter) {
|
||||||
@ -110,15 +115,37 @@ fun BattleScreen(
|
|||||||
while (progress < 1f) {
|
while (progress < 1f) {
|
||||||
progress += 0.016f // 60 FPS
|
progress += 0.016f // 60 FPS
|
||||||
battleSystem.setAttackProgress(progress)
|
battleSystem.setAttackProgress(progress)
|
||||||
|
|
||||||
|
// Trigger animation when attack reaches the opponent (around 55% progress for opponent dodge)
|
||||||
|
if (progress >= 0.55f && !battleSystem.isOpponentHit && !battleSystem.isOpponentDodging) {
|
||||||
|
if (battleSystem.attackIsHit) {
|
||||||
|
// Player attack hits opponent
|
||||||
|
println("Player attack hits opponent at progress $progress")
|
||||||
|
battleSystem.startOpponentHit()
|
||||||
|
} else {
|
||||||
|
// Player attack misses, opponent dodges
|
||||||
|
println("Player attack misses, opponent dodges at progress $progress")
|
||||||
|
battleSystem.startOpponentDodge()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delay(16) // 60 FPS
|
delay(16) // 60 FPS
|
||||||
}
|
}
|
||||||
println("Phase 2 completed, applying damage and starting opponent attack")
|
println("Phase 2 completed, applying damage and starting opponent attack")
|
||||||
// Apply player's damage and start opponent attack
|
// Apply player's damage
|
||||||
battleSystem.completeAttackAnimation(opponentDamage = pendingOpponentDamage)
|
battleSystem.completeAttackAnimation(opponentDamage = pendingOpponentDamage)
|
||||||
pendingOpponentDamage = 0f
|
pendingOpponentDamage = 0f
|
||||||
delay(500)
|
delay(500)
|
||||||
|
|
||||||
|
// Check if there's a counter-attack set up
|
||||||
|
if (battleSystem.shouldCounterAttack) {
|
||||||
|
println("Starting counter-attack")
|
||||||
|
battleSystem.startCounterAttack()
|
||||||
|
} else {
|
||||||
|
// Normal opponent attack
|
||||||
battleSystem.startOpponentAttack()
|
battleSystem.startOpponentAttack()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
3 -> {
|
3 -> {
|
||||||
// Phase 3: Opponent attack on opponent screen
|
// Phase 3: Opponent attack on opponent screen
|
||||||
println("Starting Phase 3: Opponent attack on opponent screen")
|
println("Starting Phase 3: Opponent attack on opponent screen")
|
||||||
@ -140,6 +167,23 @@ fun BattleScreen(
|
|||||||
while (progress < 1f) {
|
while (progress < 1f) {
|
||||||
progress += 0.016f // 60 FPS
|
progress += 0.016f // 60 FPS
|
||||||
battleSystem.setAttackProgress(progress)
|
battleSystem.setAttackProgress(progress)
|
||||||
|
|
||||||
|
// Trigger animation when attack reaches the player (around 75% progress - earlier for better timing)
|
||||||
|
if (progress >= 0.75f && !battleSystem.isPlayerHit && !battleSystem.isPlayerDodging) {
|
||||||
|
println("Phase 4: Checking player animation at progress $progress, opponentAttackIsHit=${battleSystem.opponentAttackIsHit}, shouldCounterAttack=${battleSystem.shouldCounterAttack}, counterAttackIsHit=${battleSystem.counterAttackIsHit}")
|
||||||
|
println("Phase 4: Player animation decision - opponentAttackIsHit=${battleSystem.opponentAttackIsHit}, will ${if (battleSystem.opponentAttackIsHit) "HIT" else "DODGE"}")
|
||||||
|
println("Phase 4: Full debug - attackPhase=${battleSystem.attackPhase}, isPlayerAttacking=${battleSystem.isPlayerAttacking}")
|
||||||
|
if (battleSystem.opponentAttackIsHit) {
|
||||||
|
// Opponent attack hits player
|
||||||
|
println("Opponent attack hits player at progress $progress")
|
||||||
|
battleSystem.startPlayerHit()
|
||||||
|
} else {
|
||||||
|
// Opponent attack misses, player dodges
|
||||||
|
println("Opponent attack misses, player dodges at progress $progress")
|
||||||
|
battleSystem.startPlayerDodge()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delay(16) // 60 FPS
|
delay(16) // 60 FPS
|
||||||
}
|
}
|
||||||
println("Phase 4 completed, applying damage and resetting")
|
println("Phase 4 completed, applying damage and resetting")
|
||||||
@ -158,6 +202,112 @@ fun BattleScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Player dodge animation
|
||||||
|
LaunchedEffect(battleSystem.isPlayerDodging) {
|
||||||
|
if (battleSystem.isPlayerDodging) {
|
||||||
|
println("Starting player dodge animation")
|
||||||
|
var dodgeProgress = 0f
|
||||||
|
var dodgeDirection = 1f // Start moving up
|
||||||
|
|
||||||
|
// Move up
|
||||||
|
while (dodgeProgress < 1f) {
|
||||||
|
dodgeProgress += 0.05f // Faster dodge movement
|
||||||
|
battleSystem.setDodgeProgress(dodgeProgress)
|
||||||
|
battleSystem.setDodgeDirection(dodgeDirection)
|
||||||
|
delay(16) // 60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait at the top
|
||||||
|
delay(200)
|
||||||
|
|
||||||
|
// Move back down
|
||||||
|
dodgeDirection = -1f
|
||||||
|
dodgeProgress = 0f
|
||||||
|
while (dodgeProgress < 1f) {
|
||||||
|
dodgeProgress += 0.05f
|
||||||
|
battleSystem.setDodgeProgress(dodgeProgress)
|
||||||
|
battleSystem.setDodgeDirection(dodgeDirection)
|
||||||
|
delay(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
battleSystem.endPlayerDodge()
|
||||||
|
println("Player dodge animation completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opponent dodge animation
|
||||||
|
LaunchedEffect(battleSystem.isOpponentDodging) {
|
||||||
|
if (battleSystem.isOpponentDodging) {
|
||||||
|
println("Starting opponent dodge animation")
|
||||||
|
var dodgeProgress = 0f
|
||||||
|
var dodgeDirection = 1f // Start moving up
|
||||||
|
|
||||||
|
// Move up
|
||||||
|
while (dodgeProgress < 1f) {
|
||||||
|
dodgeProgress += 0.05f // Faster dodge movement
|
||||||
|
battleSystem.setDodgeProgress(dodgeProgress)
|
||||||
|
battleSystem.setDodgeDirection(dodgeDirection)
|
||||||
|
delay(16) // 60 FPS
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait at the top
|
||||||
|
delay(200)
|
||||||
|
|
||||||
|
// Move back down
|
||||||
|
dodgeDirection = -1f
|
||||||
|
dodgeProgress = 0f
|
||||||
|
while (dodgeProgress < 1f) {
|
||||||
|
dodgeProgress += 0.05f
|
||||||
|
battleSystem.setDodgeProgress(dodgeProgress)
|
||||||
|
battleSystem.setDodgeDirection(dodgeDirection)
|
||||||
|
delay(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
battleSystem.endOpponentDodge()
|
||||||
|
println("Opponent dodge animation completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Player hit animation
|
||||||
|
LaunchedEffect(battleSystem.isPlayerHit) {
|
||||||
|
if (battleSystem.isPlayerHit) {
|
||||||
|
println("Starting player hit animation")
|
||||||
|
var hitProgress = 0f
|
||||||
|
|
||||||
|
// Quick hit effect
|
||||||
|
while (hitProgress < 1f) {
|
||||||
|
hitProgress += 0.1f // Fast hit effect
|
||||||
|
battleSystem.setHitProgress(hitProgress)
|
||||||
|
delay(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(100) // Brief pause
|
||||||
|
|
||||||
|
battleSystem.endPlayerHit()
|
||||||
|
println("Player hit animation completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opponent hit animation
|
||||||
|
LaunchedEffect(battleSystem.isOpponentHit) {
|
||||||
|
if (battleSystem.isOpponentHit) {
|
||||||
|
println("Starting opponent hit animation")
|
||||||
|
var hitProgress = 0f
|
||||||
|
|
||||||
|
// Quick hit effect
|
||||||
|
while (hitProgress < 1f) {
|
||||||
|
hitProgress += 0.1f // Fast hit effect
|
||||||
|
battleSystem.setHitProgress(hitProgress)
|
||||||
|
delay(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(100) // Brief pause
|
||||||
|
|
||||||
|
battleSystem.endOpponentHit()
|
||||||
|
println("Opponent hit animation completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@ -179,7 +329,8 @@ fun BattleScreen(
|
|||||||
onSetPendingDamage = { playerDamage, opponentDamage ->
|
onSetPendingDamage = { playerDamage, opponentDamage ->
|
||||||
pendingPlayerDamage = playerDamage
|
pendingPlayerDamage = playerDamage
|
||||||
pendingOpponentDamage = opponentDamage
|
pendingOpponentDamage = opponentDamage
|
||||||
}
|
},
|
||||||
|
coroutineScope = coroutineScope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
@ -207,12 +358,14 @@ fun PlayerBattleView(
|
|||||||
activeCharacter: APIBattleCharacter?,
|
activeCharacter: APIBattleCharacter?,
|
||||||
context: android.content.Context?,
|
context: android.content.Context?,
|
||||||
opponent: APIBattleCharacter?,
|
opponent: APIBattleCharacter?,
|
||||||
onSetPendingDamage: (Float, Float) -> Unit
|
onSetPendingDamage: (Float, Float) -> Unit,
|
||||||
|
coroutineScope: kotlinx.coroutines.CoroutineScope
|
||||||
) {
|
) {
|
||||||
// Track previous character ID to detect transitions
|
// Track previous character ID to detect transitions
|
||||||
var previousCharacterId by remember { mutableStateOf<String?>(null) }
|
var previousCharacterId by remember { mutableStateOf<String?>(null) }
|
||||||
var previousAttackPhase by remember { mutableStateOf<Int?>(null) }
|
var previousAttackPhase by remember { mutableStateOf<Int?>(null) }
|
||||||
var isTransitioning by remember { mutableStateOf(false) }
|
var isTransitioning by remember { mutableStateOf(false) }
|
||||||
|
var lastApiResult by remember { mutableStateOf<com.github.nacabaro.vbhelper.battle.PVPDataModel?>(null) }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
@ -238,6 +391,16 @@ fun PlayerBattleView(
|
|||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Debug display
|
||||||
|
if (lastApiResult != null) {
|
||||||
|
Text(
|
||||||
|
text = "Debug: state=${lastApiResult!!.state}, playerAttackHit=${lastApiResult!!.playerAttackHit}, opponentDamage=${lastApiResult!!.opponentAttackDamage}",
|
||||||
|
color = Color.Red,
|
||||||
|
fontSize = 10.sp
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
|
||||||
// Health bar
|
// Health bar
|
||||||
LinearProgressIndicator(
|
LinearProgressIndicator(
|
||||||
progress = battleSystem.playerHP / (activeCharacter?.baseHp?.toFloat() ?: 100f),
|
progress = battleSystem.playerHP / (activeCharacter?.baseHp?.toFloat() ?: 100f),
|
||||||
@ -271,20 +434,54 @@ fun PlayerBattleView(
|
|||||||
contentAlignment = Alignment.CenterStart
|
contentAlignment = Alignment.CenterStart
|
||||||
) {
|
) {
|
||||||
// Determine animation type based on battle state
|
// Determine animation type based on battle state
|
||||||
val animationType = when (battleSystem.attackPhase) {
|
val animationType = when {
|
||||||
1 -> DigimonAnimationType.ATTACK // Player attack on player screen
|
battleSystem.isPlayerDodging -> DigimonAnimationType.WALK // Use walk animation for dodge
|
||||||
2 -> DigimonAnimationType.ATTACK // Player attack on opponent screen
|
battleSystem.isPlayerHit -> DigimonAnimationType.SLEEP // Use sleep animation for hit effect (injured sprite)
|
||||||
3 -> DigimonAnimationType.IDLE // Opponent attack on opponent screen
|
battleSystem.attackPhase == 1 -> DigimonAnimationType.ATTACK // Player attack on player screen
|
||||||
4 -> DigimonAnimationType.IDLE // Opponent attack on player screen
|
battleSystem.attackPhase == 2 -> DigimonAnimationType.ATTACK // Player attack on opponent screen
|
||||||
|
battleSystem.attackPhase == 3 -> DigimonAnimationType.IDLE // Opponent attack on opponent screen
|
||||||
|
battleSystem.attackPhase == 4 -> DigimonAnimationType.IDLE // Opponent attack on player screen
|
||||||
else -> DigimonAnimationType.IDLE
|
else -> DigimonAnimationType.IDLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate vertical offset for dodge animation
|
||||||
|
val verticalOffset = if (battleSystem.isPlayerDodging) {
|
||||||
|
val dodgeHeight = 30.dp
|
||||||
|
val progress = battleSystem.dodgeProgress
|
||||||
|
val direction = battleSystem.dodgeDirection
|
||||||
|
|
||||||
|
if (direction > 0) {
|
||||||
|
// Moving up
|
||||||
|
(progress * dodgeHeight.value).dp
|
||||||
|
} else {
|
||||||
|
// Moving back down
|
||||||
|
((1f - progress) * dodgeHeight.value).dp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
0.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate hit effect (slight shake)
|
||||||
|
val hitOffset = if (battleSystem.isPlayerHit) {
|
||||||
|
val shakeAmount = 5.dp
|
||||||
|
val progress = battleSystem.hitProgress
|
||||||
|
// Simple shake effect without complex math
|
||||||
|
val shake = if (progress < 0.5f) progress * 2f else (1f - progress) * 2f
|
||||||
|
(shake * shakeAmount.value).dp
|
||||||
|
} else {
|
||||||
|
0.dp
|
||||||
|
}
|
||||||
|
|
||||||
AnimatedSpriteImage(
|
AnimatedSpriteImage(
|
||||||
characterId = activeCharacter?.charaId ?: "dim011_mon01",
|
characterId = activeCharacter?.charaId ?: "dim011_mon01",
|
||||||
animationType = animationType,
|
animationType = animationType,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(80.dp)
|
.size(80.dp)
|
||||||
.scale(-1f, 1f), // Flip player Digimon horizontally
|
.scale(-1f, 1f) // Flip player Digimon horizontally
|
||||||
|
.offset(
|
||||||
|
x = hitOffset,
|
||||||
|
y = verticalOffset
|
||||||
|
),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false
|
||||||
)
|
)
|
||||||
@ -407,6 +604,7 @@ fun PlayerBattleView(
|
|||||||
) { apiResult ->
|
) { apiResult ->
|
||||||
// Handle API response here
|
// Handle API response here
|
||||||
println("API Result: $apiResult")
|
println("API Result: $apiResult")
|
||||||
|
lastApiResult = apiResult // Store for debug display
|
||||||
|
|
||||||
// Update HP based on API response
|
// Update HP based on API response
|
||||||
when (apiResult.state) {
|
when (apiResult.state) {
|
||||||
@ -415,16 +613,33 @@ fun PlayerBattleView(
|
|||||||
println("Round ${apiResult.currentRound}: Player HP=${apiResult.playerHP}, Opponent HP=${apiResult.opponentHP}")
|
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.playerAttackHit) {
|
if (apiResult.playerAttackDamage > 0) {
|
||||||
// Player attack hit - enemy takes damage at end of player animation
|
// Player attack hit - enemy takes damage at end of player animation
|
||||||
println("Player attack hit! Enemy will take ${apiResult.playerAttackDamage} damage")
|
println("Player attack hit! Enemy will take ${apiResult.playerAttackDamage} damage")
|
||||||
onSetPendingDamage(0f, apiResult.playerAttackDamage.toFloat()) // Opponent takes damage
|
onSetPendingDamage(0f, apiResult.playerAttackDamage.toFloat()) // Opponent takes damage
|
||||||
battleSystem.setAttackHitState(true)
|
battleSystem.setAttackHitState(true)
|
||||||
} else {
|
} else {
|
||||||
// Player attack missed - enemy counter-attacks and player takes damage
|
// Player attack missed - enemy counter-attacks
|
||||||
println("Player attack missed! Enemy counter-attacks and player takes ${apiResult.opponentAttackDamage} damage")
|
println("Player attack missed! Enemy counter-attacks")
|
||||||
onSetPendingDamage(apiResult.opponentAttackDamage.toFloat(), 0f) // Player takes damage
|
|
||||||
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}")
|
||||||
|
println("Full API response: status=${apiResult.status}, state=${apiResult.state}, playerAttackHit=${apiResult.playerAttackHit}, playerAttackDamage=${apiResult.playerAttackDamage}, opponentAttackDamage=${apiResult.opponentAttackDamage}, playerHP=${apiResult.playerHP}, opponentHP=${apiResult.opponentHP}")
|
||||||
|
println("DEBUG: Using playerAttackDamage > 0 instead of playerAttackHit for hit detection")
|
||||||
|
|
||||||
|
// Use opponentAttackDamage to determine counter-attack hit
|
||||||
|
val finalCounterAttackHits = counterAttackHits
|
||||||
|
println("Using opponentAttackDamage > 0 for counter-attack: $finalCounterAttackHits")
|
||||||
|
|
||||||
|
if (finalCounterAttackHits) {
|
||||||
|
println("Counter-attack hits! Player takes ${apiResult.opponentAttackDamage} damage")
|
||||||
|
onSetPendingDamage(apiResult.opponentAttackDamage.toFloat(), 0f) // Player takes damage
|
||||||
|
} else {
|
||||||
|
println("Counter-attack misses! Player dodges")
|
||||||
|
onSetPendingDamage(0f, 0f) // No damage
|
||||||
|
}
|
||||||
|
battleSystem.setupCounterAttack(finalCounterAttackHits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 -> {
|
2 -> {
|
||||||
@ -515,18 +730,53 @@ fun OpponentBattleView(
|
|||||||
contentAlignment = Alignment.CenterEnd
|
contentAlignment = Alignment.CenterEnd
|
||||||
) {
|
) {
|
||||||
// Determine animation type based on battle state
|
// Determine animation type based on battle state
|
||||||
val animationType = when (battleSystem.attackPhase) {
|
val animationType = when {
|
||||||
1 -> DigimonAnimationType.IDLE // Player attack on player screen
|
battleSystem.isOpponentDodging -> DigimonAnimationType.WALK // Use walk animation for dodge
|
||||||
2 -> DigimonAnimationType.IDLE // Player attack on opponent screen
|
battleSystem.isOpponentHit -> DigimonAnimationType.SLEEP // Use sleep animation for hit effect (injured sprite)
|
||||||
3 -> DigimonAnimationType.ATTACK // Opponent attack on opponent screen
|
battleSystem.attackPhase == 1 -> DigimonAnimationType.IDLE // Player attack on player screen
|
||||||
4 -> DigimonAnimationType.ATTACK // Opponent attack on player screen
|
battleSystem.attackPhase == 2 -> DigimonAnimationType.IDLE // Player attack on opponent screen
|
||||||
|
battleSystem.attackPhase == 3 -> DigimonAnimationType.ATTACK // Opponent attack on opponent screen
|
||||||
|
battleSystem.attackPhase == 4 -> DigimonAnimationType.ATTACK // Opponent attack on player screen
|
||||||
else -> DigimonAnimationType.IDLE
|
else -> DigimonAnimationType.IDLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate vertical offset for dodge animation
|
||||||
|
val verticalOffset = if (battleSystem.isOpponentDodging) {
|
||||||
|
val dodgeHeight = 30.dp
|
||||||
|
val progress = battleSystem.dodgeProgress
|
||||||
|
val direction = battleSystem.dodgeDirection
|
||||||
|
|
||||||
|
if (direction > 0) {
|
||||||
|
// Moving up
|
||||||
|
(progress * dodgeHeight.value).dp
|
||||||
|
} else {
|
||||||
|
// Moving back down
|
||||||
|
((1f - progress) * dodgeHeight.value).dp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
0.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate hit effect (slight shake)
|
||||||
|
val hitOffset = if (battleSystem.isOpponentHit) {
|
||||||
|
val shakeAmount = 5.dp
|
||||||
|
val progress = battleSystem.hitProgress
|
||||||
|
// Simple shake effect without complex math
|
||||||
|
val shake = if (progress < 0.5f) progress * 2f else (1f - progress) * 2f
|
||||||
|
(shake * shakeAmount.value).dp
|
||||||
|
} else {
|
||||||
|
0.dp
|
||||||
|
}
|
||||||
|
|
||||||
AnimatedSpriteImage(
|
AnimatedSpriteImage(
|
||||||
characterId = activeCharacter?.charaId ?: "dim011_mon01",
|
characterId = activeCharacter?.charaId ?: "dim011_mon01",
|
||||||
animationType = animationType,
|
animationType = animationType,
|
||||||
modifier = Modifier.size(80.dp),
|
modifier = Modifier
|
||||||
|
.size(80.dp)
|
||||||
|
.offset(
|
||||||
|
x = hitOffset,
|
||||||
|
y = verticalOffset
|
||||||
|
),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user