Files
flutter_first_station/lib/muyu/muyu_page.dart
2023-05-16 20:28:08 +08:00

207 lines
5.0 KiB
Dart

import 'dart:math';
import 'package:flame_audio/flame_audio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_first_station/muyu/animate_text.dart';
import 'package:flutter_first_station/muyu/options/select_audio.dart';
import 'package:uuid/uuid.dart';
import '../storage/db_storage/db_storage.dart';
import '../storage/sp_storage.dart';
import 'models/audio_option.dart';
import 'models/image_option.dart';
import 'models/merit_record.dart';
import 'muyu_image.dart';
import 'count_panel.dart';
import 'muyu_app_bar.dart';
import 'options/select_image.dart';
import 'record_history.dart';
class MuyuPage extends StatefulWidget {
const MuyuPage({Key? key}) : super(key: key);
@override
State<MuyuPage> createState() => _MuyuPageState();
}
class _MuyuPageState extends State<MuyuPage>
with AutomaticKeepAliveClientMixin {
int _counter = 0;
MeritRecord? _cruRecord;
int _activeImageIndex = 0;
int _activeAudioIndex = 0;
final Random _random = Random();
final Uuid uuid = Uuid();
List<MeritRecord> _records = [];
final List<AudioOption> audioOptions = const [
AudioOption('音效1', 'muyu_1.mp3'),
AudioOption('音效2', 'muyu_2.mp3'),
AudioOption('音效3', 'muyu_3.mp3'),
];
final List<ImageOption> imageOptions = const [
ImageOption('基础版', 'assets/images/muyu.png', 1, 3),
ImageOption('尊享版', 'assets/images/muyu2.png', 3, 6),
];
AudioPool? pool;
@override
void initState() {
super.initState();
_initAudioPool();
_initConfig();
}
void _initConfig() async{
Map<String,dynamic> config = await SpStorage.instance.readMuYUConfig();
_counter = config['counter']??0;
_activeImageIndex = config['activeImageIndex']??0;
_activeAudioIndex = config['activeAudioIndex']??0;
_records = await DbStorage.instance.meritRecordDao.query();
setState(() {
});
}
void _initAudioPool() async {
pool = await FlameAudio.createPool(
audioOptions[_activeAudioIndex].src,
maxPlayers: 1,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MuyuAppBar(
onTapHistory: _toHistory,
),
body: Column(
children: [
Expanded(
child: CountPanel(
count: _counter,
onTapSwitchAudio: _onTapSwitchAudio,
onTapSwitchImage: _onTapSwitchImage,
),
),
Expanded(
child: Stack(
alignment: Alignment.topCenter,
children: [
MuyuAssetsImage(
image: activeImage,
onTap: _onKnock,
),
if (_cruRecord != null) AnimateText(record: _cruRecord!)
],
),
),
],
),
);
}
void _toHistory() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => RecordHistory(
records: _records.reversed.toList(),
),
),
);
}
void _onTapSwitchAudio() {
showCupertinoModalPopup(
context: context,
builder: (BuildContext context) {
return AudioOptionPanel(
audioOptions: audioOptions,
activeIndex: _activeAudioIndex,
onSelect: _onSelectAudio,
);
},
);
}
void _onTapSwitchImage() {
showCupertinoModalPopup(
context: context,
builder: (BuildContext context) {
return ImageOptionPanel(
imageOptions: imageOptions,
activeIndex: _activeImageIndex,
onSelect: _onSelectImage,
);
},
);
}
void _onKnock() {
pool?.start();
setState(() {
String id = uuid.v4();
_cruRecord = MeritRecord(
id,
DateTime.now().millisecondsSinceEpoch,
knockValue,
activeImage,
audioOptions[_activeAudioIndex].name,
);
_counter += _cruRecord!.value;
saveConfig();
DbStorage.instance.meritRecordDao.insert(_cruRecord!);
// 添加功德记录
_records.add(_cruRecord!);
});
}
void saveConfig() {
SpStorage.instance.saveMuYUConfig(
counter: _counter,
activeImageIndex: _activeImageIndex,
activeAudioIndex: _activeAudioIndex,
);
}
String get activeImage => imageOptions[_activeImageIndex].src;
int get knockValue {
int min = imageOptions[_activeImageIndex].min;
int max = imageOptions[_activeImageIndex].max;
return min + _random.nextInt(max + 1 - min);
}
void _onSelectImage(int value) {
Navigator.of(context).pop();
if (value == _activeImageIndex) return;
setState(() {
_activeImageIndex = value;
saveConfig();
});
}
String get activeAudio => audioOptions[_activeAudioIndex].src;
void _onSelectAudio(int value) async {
Navigator.of(context).pop();
if (value == _activeAudioIndex) return;
_activeAudioIndex = value;
saveConfig();
pool = await FlameAudio.createPool(
activeAudio,
maxPlayers: 1,
);
}
@override
bool get wantKeepAlive => true;
}