mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-11-01 01:18:38 +08:00 
			
		
		
		
	🏷 Backport some code improvements from the null-safety branch (#603)
				
					
				
			This commit is contained in:
		| @ -1,6 +1,7 @@ | ||||
| # CHANGELOG | ||||
|  | ||||
| ## [next] | ||||
|  - Code improvements and preparing APIs to null-safety | ||||
|  - BaseComponent removes children marked as shouldRemove during update | ||||
|  - Use `find` instead of `globstar` pattern in `scripts/lint.sh` as the later isn't enabled by default in bash | ||||
|  - Fixes aseprite constructor bug | ||||
|  | ||||
| @ -21,18 +21,19 @@ void main() async { | ||||
|   ); | ||||
| } | ||||
|  | ||||
| const green = Color(0xAA338833); | ||||
| const red = Color(0xAA883333); | ||||
| const orange = Color(0xAABB6633); | ||||
|  | ||||
| class MyGame extends BaseGame with TapDetector { | ||||
|   Square greenSquare; | ||||
|   Square redSquare; | ||||
|   Square orangeSquare; | ||||
|  | ||||
|   MyGame() { | ||||
|     final green = Paint()..color = const Color(0xAA338833); | ||||
|     final red = Paint()..color = const Color(0xAA883333); | ||||
|     final orange = Paint()..color = const Color(0xAABB6633); | ||||
|     greenSquare = Square(green, Vector2.all(100)); | ||||
|     redSquare = Square(red, Vector2.all(200)); | ||||
|     orangeSquare = Square(orange, Vector2(200, 400)); | ||||
|   MyGame() | ||||
|       : greenSquare = Square(Paint()..color = green, Vector2.all(100)), | ||||
|         redSquare = Square(Paint()..color = red, Vector2.all(200)), | ||||
|         orangeSquare = Square(Paint()..color = orange, Vector2(200, 400)) { | ||||
|     add(greenSquare); | ||||
|     add(redSquare); | ||||
|     add(orangeSquare); | ||||
|  | ||||
| @ -74,12 +74,14 @@ class MyGame extends BaseGame | ||||
|   } | ||||
|  | ||||
|   void onPanEnd(DragEndDetails details) { | ||||
|     _panRect = Rect.fromLTRB( | ||||
|       _start.dx, | ||||
|       _start.dy, | ||||
|       _end.dx, | ||||
|       _end.dy, | ||||
|     ); | ||||
|     if (_start != null && _end != null) { | ||||
|       _panRect = Rect.fromLTRB( | ||||
|         _start.dx, | ||||
|         _start.dy, | ||||
|         _end.dx, | ||||
|         _end.dy, | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|  | ||||
| @ -25,14 +25,15 @@ class Player extends Component implements JoystickListener { | ||||
|  | ||||
|   @override | ||||
|   void render(Canvas canvas) { | ||||
|     if (_rect != null) { | ||||
|       canvas.save(); | ||||
|       canvas.translate(_rect.center.dx, _rect.center.dy); | ||||
|       canvas.rotate(radAngle == 0.0 ? 0.0 : radAngle + (pi / 2)); | ||||
|       canvas.translate(-_rect.center.dx, -_rect.center.dy); | ||||
|       canvas.drawRect(_rect, _paint); | ||||
|       canvas.restore(); | ||||
|     if (_rect == null) { | ||||
|       return; | ||||
|     } | ||||
|     canvas.save(); | ||||
|     canvas.translate(_rect.center.dx, _rect.center.dy); | ||||
|     canvas.rotate(radAngle == 0.0 ? 0.0 : radAngle + (pi / 2)); | ||||
|     canvas.translate(-_rect.center.dx, -_rect.center.dy); | ||||
|     canvas.drawRect(_rect, _paint); | ||||
|     canvas.restore(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
| @ -79,12 +80,15 @@ class Player extends Component implements JoystickListener { | ||||
|     final double nextX = (currentSpeed * dtUpdate) * cos(radAngle); | ||||
|     final double nextY = (currentSpeed * dtUpdate) * sin(radAngle); | ||||
|  | ||||
|     if (_rect == null) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     final Offset diffBase = Offset( | ||||
|           _rect.center.dx + nextX, | ||||
|           _rect.center.dy + nextY, | ||||
|         ) - | ||||
|         _rect.center; | ||||
|  | ||||
|     _rect = _rect.shift(diffBase); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -16,8 +16,6 @@ void main() async { | ||||
| } | ||||
|  | ||||
| class MyGame extends BaseGame { | ||||
|   SpriteAnimation animation; | ||||
|  | ||||
|   @override | ||||
|   Future<void> onLoad() async { | ||||
|     final image = await images.load('chopper.png'); | ||||
|  | ||||
| @ -108,8 +108,9 @@ void main() async { | ||||
|           child: SpriteWidget( | ||||
|             sprite: shieldSprite, | ||||
|             anchor: parseAnchor( | ||||
|               ctx.listProperty('anchor', 'Anchor.center', anchorOptions), | ||||
|             ), | ||||
|                   ctx.listProperty('anchor', 'Anchor.center', anchorOptions), | ||||
|                 ) ?? | ||||
|                 Anchor.topLeft, | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
| @ -134,8 +135,9 @@ void main() async { | ||||
|             animation: _animation, | ||||
|             playing: ctx.boolProperty('playing', true), | ||||
|             anchor: parseAnchor( | ||||
|               ctx.listProperty('anchor', 'Anchor.center', anchorOptions), | ||||
|             ), | ||||
|                   ctx.listProperty('anchor', 'Anchor.center', anchorOptions), | ||||
|                 ) ?? | ||||
|                 Anchor.topLeft, | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|  | ||||
| @ -34,11 +34,11 @@ class JoystickAction { | ||||
|   bool _dragging = false; | ||||
|   Sprite _spriteAction; | ||||
|   Offset _dragPosition; | ||||
|   Paint _paintBackground; | ||||
|   Paint _paintAction; | ||||
|   Paint _paintActionPressed; | ||||
|   final Paint _paintBackground; | ||||
|   final Paint _paintAction; | ||||
|   final Paint _paintActionPressed; | ||||
|   JoystickController _joystickController; | ||||
|   double _sizeBackgroundDirection; | ||||
|   final double _sizeBackgroundDirection; | ||||
|   DragEvent _currentDragEvent; | ||||
|   double _tileSize; | ||||
|  | ||||
| @ -55,9 +55,17 @@ class JoystickAction { | ||||
|     this.align = JoystickActionAlign.BOTTOM_RIGHT, | ||||
|     this.opacityBackground = 0.5, | ||||
|     this.opacityKnob = 0.8, | ||||
|   }) { | ||||
|     _spriteAction = sprite; | ||||
|     _sizeBackgroundDirection = sizeFactorBackgroundDirection * size; | ||||
|   })  : _spriteAction = sprite, | ||||
|         _sizeBackgroundDirection = sizeFactorBackgroundDirection * size, | ||||
|         _paintBackground = Paint() | ||||
|           ..color = color.withOpacity(opacityBackground) | ||||
|           ..style = PaintingStyle.fill, | ||||
|         _paintAction = Paint() | ||||
|           ..color = color.withOpacity(opacityKnob) | ||||
|           ..style = PaintingStyle.fill, | ||||
|         _paintActionPressed = Paint() | ||||
|           ..color = color.withOpacity(opacityBackground) | ||||
|           ..style = PaintingStyle.fill { | ||||
|     _tileSize = _sizeBackgroundDirection / 2; | ||||
|   } | ||||
|  | ||||
| @ -91,25 +99,6 @@ class JoystickAction { | ||||
|       center: Offset(dx, dy), | ||||
|       radius: _sizeBackgroundDirection / 2, | ||||
|     ); | ||||
|  | ||||
|     if (spriteBackgroundDirection == null) { | ||||
|       _paintBackground = Paint() | ||||
|         ..color = color.withOpacity(opacityBackground) | ||||
|         ..style = PaintingStyle.fill; | ||||
|     } | ||||
|  | ||||
|     if (sprite == null) { | ||||
|       _paintAction = Paint() | ||||
|         ..color = color.withOpacity(opacityKnob) | ||||
|         ..style = PaintingStyle.fill; | ||||
|     } | ||||
|  | ||||
|     if (spritePressed == null) { | ||||
|       _paintActionPressed = Paint() | ||||
|         ..color = color.withOpacity(opacityBackground) | ||||
|         ..style = PaintingStyle.fill; | ||||
|     } | ||||
|  | ||||
|     _dragPosition = _rectAction.center; | ||||
|   } | ||||
|  | ||||
| @ -128,7 +117,7 @@ class JoystickAction { | ||||
|   } | ||||
|  | ||||
|   void update(double dt) { | ||||
|     if (_dragging) { | ||||
|     if (_rectBackgroundDirection != null && _dragging) { | ||||
|       final double _radAngle = atan2( | ||||
|         _dragPosition.dy - _rectBackgroundDirection.center.dy, | ||||
|         _dragPosition.dx - _rectBackgroundDirection.center.dx, | ||||
| @ -149,13 +138,15 @@ class JoystickAction { | ||||
|       final double nextY = dist * sin(_radAngle); | ||||
|       final Offset nextPoint = Offset(nextX, nextY); | ||||
|  | ||||
|       final Offset diff = Offset( | ||||
|             _rectBackgroundDirection.center.dx + nextPoint.dx, | ||||
|             _rectBackgroundDirection.center.dy + nextPoint.dy, | ||||
|           ) - | ||||
|           _rectAction.center; | ||||
|       if (_rectAction != null) { | ||||
|         final Offset diff = Offset( | ||||
|               _rectBackgroundDirection.center.dx + nextPoint.dx, | ||||
|               _rectBackgroundDirection.center.dy + nextPoint.dy, | ||||
|             ) - | ||||
|             _rectAction.center; | ||||
|  | ||||
|       _rectAction = _rectAction.shift(diff); | ||||
|         _rectAction = _rectAction.shift(diff); | ||||
|       } | ||||
|  | ||||
|       final double _intensity = dist / _tileSize; | ||||
|  | ||||
| @ -176,24 +167,26 @@ class JoystickAction { | ||||
|   } | ||||
|  | ||||
|   void onReceiveDrag(DragEvent event) { | ||||
|     if (!_dragging && (_rectAction?.contains(event.initialPosition) ?? false)) { | ||||
|       if (enableDirection) { | ||||
|         _dragPosition = event.initialPosition; | ||||
|         _dragging = true; | ||||
|       } | ||||
|       _joystickController.joystickAction( | ||||
|         JoystickActionEvent( | ||||
|           id: actionId, | ||||
|           event: ActionEvent.DOWN, | ||||
|         ), | ||||
|       ); | ||||
|       tapDown(); | ||||
|       _currentDragEvent = event; | ||||
|       _currentDragEvent | ||||
|         ..onUpdate = onPanUpdate | ||||
|         ..onEnd = onPanEnd | ||||
|         ..onCancel = onPanCancel; | ||||
|     if (_dragging || !(_rectAction?.contains(event.initialPosition) ?? false)) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (enableDirection) { | ||||
|       _dragPosition = event.initialPosition; | ||||
|       _dragging = true; | ||||
|     } | ||||
|     _joystickController.joystickAction( | ||||
|       JoystickActionEvent( | ||||
|         id: actionId, | ||||
|         event: ActionEvent.DOWN, | ||||
|       ), | ||||
|     ); | ||||
|     tapDown(); | ||||
|     _currentDragEvent = event; | ||||
|     _currentDragEvent | ||||
|       ..onUpdate = onPanUpdate | ||||
|       ..onEnd = onPanEnd | ||||
|       ..onCancel = onPanCancel; | ||||
|   } | ||||
|  | ||||
|   void tapDown() { | ||||
|  | ||||
| @ -11,6 +11,8 @@ class JoystickUtils { | ||||
|     } | ||||
|  | ||||
|     if (sprite == null) { | ||||
|       assert(paint != null, '`paint` must not be `null` if `sprite` is `null`'); | ||||
|  | ||||
|       final double radius = rect.width / 2; | ||||
|       c.drawCircle( | ||||
|         Offset(rect.left + radius, rect.top + radius), | ||||
|  | ||||
| @ -34,7 +34,7 @@ class SpriteComponent extends PositionComponent { | ||||
|   @override | ||||
|   void render(Canvas canvas) { | ||||
|     super.render(canvas); | ||||
|     sprite.render( | ||||
|     sprite?.render( | ||||
|       canvas, | ||||
|       size: size, | ||||
|       overridePaint: overridePaint, | ||||
|  | ||||
| @ -28,11 +28,11 @@ class TextBoxConfig { | ||||
| class TextBoxComponent extends PositionComponent { | ||||
|   static final Paint _imagePaint = BasicPalette.white.paint | ||||
|     ..filterQuality = FilterQuality.high; | ||||
|   Vector2 _gameSize; | ||||
|   Vector2 _gameSize = Vector2.zero(); | ||||
|  | ||||
|   String _text; | ||||
|   TextConfig _config; | ||||
|   TextBoxConfig _boxConfig; | ||||
|   final String _text; | ||||
|   final TextConfig _config; | ||||
|   final TextBoxConfig _boxConfig; | ||||
|  | ||||
|   List<String> _lines; | ||||
|   double _maxLineWidth = 0.0; | ||||
| @ -53,15 +53,15 @@ class TextBoxComponent extends PositionComponent { | ||||
|     String text, { | ||||
|     TextConfig config, | ||||
|     TextBoxConfig boxConfig, | ||||
|   }) { | ||||
|     _boxConfig = boxConfig ?? TextBoxConfig(); | ||||
|     _config = config ?? TextConfig(); | ||||
|     _text = text; | ||||
|   })  : _text = text, | ||||
|         _boxConfig = boxConfig ?? TextBoxConfig(), | ||||
|         _config = config ?? TextConfig() { | ||||
|     _lines = []; | ||||
|     double lineHeight; | ||||
|     text.split(' ').forEach((word) { | ||||
|       final possibleLine = _lines.isEmpty ? word : _lines.last + ' ' + word; | ||||
|       final painter = _config.toTextPainter(possibleLine); | ||||
|       _lineHeight ??= painter.height; | ||||
|       lineHeight ??= painter.height; | ||||
|       if (painter.width <= | ||||
|           _boxConfig.maxWidth - _boxConfig.margins.horizontal) { | ||||
|         if (_lines.isNotEmpty) { | ||||
| @ -76,6 +76,7 @@ class TextBoxComponent extends PositionComponent { | ||||
|       } | ||||
|     }); | ||||
|     _totalLines = _lines.length; | ||||
|     _lineHeight = lineHeight ?? 0.0; | ||||
|   } | ||||
|  | ||||
|   void _updateMaxWidth(double w) { | ||||
|  | ||||
| @ -28,8 +28,8 @@ class TextComponent extends PositionComponent { | ||||
|     _updateBox(); | ||||
|   } | ||||
|  | ||||
|   TextComponent(this._text, {TextConfig config}) { | ||||
|     _config = config ?? TextConfig(); | ||||
|   TextComponent(this._text, {TextConfig config}) | ||||
|       : _config = config ?? TextConfig() { | ||||
|     _updateBox(); | ||||
|   } | ||||
|  | ||||
|  | ||||
| @ -47,8 +47,10 @@ class CombinedEffect extends PositionComponentEffect { | ||||
|           effect.originalAngle != effect.endAngle ? effect.endAngle : endAngle; | ||||
|       endSize = | ||||
|           effect.originalSize != effect.endSize ? effect.endSize : endSize; | ||||
|       peakTime = max(peakTime ?? 0, | ||||
|           effect.iterationTime + offset * effects.indexOf(effect)); | ||||
|       peakTime = max( | ||||
|         peakTime, | ||||
|         effect.iterationTime + offset * effects.indexOf(effect), | ||||
|       ); | ||||
|     }); | ||||
|     if (isAlternating) { | ||||
|       endPosition = originalPosition; | ||||
|  | ||||
| @ -30,8 +30,8 @@ abstract class ComponentEffect<T extends BaseComponent> { | ||||
|   final bool _initialIsInfinite; | ||||
|   final bool _initialIsAlternating; | ||||
|   double percentage; | ||||
|   double curveProgress; | ||||
|   double peakTime; | ||||
|   double curveProgress = 0.0; | ||||
|   double peakTime = 0.0; | ||||
|   double currentTime = 0.0; | ||||
|   double driftTime = 0.0; | ||||
|   int curveDirection = 1; | ||||
| @ -43,13 +43,12 @@ abstract class ComponentEffect<T extends BaseComponent> { | ||||
|     this._initialIsInfinite, | ||||
|     this._initialIsAlternating, { | ||||
|     this.isRelative = false, | ||||
|     this.curve = Curves.linear, | ||||
|     Curve curve, | ||||
|     this.onComplete, | ||||
|   }) { | ||||
|     isInfinite = _initialIsInfinite; | ||||
|     isAlternating = _initialIsAlternating; | ||||
|     curve ??= Curves.linear; | ||||
|   } | ||||
|   })  : assert(isRelative != null), | ||||
|         isInfinite = _initialIsInfinite, | ||||
|         isAlternating = _initialIsAlternating, | ||||
|         curve = curve ?? Curves.linear; | ||||
|  | ||||
|   @mustCallSuper | ||||
|   void update(double dt) { | ||||
| @ -171,12 +170,24 @@ abstract class PositionComponentEffect | ||||
|   void _setComponentState(Vector2 position, double angle, Vector2 size) { | ||||
|     if (isRootEffect()) { | ||||
|       if (modifiesPosition) { | ||||
|         assert( | ||||
|           position != null, | ||||
|           '`position` must not be `null` for an effect which modifies `position`', | ||||
|         ); | ||||
|         component?.position?.setFrom(position); | ||||
|       } | ||||
|       if (modifiesAngle) { | ||||
|         assert( | ||||
|           angle != null, | ||||
|           '`angle` must not be `null` for an effect which modifies `angle`', | ||||
|         ); | ||||
|         component?.angle = angle; | ||||
|       } | ||||
|       if (modifiesSize) { | ||||
|         assert( | ||||
|           size != null, | ||||
|           '`size` must not be `null` for an effect which modifies `size`', | ||||
|         ); | ||||
|         component?.size?.setFrom(size); | ||||
|       } | ||||
|     } | ||||
|  | ||||
| @ -50,8 +50,8 @@ class MoveEffect extends SimplePositionComponentEffect { | ||||
|         ); | ||||
|  | ||||
|   @override | ||||
|   void initialize(_comp) { | ||||
|     super.initialize(_comp); | ||||
|   void initialize(component) { | ||||
|     super.initialize(component); | ||||
|     List<Vector2> _movePath; | ||||
|     _startPosition = component.position.clone(); | ||||
|     // With relative here we mean that any vector in the list is relative | ||||
| @ -96,7 +96,11 @@ class MoveEffect extends SimplePositionComponentEffect { | ||||
|     } | ||||
|     final double totalPathLength = isAlternating ? pathLength * 2 : pathLength; | ||||
|     speed ??= totalPathLength / duration; | ||||
|  | ||||
|     // `duration` is not null when speed is null | ||||
|     duration ??= totalPathLength / speed; | ||||
|  | ||||
|     // `speed` is always not null here already | ||||
|     peakTime = isAlternating ? duration / 2 : duration; | ||||
|   } | ||||
|  | ||||
|  | ||||
| @ -34,8 +34,8 @@ class RotateEffect extends SimplePositionComponentEffect { | ||||
|         ); | ||||
|  | ||||
|   @override | ||||
|   void initialize(_comp) { | ||||
|     super.initialize(_comp); | ||||
|   void initialize(component) { | ||||
|     super.initialize(component); | ||||
|     _startAngle = component.angle; | ||||
|     _delta = isRelative ? angle : angle - _startAngle; | ||||
|     if (!isAlternating) { | ||||
| @ -49,6 +49,6 @@ class RotateEffect extends SimplePositionComponentEffect { | ||||
|   @override | ||||
|   void update(double dt) { | ||||
|     super.update(dt); | ||||
|     component.angle = _startAngle + _delta * curveProgress; | ||||
|     component?.angle = _startAngle + _delta * curveProgress; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -35,8 +35,8 @@ class ScaleEffect extends SimplePositionComponentEffect { | ||||
|         ); | ||||
|  | ||||
|   @override | ||||
|   void initialize(_comp) { | ||||
|     super.initialize(_comp); | ||||
|   void initialize(component) { | ||||
|     super.initialize(component); | ||||
|     _startSize = component.size; | ||||
|     _delta = isRelative ? size : size - _startSize; | ||||
|     if (!isAlternating) { | ||||
|  | ||||
| @ -5,10 +5,14 @@ import 'effects.dart'; | ||||
|  | ||||
| class SequenceEffect extends PositionComponentEffect { | ||||
|   final List<PositionComponentEffect> effects; | ||||
|   int _currentIndex; | ||||
|   PositionComponentEffect currentEffect; | ||||
|   bool _currentWasAlternating; | ||||
|   double _driftModifier; | ||||
|  | ||||
|   static const int _initialIndex = 0; | ||||
|   static const double _initialDriftModifier = 0.0; | ||||
|  | ||||
|   int _currentIndex = _initialIndex; | ||||
|   double _driftModifier = _initialDriftModifier; | ||||
|  | ||||
|   SequenceEffect({ | ||||
|     @required this.effects, | ||||
| @ -36,8 +40,8 @@ class SequenceEffect extends PositionComponentEffect { | ||||
|   @override | ||||
|   void initialize(PositionComponent component) { | ||||
|     super.initialize(component); | ||||
|     _currentIndex = 0; | ||||
|     _driftModifier = 0.0; | ||||
|     _currentIndex = _initialIndex; | ||||
|     _driftModifier = _initialDriftModifier; | ||||
|  | ||||
|     effects.forEach((effect) { | ||||
|       effect.reset(); | ||||
|  | ||||
| @ -14,8 +14,7 @@ import 'util.dart'; | ||||
| class Flame { | ||||
|   // Flame asset bundle, defaults to root | ||||
|   static AssetBundle _bundle; | ||||
|  | ||||
|   static AssetBundle get bundle => _bundle == null ? rootBundle : _bundle; | ||||
|   static AssetBundle get bundle => _bundle ?? rootBundle; | ||||
|  | ||||
|   /// Access a shared instance of [AssetsCache] class. | ||||
|   static AssetsCache assets = AssetsCache(); | ||||
|  | ||||
| @ -57,9 +57,7 @@ class BaseGame extends Game with FPSCounter { | ||||
|     } | ||||
|  | ||||
|     // first time resize | ||||
|     if (size != null) { | ||||
|       c.onGameResize(size); | ||||
|     } | ||||
|     c.onGameResize(size); | ||||
|   } | ||||
|  | ||||
|   /// Prepares and registers a component to be added on the next game tick | ||||
|  | ||||
| @ -134,12 +134,13 @@ class _GameWidgetState<T extends Game> extends State<GameWidget<T>> { | ||||
|   } | ||||
|  | ||||
|   void _initActiveOverlays() { | ||||
|     if (widget.initialActiveOverlays != null) { | ||||
|       _checkOverlays(widget.initialActiveOverlays.toSet()); | ||||
|       widget.initialActiveOverlays.forEach((key) { | ||||
|         widget.game.overlays.add(key); | ||||
|       }); | ||||
|     if (widget.initialActiveOverlays == null) { | ||||
|       return; | ||||
|     } | ||||
|     _checkOverlays(widget.initialActiveOverlays.toSet()); | ||||
|     widget.initialActiveOverlays.forEach((key) { | ||||
|       widget.game.overlays.add(key); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
| @ -175,8 +176,10 @@ class _GameWidgetState<T extends Game> extends State<GameWidget<T>> { | ||||
|  | ||||
|   void _checkOverlays(Set<String> overlays) { | ||||
|     overlays.forEach((overlayKey) { | ||||
|       assert(widget.overlayBuilderMap.containsKey(overlayKey), | ||||
|           "A non mapped overlay has been added: $overlayKey"); | ||||
|       assert( | ||||
|         widget.overlayBuilderMap?.containsKey(overlayKey) ?? false, | ||||
|         "A non mapped overlay has been added: $overlayKey", | ||||
|       ); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
| @ -472,10 +475,9 @@ Widget _applyAdvancedGesturesDetectors(Game game, Widget child) { | ||||
|       (MultiDragGestureRecognizer instance) { | ||||
|         instance | ||||
|           ..onStart = (Offset o) { | ||||
|             final drag = DragEvent(); | ||||
|             // Note that padding or margin isn't taken into account here | ||||
|             drag.initialPosition = o; | ||||
|             dragHandlers.forEach((h) => h.onReceiveDrag(drag)); | ||||
|             final drag = DragEvent(o); | ||||
|             dragHandlers.forEach((h) => h.onReceiveDrag?.call(drag)); | ||||
|             return drag; | ||||
|           }; | ||||
|       }, | ||||
|  | ||||
| @ -11,7 +11,9 @@ mixin MultiTouchTapDetector on Game { | ||||
| } | ||||
|  | ||||
| class DragEvent extends Drag { | ||||
|   Offset initialPosition; | ||||
|   final Offset initialPosition; | ||||
|  | ||||
|   DragEvent(this.initialPosition); | ||||
|  | ||||
|   void Function(DragUpdateDetails) onUpdate; | ||||
|   void Function() onCancel; | ||||
|  | ||||
| @ -5,7 +5,7 @@ abstract class LayerProcessor { | ||||
| } | ||||
|  | ||||
| class ShadowProcessor extends LayerProcessor { | ||||
|   Paint _shadowPaint; | ||||
|   final Paint _shadowPaint; | ||||
|  | ||||
|   final Offset offset; | ||||
|  | ||||
| @ -13,11 +13,9 @@ class ShadowProcessor extends LayerProcessor { | ||||
|     this.offset = const Offset(10, 10), | ||||
|     double opacity = 0.9, | ||||
|     Color color = const Color(0xFF000000), | ||||
|   }) { | ||||
|     _shadowPaint = Paint() | ||||
|       ..colorFilter = | ||||
|           ColorFilter.mode(color.withOpacity(opacity), BlendMode.srcATop); | ||||
|   } | ||||
|   }) : _shadowPaint = Paint() | ||||
|           ..colorFilter = | ||||
|               ColorFilter.mode(color.withOpacity(opacity), BlendMode.srcATop); | ||||
|  | ||||
|   @override | ||||
|   void process(Picture pic, Canvas canvas) { | ||||
|  | ||||
| @ -30,9 +30,9 @@ class NineTileBox { | ||||
|   /// | ||||
|   /// If [destTileSize] is not provided, the evaluated [tileSize] is used instead | ||||
|   /// (so no scaling happens). | ||||
|   NineTileBox(this.sprite, {int tileSize, int destTileSize}) { | ||||
|     this.tileSize = tileSize ?? sprite.src.width.toInt(); | ||||
|     this.destTileSize = destTileSize ?? tileSize; | ||||
|   NineTileBox(this.sprite, {int tileSize, int destTileSize}) | ||||
|       : tileSize = tileSize ?? sprite.src.width.toInt() { | ||||
|     this.destTileSize = destTileSize ?? this.tileSize; | ||||
|   } | ||||
|  | ||||
|   /// Renders this nine box with the dimensions provided by [rect]. | ||||
|  | ||||
| @ -121,10 +121,8 @@ class ParallaxLayer { | ||||
|   /// multiplying the [baseVelocity] with the [velocityMultiplier]. | ||||
|   ParallaxLayer( | ||||
|     this.parallaxImage, { | ||||
|     this.velocityMultiplier, | ||||
|   }) { | ||||
|     velocityMultiplier ??= Vector2.all(1.0); | ||||
|   } | ||||
|     Vector2 velocityMultiplier, | ||||
|   }) : velocityMultiplier = velocityMultiplier ?? Vector2.all(1.0); | ||||
|  | ||||
|   Vector2 currentOffset() => _scroll; | ||||
|  | ||||
| @ -241,10 +239,8 @@ class Parallax { | ||||
|  | ||||
|   Parallax( | ||||
|     this.layers, { | ||||
|     this.baseVelocity, | ||||
|   }) { | ||||
|     baseVelocity ??= Vector2.zero(); | ||||
|   } | ||||
|     Vector2 baseVelocity, | ||||
|   }) : baseVelocity = baseVelocity ?? Vector2.zero(); | ||||
|  | ||||
|   /// The base offset of the parallax, can be used in an outer update loop | ||||
|   /// if you want to transition the parallax to a certain position. | ||||
|  | ||||
| @ -19,7 +19,6 @@ class ComputedParticle extends Particle { | ||||
|   ComputedParticle({ | ||||
|     @required this.renderer, | ||||
|     double lifespan, | ||||
|     Duration duration, | ||||
|   }) : super( | ||||
|           lifespan: lifespan, | ||||
|         ); | ||||
|  | ||||
| @ -25,7 +25,7 @@ class RotatingParticle extends CurvedParticle with SingleChildParticle { | ||||
|           lifespan: lifespan, | ||||
|         ); | ||||
|  | ||||
|   double get angle => lerpDouble(from, to, progress); | ||||
|   double get angle => lerpDouble(from, to, progress) ?? 0; | ||||
|  | ||||
|   @override | ||||
|   void render(Canvas canvas) { | ||||
|  | ||||
| @ -10,7 +10,7 @@ import 'assets/images.dart'; | ||||
| class Sprite { | ||||
|   Paint paint = BasicPalette.white.paint; | ||||
|   Image image; | ||||
|   Rect src; | ||||
|   Rect src = Rect.zero; | ||||
|  | ||||
|   Sprite( | ||||
|     this.image, { | ||||
| @ -44,10 +44,10 @@ class Sprite { | ||||
|  | ||||
|   set srcSize(Vector2 size) { | ||||
|     size ??= Vector2Extension.fromInts(image.width, image.height); | ||||
|     src = (srcPosition ?? Vector2.zero()).toPositionedRect(size); | ||||
|     src = srcPosition.toPositionedRect(size); | ||||
|   } | ||||
|  | ||||
|   Vector2 get srcPosition => (src?.topLeft ?? Offset.zero).toVector2(); | ||||
|   Vector2 get srcPosition => src.topLeft.toVector2(); | ||||
|  | ||||
|   set srcPosition(Vector2 position) { | ||||
|     src = (position ?? Vector2.zero()).toPositionedRect(srcSize); | ||||
|  | ||||
| @ -50,7 +50,7 @@ class _AnimationWidget extends State<SpriteAnimationWidget> | ||||
|       ..addListener(() { | ||||
|         final now = DateTime.now().millisecond.toDouble(); | ||||
|  | ||||
|         final dt = max(0, (now - _lastUpdated) / 1000).toDouble(); | ||||
|         final dt = max(0, (now - (_lastUpdated ?? 0)) / 1000).toDouble(); | ||||
|         widget.animation.update(dt); | ||||
|  | ||||
|         setState(() { | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Serge Matveenko
					Serge Matveenko