diff options
Diffstat (limited to 'lib/level.dart')
-rw-r--r-- | lib/level.dart | 93 |
1 files changed, 55 insertions, 38 deletions
diff --git a/lib/level.dart b/lib/level.dart index a6d4967..4f69b67 100644 --- a/lib/level.dart +++ b/lib/level.dart @@ -1,15 +1,15 @@ import 'dart:async'; -import 'dart:io'; import 'package:flutter/material.dart'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/services.dart'; import 'package:sense_the_rhythm/arrows.dart'; +import 'package:sense_the_rhythm/game_over_stats.dart'; import 'package:sense_the_rhythm/simfile.dart'; class Level extends StatefulWidget { - const Level({super.key, required this.stepmaniaFolderPath}); - final String stepmaniaFolderPath; + const Level(this.simfile, {super.key}); + final Simfile simfile; @override State<Level> createState() => _LevelState(); @@ -22,9 +22,8 @@ class InputDirection { bool right = false; } -class _LevelState extends State<Level> { +class _LevelState extends State<Level> with SingleTickerProviderStateMixin { final player = AudioPlayer(); - Simfile? simfile; bool _isPlaying = true; Duration? _duration; Duration? _position; @@ -35,8 +34,13 @@ class _LevelState extends State<Level> { final FocusNode _focusNode = FocusNode(); InputDirection inputDirection = InputDirection(); + String hitOrMissMessage = 'Play!'; + List<Note> notes = []; + late AnimationController _animationController; + late Animation<double> _animation; + @override void setState(VoidCallback fn) { // Subscriptions only can be closed asynchronously, @@ -49,6 +53,15 @@ class _LevelState extends State<Level> { @override void 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 player.getDuration().then( (value) => setState(() { @@ -73,13 +86,24 @@ class _LevelState extends State<Level> { setState(() => _duration = d); }); + player.onPlayerComplete.listen((void _) { + Route route = MaterialPageRoute( + builder: (context) => GameOverStats( + simfile: widget.simfile, + notes: notes, + )); + Navigator.pushReplacement(context, route); + }); + player.onPositionChanged.listen((Duration p) { // print('Current position: $p'); setState(() => _position = p); for (final note in notes) { note.position = note.time - p.inMilliseconds / 60000.0; - - if (!note.wasHit && note.position.abs() < 0.5 * 1.0 / 60.0) { + if (note.wasHit != null) { + continue; + } + if (note.position.abs() < 0.5 * 1.0 / 60.0) { bool keypressCorrect = false; switch (note.direction) { case ArrowDirection.up: @@ -98,34 +122,25 @@ class _LevelState extends State<Level> { if (keypressCorrect) { print("you hit!"); note.wasHit = true; - - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('This is a toast message'), - duration: Duration(seconds: 2), - ), - ); + _animationController.reset(); + _animationController.forward(); + setState(() { + hitOrMissMessage = 'Great!'; + }); } + } else if (note.position < -0.5 * 1.0 / 60.0) { + print("Missed"); + note.wasHit = false; + _animationController.reset(); + _animationController.forward(); + setState(() { + hitOrMissMessage = 'Missed'; + }); } } }); - String simfilePath = Directory(widget.stepmaniaFolderPath) - .listSync() - .firstWhere((entity) => entity.path.endsWith('.sm'), - orElse: () => File('')) - .path; - - String audioPath = Directory(widget.stepmaniaFolderPath) - .listSync() - .firstWhere((entity) => entity.path.endsWith('.ogg'), - orElse: () => File('')) - .path; - - simfile = Simfile(simfilePath); - simfile!.load(); - - simfile!.chartSimplest!.beats.forEach((time, noteData) { + widget.simfile.chartSimplest!.beats.forEach((time, noteData) { int arrowIndex = noteData.indexOf('1'); if (arrowIndex < 0 || arrowIndex > 3) { return; @@ -133,9 +148,7 @@ class _LevelState extends State<Level> { notes.add(Note(time: time, direction: ArrowDirection.values[arrowIndex])); }); - print(audioPath); - - player.play(DeviceFileSource(audioPath)); + player.play(DeviceFileSource(widget.simfile.audioPath!)); } @override @@ -185,7 +198,7 @@ class _LevelState extends State<Level> { } }, ), - title: Text(widget.stepmaniaFolderPath.split('/').last), + title: Text(widget.simfile.tags['TITLE']!), actions: [ IconButton( icon: Icon(Icons.close), @@ -212,10 +225,13 @@ class _LevelState extends State<Level> { top: 50, width: MediaQuery.of(context).size.width, left: 0, - child: Text( - "Great!", - textScaler: TextScaler.linear(4), - textAlign: TextAlign.center, + child: FadeTransition( + opacity: _animation, + child: Text( + hitOrMissMessage, + textScaler: TextScaler.linear(4), + textAlign: TextAlign.center, + ), ), ), Positioned( @@ -235,6 +251,7 @@ class _LevelState extends State<Level> { @override void dispose() { + _animationController.dispose(); _durationSubscription?.cancel(); _positionSubscription?.cancel(); player.dispose(); |