feat: animate hit or miss message instead of snackbar

This commit is contained in:
Orangerot 2025-01-08 10:41:22 +01:00
parent c5cee0cb9d
commit 856949ceef

View file

@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart'; import 'package:audioplayers/audioplayers.dart';
@ -23,7 +22,7 @@ class InputDirection {
bool right = false; bool right = false;
} }
class _LevelState extends State<Level> { class _LevelState extends State<Level> with SingleTickerProviderStateMixin {
final player = AudioPlayer(); final player = AudioPlayer();
bool _isPlaying = true; bool _isPlaying = true;
Duration? _duration; Duration? _duration;
@ -35,8 +34,13 @@ class _LevelState extends State<Level> {
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
InputDirection inputDirection = InputDirection(); InputDirection inputDirection = InputDirection();
String hitOrMissMessage = 'Play!';
List<Note> notes = []; List<Note> notes = [];
late AnimationController _animationController;
late Animation<double> _animation;
@override @override
void setState(VoidCallback fn) { void setState(VoidCallback fn) {
// Subscriptions only can be closed asynchronously, // Subscriptions only can be closed asynchronously,
@ -49,6 +53,15 @@ class _LevelState extends State<Level> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2),
);
_animation =
Tween<double>(begin: 1.0, end: 0.0).animate(_animationController);
_animationController.forward();
// Use initial values from player // Use initial values from player
player.getDuration().then( player.getDuration().then(
(value) => setState(() { (value) => setState(() {
@ -109,23 +122,20 @@ class _LevelState extends State<Level> {
if (keypressCorrect) { if (keypressCorrect) {
print("you hit!"); print("you hit!");
note.wasHit = true; note.wasHit = true;
_animationController.reset();
ScaffoldMessenger.of(context).showSnackBar( _animationController.forward();
SnackBar( setState(() {
content: Text('Great!'), hitOrMissMessage = 'Great!';
duration: Duration(milliseconds: 500), });
),
);
} }
} else if (note.position < -0.5 * 1.0 / 60.0) { } else if (note.position < -0.5 * 1.0 / 60.0) {
print("Missed"); print("Missed");
note.wasHit = false; note.wasHit = false;
ScaffoldMessenger.of(context).showSnackBar( _animationController.reset();
SnackBar( _animationController.forward();
content: Text('Missed!'), setState(() {
duration: Duration(milliseconds: 500), hitOrMissMessage = 'Missed';
), });
);
} }
} }
}); });
@ -215,10 +225,13 @@ class _LevelState extends State<Level> {
top: 50, top: 50,
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
left: 0, left: 0,
child: Text( child: FadeTransition(
"Great!", opacity: _animation,
textScaler: TextScaler.linear(4), child: Text(
textAlign: TextAlign.center, hitOrMissMessage,
textScaler: TextScaler.linear(4),
textAlign: TextAlign.center,
),
), ),
), ),
Positioned( Positioned(
@ -238,6 +251,7 @@ class _LevelState extends State<Level> {
@override @override
void dispose() { void dispose() {
_animationController.dispose();
_durationSubscription?.cancel(); _durationSubscription?.cancel();
_positionSubscription?.cancel(); _positionSubscription?.cancel();
player.dispose(); player.dispose();