mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-11-04 13:08:09 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:flutter/material.dart';
 | 
						|
import 'package:flame/sprite_animation.dart';
 | 
						|
 | 
						|
import 'dart:math';
 | 
						|
 | 
						|
import '../anchor.dart';
 | 
						|
import './sprite_widget.dart';
 | 
						|
 | 
						|
/// A [StatefulWidget] that render a [SpriteAnimation].
 | 
						|
class SpriteAnimationWidget extends StatefulWidget {
 | 
						|
  /// The [SpriteAnimation] to be rendered
 | 
						|
  final SpriteAnimation animation;
 | 
						|
 | 
						|
  /// The positioning [Anchor]
 | 
						|
  final Anchor anchor;
 | 
						|
 | 
						|
  /// Should the [animation] be playing or not
 | 
						|
  final bool playing;
 | 
						|
 | 
						|
  SpriteAnimationWidget({
 | 
						|
    this.animation,
 | 
						|
    this.playing = true,
 | 
						|
    this.anchor = Anchor.topLeft,
 | 
						|
  }) : assert(animation.loaded(), 'Animation must be loaded');
 | 
						|
 | 
						|
  @override
 | 
						|
  State createState() => _AnimationWidget();
 | 
						|
}
 | 
						|
 | 
						|
class _AnimationWidget extends State<SpriteAnimationWidget>
 | 
						|
    with SingleTickerProviderStateMixin {
 | 
						|
  AnimationController _controller;
 | 
						|
  double _lastUpdated;
 | 
						|
 | 
						|
  @override
 | 
						|
  void didUpdateWidget(oldWidget) {
 | 
						|
    super.didUpdateWidget(oldWidget);
 | 
						|
    if (widget.playing) {
 | 
						|
      _initAnimation();
 | 
						|
    } else {
 | 
						|
      _pauseAnimation();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  void initState() {
 | 
						|
    super.initState();
 | 
						|
 | 
						|
    _controller = AnimationController(vsync: this)
 | 
						|
      ..addListener(() {
 | 
						|
        final now = DateTime.now().millisecond.toDouble();
 | 
						|
 | 
						|
        final dt = max(0, (now - _lastUpdated) / 1000).toDouble();
 | 
						|
        widget.animation.update(dt);
 | 
						|
 | 
						|
        setState(() {
 | 
						|
          _lastUpdated = now;
 | 
						|
        });
 | 
						|
      });
 | 
						|
 | 
						|
    widget.animation.onComplete = _pauseAnimation;
 | 
						|
 | 
						|
    if (widget.playing) {
 | 
						|
      _initAnimation();
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void _initAnimation() {
 | 
						|
    setState(() {
 | 
						|
      widget.animation.reset();
 | 
						|
      _lastUpdated = DateTime.now().millisecond.toDouble();
 | 
						|
      _controller.repeat(
 | 
						|
        // Approximately 60 fps
 | 
						|
        period: const Duration(milliseconds: 16),
 | 
						|
      );
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  void _pauseAnimation() {
 | 
						|
    setState(() => _controller.stop());
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  void dispose() {
 | 
						|
    _controller.dispose();
 | 
						|
    super.dispose();
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(ctx) {
 | 
						|
    return SpriteWidget(
 | 
						|
      sprite: widget.animation.getSprite(),
 | 
						|
      anchor: widget.anchor,
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 |