292 lines
6.9 KiB
Dart
292 lines
6.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../game/config/theme_config.dart';
|
|
import '../../game/config/animation_config.dart';
|
|
|
|
class FloatingDamageText extends StatefulWidget {
|
|
final String damage;
|
|
final Color color;
|
|
final VoidCallback onRemove;
|
|
|
|
const FloatingDamageText({
|
|
Key? key,
|
|
required this.damage,
|
|
required this.color,
|
|
required this.onRemove,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
FloatingDamageTextState createState() => FloatingDamageTextState();
|
|
}
|
|
|
|
class FloatingDamageTextState extends State<FloatingDamageText>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
late Animation<Offset> _offsetAnimation;
|
|
late Animation<double> _opacityAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
duration: AnimationConfig.floatingTextDuration,
|
|
vsync: this,
|
|
);
|
|
|
|
_offsetAnimation =
|
|
Tween<Offset>(
|
|
begin: const Offset(0.0, 0.0),
|
|
end: const Offset(0.0, -1.5),
|
|
).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: AnimationConfig.floatingTextCurve,
|
|
),
|
|
);
|
|
|
|
_opacityAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: const Interval(0.5, 1.0, curve: Curves.easeOut),
|
|
),
|
|
);
|
|
|
|
_controller.forward().then((_) {
|
|
if (mounted) {
|
|
widget.onRemove();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AnimatedBuilder(
|
|
animation: _controller,
|
|
builder: (context, child) {
|
|
return FractionalTranslation(
|
|
translation: _offsetAnimation.value,
|
|
child: Opacity(
|
|
opacity: _opacityAnimation.value,
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
child: Text(
|
|
widget.damage,
|
|
style: TextStyle(
|
|
color: widget.color,
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
shadows: const [
|
|
Shadow(
|
|
blurRadius: 2.0,
|
|
color: ThemeConfig.feedbackShadow,
|
|
offset: Offset(1.0, 1.0),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class DamageTextData {
|
|
final String id;
|
|
final Widget widget;
|
|
|
|
DamageTextData({required this.id, required this.widget});
|
|
}
|
|
|
|
class FloatingEffect extends StatefulWidget {
|
|
final IconData icon;
|
|
final Color color;
|
|
final double size;
|
|
final VoidCallback onRemove;
|
|
|
|
const FloatingEffect({
|
|
Key? key,
|
|
required this.icon,
|
|
required this.color,
|
|
required this.size,
|
|
required this.onRemove,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
FloatingEffectState createState() => FloatingEffectState();
|
|
}
|
|
|
|
class FloatingEffectState extends State<FloatingEffect>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
late Animation<double> _scaleAnimation;
|
|
late Animation<double> _opacityAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
duration: AnimationConfig.floatingEffectDuration,
|
|
vsync: this,
|
|
);
|
|
|
|
_scaleAnimation = Tween<double>(begin: 0.5, end: 1.5).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: AnimationConfig.floatingEffectScaleCurve,
|
|
),
|
|
);
|
|
|
|
_opacityAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: const Interval(0.5, 1.0, curve: Curves.easeOut),
|
|
),
|
|
);
|
|
|
|
_controller.forward().then((_) {
|
|
if (mounted) {
|
|
widget.onRemove();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AnimatedBuilder(
|
|
animation: _controller,
|
|
builder: (context, child) {
|
|
return Transform.scale(
|
|
scale: _scaleAnimation.value,
|
|
child: Opacity(
|
|
opacity: _opacityAnimation.value,
|
|
child: Icon(widget.icon, color: widget.color, size: widget.size),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class FloatingEffectData {
|
|
final String id;
|
|
final Widget widget;
|
|
|
|
FloatingEffectData({required this.id, required this.widget});
|
|
}
|
|
|
|
class FloatingFeedbackText extends StatefulWidget {
|
|
final String feedback;
|
|
final Color color;
|
|
final VoidCallback onRemove;
|
|
|
|
const FloatingFeedbackText({
|
|
Key? key,
|
|
required this.feedback,
|
|
required this.color,
|
|
required this.onRemove,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
FloatingFeedbackTextState createState() => FloatingFeedbackTextState();
|
|
}
|
|
|
|
class FloatingFeedbackTextState extends State<FloatingFeedbackText>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
late Animation<Offset> _offsetAnimation;
|
|
late Animation<double> _opacityAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
duration: AnimationConfig.floatingTextDuration,
|
|
vsync: this,
|
|
);
|
|
|
|
_offsetAnimation =
|
|
Tween<Offset>(
|
|
begin: const Offset(0.0, 0.0),
|
|
end: const Offset(0.0, -1.5),
|
|
).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: AnimationConfig.floatingTextCurve,
|
|
),
|
|
);
|
|
|
|
_opacityAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
|
|
CurvedAnimation(
|
|
parent: _controller,
|
|
curve: const Interval(0.5, 1.0, curve: Curves.easeOut),
|
|
),
|
|
);
|
|
|
|
_controller.forward().then((_) {
|
|
if (mounted) {
|
|
widget.onRemove();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AnimatedBuilder(
|
|
animation: _controller,
|
|
builder: (context, child) {
|
|
return FractionalTranslation(
|
|
translation: _offsetAnimation.value,
|
|
child: Opacity(
|
|
opacity: _opacityAnimation.value,
|
|
child: Material(
|
|
color: Colors.transparent,
|
|
child: Text(
|
|
widget.feedback,
|
|
style: TextStyle(
|
|
color: widget.color,
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
shadows: const [
|
|
Shadow(
|
|
blurRadius: 2.0,
|
|
color: ThemeConfig.feedbackShadow,
|
|
offset: Offset(1.0, 1.0),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class FeedbackTextData {
|
|
final String id;
|
|
final Widget widget;
|
|
|
|
FeedbackTextData({required this.id, required this.widget});
|
|
}
|