Compare commits
3 Commits
d63463a677
...
7e736df46c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e736df46c | ||
|
|
fbc3016ab1 | ||
|
|
464e5e9c22 |
BIN
assets/icon/AsciiNeverDieIcon.png
Normal file
BIN
assets/icon/AsciiNeverDieIcon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 203 KiB |
@@ -1,4 +1,4 @@
|
||||
import 'dart:async' show Completer, unawaited;
|
||||
import 'dart:async' show Completer;
|
||||
|
||||
import 'package:flutter/foundation.dart' show debugPrint, kIsWeb;
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
@@ -6,43 +6,6 @@ import 'package:just_audio/just_audio.dart';
|
||||
import 'package:asciineverdie/src/core/audio/sfx_channel_pool.dart';
|
||||
import 'package:asciineverdie/src/core/storage/settings_repository.dart';
|
||||
|
||||
/// BGM 작업 직렬화를 위한 간단한 뮤텍스
|
||||
class _BgmMutex {
|
||||
Completer<void>? _completer;
|
||||
String? _pendingBgm;
|
||||
|
||||
/// 현재 작업 중인지 확인
|
||||
bool get isLocked => _completer != null && !_completer!.isCompleted;
|
||||
|
||||
/// 락 획득 시도 (이미 잠겨있으면 대기 BGM 설정 후 false 반환)
|
||||
Future<bool> tryAcquire(String bgmName) async {
|
||||
if (isLocked) {
|
||||
// 이미 작업 중이면 대기 BGM 설정 (마지막 것만 유지)
|
||||
_pendingBgm = bgmName;
|
||||
return false;
|
||||
}
|
||||
_completer = Completer<void>();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 락 해제 및 대기 중인 BGM 반환
|
||||
String? release() {
|
||||
_completer?.complete();
|
||||
_completer = null;
|
||||
final pending = _pendingBgm;
|
||||
_pendingBgm = null;
|
||||
return pending;
|
||||
}
|
||||
|
||||
/// 강제 해제 (에러 시)
|
||||
void forceRelease() {
|
||||
if (_completer != null && !_completer!.isCompleted) {
|
||||
_completer!.complete();
|
||||
}
|
||||
_completer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 게임 오디오 서비스 (싱글톤, 핫 리로드 안전)
|
||||
///
|
||||
/// BGM과 SFX를 관리하며, 설정과 연동하여 볼륨을 조절합니다.
|
||||
@@ -122,9 +85,6 @@ class AudioService {
|
||||
// 오디오 일시정지 상태 (앱 백그라운드 시)
|
||||
bool _isPaused = false;
|
||||
|
||||
// BGM 작업 직렬화 뮤텍스 (동시 호출 방지)
|
||||
final _bgmMutex = _BgmMutex();
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// 초기화
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -242,32 +202,17 @@ class AudioService {
|
||||
// BGM 재생
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// BGM 재생 (뮤텍스로 동시 호출 방지)
|
||||
/// BGM 재생 (단순화된 버전)
|
||||
///
|
||||
/// 여러 곳에서 동시에 호출되어도 안전하게 처리합니다.
|
||||
/// 진행 중인 작업이 있으면 대기열에 추가하고, 완료 후 마지막 요청만 실행합니다.
|
||||
/// 여러 곳에서 동시에 호출되어도 마지막 요청만 처리합니다.
|
||||
Future<void> playBgm(String name) async {
|
||||
if (_isPaused) return;
|
||||
if (!_staticInitialized) await init();
|
||||
if (_currentBgm == name) return;
|
||||
if (_staticBgmPlayer == null) return;
|
||||
|
||||
// 뮤텍스 획득 시도 (실패하면 대기열에 추가)
|
||||
if (!await _bgmMutex.tryAcquire(name)) {
|
||||
debugPrint('[AudioService] BGM $name queued (mutex locked)');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await _playBgmInternal(name);
|
||||
} finally {
|
||||
// 락 해제 및 대기 중인 BGM 확인
|
||||
final pendingBgm = _bgmMutex.release();
|
||||
if (pendingBgm != null && pendingBgm != _currentBgm) {
|
||||
// 대기 중인 BGM이 있으면 재귀 호출 (새 뮤텍스 획득)
|
||||
unawaited(playBgm(pendingBgm));
|
||||
}
|
||||
}
|
||||
debugPrint('[AudioService] playBgm requested: $name');
|
||||
await _playBgmInternal(name);
|
||||
}
|
||||
|
||||
/// 내부 BGM 재생 (뮤텍스 내에서 호출)
|
||||
|
||||
@@ -256,6 +256,9 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
final taskType = state.progress.currentTask.type;
|
||||
final isInBattleTask = taskType == TaskType.kill;
|
||||
|
||||
debugPrint(
|
||||
'[BGM] TaskType: $taskType, isInBattle: $isInBattleTask, currentBgm: ${audio.currentBgm}');
|
||||
|
||||
// 전투 태스크 상태 결정
|
||||
if (isInBattleTask) {
|
||||
// 전투 태스크: 보스 여부에 따라 BGM 선택
|
||||
@@ -266,11 +269,15 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
// 전환 시점이거나 현재 BGM이 일치하지 않으면 재생
|
||||
if (!_wasInBattleTask || audio.currentBgm != expectedBgm) {
|
||||
debugPrint('[BGM] Playing battle BGM: $expectedBgm');
|
||||
audio.playBgm(expectedBgm);
|
||||
}
|
||||
} else if (_wasInBattleTask || audio.currentBgm == 'battle' || audio.currentBgm == 'boss') {
|
||||
// 전투 태스크 종료 또는 BGM 불일치: 마을 BGM으로 복귀
|
||||
audio.playBgm('town');
|
||||
} else {
|
||||
// 비전투 태스크: 항상 마을 BGM 유지 (이미 town이면 스킵)
|
||||
if (audio.currentBgm != 'town') {
|
||||
debugPrint('[BGM] Playing town BGM (was: ${audio.currentBgm})');
|
||||
audio.playBgm('town');
|
||||
}
|
||||
}
|
||||
|
||||
_wasInBattleTask = isInBattleTask;
|
||||
|
||||
Reference in New Issue
Block a user