Line data Source code
1 : import 'dart:async';
2 : import 'dart:ui';
3 :
4 : import 'package:flutter/painting.dart';
5 : import 'package:meta/meta.dart';
6 :
7 : import '../../components.dart';
8 : import '../../game.dart';
9 : import '../assets/images.dart';
10 : import '../extensions/vector2.dart';
11 : import '../game/game.dart';
12 : import '../parallax.dart';
13 : import 'position_component.dart';
14 :
15 : extension ParallaxComponentExtension on Game {
16 1 : Future<ParallaxComponent> loadParallaxComponent(
17 : List<ParallaxData> dataList, {
18 : Vector2? size,
19 : Vector2? baseVelocity,
20 : Vector2? velocityMultiplierDelta,
21 : ImageRepeat repeat = ImageRepeat.repeatX,
22 : Alignment alignment = Alignment.bottomLeft,
23 : LayerFill fill = LayerFill.height,
24 : int? priority,
25 : }) async {
26 2 : final component = await ParallaxComponent.load(
27 : dataList,
28 : size: size,
29 : baseVelocity: baseVelocity,
30 : velocityMultiplierDelta: velocityMultiplierDelta,
31 : repeat: repeat,
32 : alignment: alignment,
33 : fill: fill,
34 1 : images: images,
35 : priority: priority,
36 : );
37 :
38 : return component;
39 : }
40 : }
41 :
42 : /// A full parallax, several layers of images drawn out on the screen and each
43 : /// layer moves with different velocities to give an effect of depth.
44 : class ParallaxComponent<T extends BaseGame> extends PositionComponent
45 : with HasGameRef<T> {
46 : @override
47 : bool isHud = true;
48 : bool isFullscreen = true;
49 : Parallax? _parallax;
50 :
51 2 : Parallax? get parallax => _parallax;
52 1 : set parallax(Parallax? p) {
53 1 : _parallax = p;
54 3 : _parallax?.resize(size);
55 : }
56 :
57 : /// Creates a component with an empty parallax which can be set later.
58 1 : ParallaxComponent({
59 : Vector2? position,
60 : Vector2? size,
61 : int? priority,
62 1 : }) : super(position: position, size: size, priority: priority) {
63 : if (size != null) {
64 1 : isFullscreen = false;
65 : }
66 : }
67 :
68 : /// Creates a component from a [Parallax] object.
69 1 : factory ParallaxComponent.fromParallax(
70 : Parallax parallax, {
71 : Vector2? position,
72 : int? priority,
73 : }) {
74 1 : return ParallaxComponent(
75 : position: position,
76 2 : size: parallax.isSized ? parallax.size : null,
77 : priority: priority,
78 1 : )..parallax = parallax;
79 : }
80 :
81 1 : @mustCallSuper
82 : @override
83 : void onGameResize(Vector2 size) {
84 1 : super.onGameResize(size);
85 1 : if (!isFullscreen) {
86 : return;
87 : }
88 3 : final newSize = gameRef.viewport.effectiveSize;
89 2 : this.size.setFrom(newSize);
90 2 : parallax?.resize(newSize);
91 : }
92 :
93 1 : @override
94 : void update(double dt) {
95 1 : super.update(dt);
96 2 : parallax?.update(dt);
97 : }
98 :
99 0 : @mustCallSuper
100 : @override
101 : void render(Canvas canvas) {
102 0 : super.render(canvas);
103 0 : parallax?.render(canvas);
104 : }
105 :
106 : /// Note that this method only should be used if all of your layers should
107 : /// have the same layer arguments (how the images should be repeated, aligned
108 : /// and filled), otherwise load the [ParallaxLayer]s individually and use the
109 : /// normal constructor.
110 : ///
111 : /// [load] takes a list of [ParallaxData] of all the images and a size that you want to use in the
112 : /// parallax.
113 : ///
114 : /// Optionally arguments for the [baseVelocity] and [velocityMultiplierDelta] can be passed
115 : /// in, [baseVelocity] defines what the base velocity of the layers should be
116 : /// and [velocityMultiplierDelta] defines how the velocity should change the
117 : /// closer the layer is ([velocityMultiplierDelta ^ n], where n is the
118 : /// layer index).
119 : /// Arguments for how all the images should repeat ([repeat]),
120 : /// which edge it should align with ([alignment]), which axis it should fill
121 : /// the image on ([fill]) and [images] which is the image cache that should be
122 : /// used can also be passed in.
123 : ///
124 : /// If no image cache is set, the global flame cache is used.
125 1 : static Future<ParallaxComponent> load(
126 : List<ParallaxData> dataList, {
127 : Vector2? size,
128 : Vector2? baseVelocity,
129 : Vector2? velocityMultiplierDelta,
130 : ImageRepeat repeat = ImageRepeat.repeatX,
131 : Alignment alignment = Alignment.bottomLeft,
132 : LayerFill fill = LayerFill.height,
133 : Images? images,
134 : int? priority,
135 : }) async {
136 1 : final component = ParallaxComponent.fromParallax(
137 2 : await Parallax.load(
138 : dataList,
139 : size: size,
140 : baseVelocity: baseVelocity,
141 : velocityMultiplierDelta: velocityMultiplierDelta,
142 : repeat: repeat,
143 : alignment: alignment,
144 : fill: fill,
145 : images: images,
146 : ),
147 : priority: priority,
148 : );
149 :
150 : if (size != null) {
151 2 : component.size.setFrom(size);
152 : }
153 :
154 : return component;
155 : }
156 : }
|