mirror of
https://github.com/nacabaro/vbhelper.git
synced 2026-06-05 22:02:54 +00:00
Offset idle animation so player/enemy Digimon aren't in sync.
This commit is contained in:
parent
d833a89c17
commit
371a850d45
@ -7,6 +7,7 @@ import androidx.compose.ui.graphics.asImageBitmap
|
|||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AnimatedSpriteImage(
|
fun AnimatedSpriteImage(
|
||||||
@ -14,11 +15,22 @@ fun AnimatedSpriteImage(
|
|||||||
animationType: DigimonAnimationType = DigimonAnimationType.IDLE,
|
animationType: DigimonAnimationType = DigimonAnimationType.IDLE,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
contentScale: ContentScale = ContentScale.Fit,
|
contentScale: ContentScale = ContentScale.Fit,
|
||||||
reloadMappings: Boolean = false
|
reloadMappings: Boolean = false,
|
||||||
|
animationOffset: Long = 0L // New parameter for offsetting animation timing
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val spriteManager = remember { IndividualSpriteManager(context) }
|
val spriteManager = remember { IndividualSpriteManager(context) }
|
||||||
val animationStateMachine = remember { DigimonAnimationStateMachine(characterId, context) }
|
|
||||||
|
// Calculate frame offset based on animation offset
|
||||||
|
// 750ms is the idle animation duration, so we calculate how many frames to offset
|
||||||
|
val frameOffset = if (animationOffset > 0L) {
|
||||||
|
// Convert time offset to frame offset (2 frames per cycle, 750ms per frame)
|
||||||
|
((animationOffset / 750L) * 2).toInt()
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
val animationStateMachine = remember { DigimonAnimationStateMachine(characterId, context, frameOffset, animationOffset) }
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
var bitmap by remember { mutableStateOf<android.graphics.Bitmap?>(null) }
|
||||||
|
|||||||
@ -31,7 +31,9 @@ data class AnimationState(
|
|||||||
|
|
||||||
class DigimonAnimationStateMachine(
|
class DigimonAnimationStateMachine(
|
||||||
private val characterId: String,
|
private val characterId: String,
|
||||||
private val context: Context
|
private val context: Context,
|
||||||
|
private val initialFrameOffset: Int = 0, // New parameter for offsetting the starting frame
|
||||||
|
private val timingOffset: Long = 0L // New parameter for offsetting the timing
|
||||||
) {
|
) {
|
||||||
var currentAnimation by mutableStateOf<DigimonAnimationType>(DigimonAnimationType.IDLE)
|
var currentAnimation by mutableStateOf<DigimonAnimationType>(DigimonAnimationType.IDLE)
|
||||||
private set
|
private set
|
||||||
@ -79,7 +81,7 @@ class DigimonAnimationStateMachine(
|
|||||||
)
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
println("Initialized DigimonAnimationStateMachine for character: $characterId")
|
println("Initialized DigimonAnimationStateMachine for character: $characterId with frame offset: $initialFrameOffset, timing offset: $timingOffset")
|
||||||
println("Available animation types: ${animationTypeToFrames.keys}")
|
println("Available animation types: ${animationTypeToFrames.keys}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,12 +130,17 @@ class DigimonAnimationStateMachine(
|
|||||||
// Combine frames for cycling idle animation
|
// Combine frames for cycling idle animation
|
||||||
val combinedFrames = (idleFrames + idle2Frames).distinct()
|
val combinedFrames = (idleFrames + idle2Frames).distinct()
|
||||||
|
|
||||||
println("Playing idle animation with frames: $combinedFrames")
|
println("Playing idle animation with frames: $combinedFrames, starting at offset: $initialFrameOffset, timing offset: $timingOffset")
|
||||||
|
|
||||||
val duration = animationDurations[DigimonAnimationType.IDLE] ?: 500L
|
val duration = animationDurations[DigimonAnimationType.IDLE] ?: 500L
|
||||||
|
|
||||||
// Cycle through idle frames
|
// Apply initial timing offset
|
||||||
var frameIndex = 0
|
if (timingOffset > 0L) {
|
||||||
|
delay(timingOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cycle through idle frames, starting from the offset
|
||||||
|
var frameIndex = initialFrameOffset
|
||||||
while (isPlaying && currentAnimation == DigimonAnimationType.IDLE) {
|
while (isPlaying && currentAnimation == DigimonAnimationType.IDLE) {
|
||||||
val frameNumber = combinedFrames[frameIndex % combinedFrames.size]
|
val frameNumber = combinedFrames[frameIndex % combinedFrames.size]
|
||||||
currentFrameNumber = frameNumber
|
currentFrameNumber = frameNumber
|
||||||
|
|||||||
@ -730,7 +730,8 @@ fun MiddleBattleView(
|
|||||||
y = enemyVerticalOffset + 40.dp
|
y = enemyVerticalOffset + 40.dp
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false,
|
||||||
|
animationOffset = 375L // Offset enemy animation by half the idle duration
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enemy attack sprite (Phase 1 only)
|
// Enemy attack sprite (Phase 1 only)
|
||||||
@ -811,7 +812,8 @@ fun MiddleBattleView(
|
|||||||
y = playerVerticalOffset - 40.dp
|
y = playerVerticalOffset - 40.dp
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false,
|
||||||
|
animationOffset = 0L // Player animation starts immediately
|
||||||
)
|
)
|
||||||
|
|
||||||
// Player attack sprite (Phase 1 only)
|
// Player attack sprite (Phase 1 only)
|
||||||
@ -1149,7 +1151,8 @@ fun PlayerBattleView(
|
|||||||
y = verticalOffset
|
y = verticalOffset
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false,
|
||||||
|
animationOffset = 0L // Player animation starts immediately
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attack sprite visibility and positioning based on attack phase
|
// Attack sprite visibility and positioning based on attack phase
|
||||||
@ -1456,7 +1459,8 @@ fun EnemyBattleView(
|
|||||||
y = verticalOffset
|
y = verticalOffset
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false,
|
||||||
|
animationOffset = 375L // Offset enemy animation by half the idle duration
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attack sprite visibility and positioning based on attack phase
|
// Attack sprite visibility and positioning based on attack phase
|
||||||
@ -1797,7 +1801,8 @@ fun BattlesScreen() {
|
|||||||
animationType = currentTestAnimation,
|
animationType = currentTestAnimation,
|
||||||
modifier = Modifier.size(120.dp),
|
modifier = Modifier.size(120.dp),
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
reloadMappings = false
|
reloadMappings = false,
|
||||||
|
animationOffset = 0L // No offset for sprite tester
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user