mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 20:13:50 +08:00
Improving Parallax APIs regarding handling its size and the use outside FCS (#651)
* Improving Parallax APIs regarding handling its size and the use outside FCS * Formatting * Fixing flutter format vs flutter analyze crazy conflicts * Some suggestions * Removing unecessary line * Luan suggestions * Luan suggestion * Lukas suggestions * updating comment
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
- Moving render functions from `util.dart` to `extensions/canvas.dart`
|
||||
- Adapting ParallaxComponent contructors to match the pattern followed on other components
|
||||
- Adapting SpriteBatchComponent constructors to match the pattern used on other components
|
||||
- Improving Parallax APIs regarding handling its size and the use outside FCS
|
||||
- Enabling direct import of Sprite and SpriteAnimation
|
||||
- Renamed `Composition` to `ImageComposition` to prevent confusion with the composition component
|
||||
- Added `rotation` and `anchor` arguments to `ImageComposition.add`
|
||||
|
||||
@ -264,6 +264,7 @@ final layers = images.map((image) => ParallaxLayer(await image, velocityMulitpli
|
||||
final parallaxComponent = ParallaxComponent.fromParallax(
|
||||
Parallax(
|
||||
await Future.wait(layers),
|
||||
size, // size is a property on the Game class
|
||||
baseVelocity: Vector2(50, 0),
|
||||
),
|
||||
);
|
||||
|
||||
@ -24,11 +24,10 @@ class MyGame extends BaseGame {
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
final parallax = await ParallaxComponent.load(
|
||||
final parallax = await loadParallaxComponent(
|
||||
_imageNames,
|
||||
baseVelocity: Vector2(20, 0),
|
||||
velocityMultiplierDelta: Vector2(1.8, 1.0),
|
||||
images: images,
|
||||
);
|
||||
add(parallax);
|
||||
}
|
||||
|
||||
@ -34,6 +34,7 @@ class MyGame extends BaseGame {
|
||||
final parallax = ParallaxComponent.fromParallax(
|
||||
Parallax(
|
||||
await Future.wait(layers),
|
||||
size,
|
||||
baseVelocity: Vector2(20, 0),
|
||||
),
|
||||
);
|
||||
|
||||
@ -32,6 +32,7 @@ class MyParallaxComponent extends ParallaxComponent with HasGameRef<MyGame> {
|
||||
'trees.png',
|
||||
'foreground-trees.png',
|
||||
],
|
||||
size,
|
||||
baseVelocity: Vector2(20, 0),
|
||||
velocityMultiplierDelta: Vector2(1.8, 1.0),
|
||||
);
|
||||
|
||||
51
doc/examples/parallax/lib/main_game.dart
Normal file
51
doc/examples/parallax/lib/main_game.dart
Normal file
@ -0,0 +1,51 @@
|
||||
import 'package:flame/components.dart';
|
||||
import 'package:flame/flame.dart';
|
||||
import 'package:flame/game.dart';
|
||||
import 'package:flame/parallax.dart';
|
||||
import 'package:flame/extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// This examples serves to test the Parallax feature outside of the
|
||||
/// Flame Component System (FCS), use the other files in this folder
|
||||
/// for examples on how to use parallax with FCS
|
||||
/// FCS is only used when you extend BaseGame, not Game,
|
||||
/// like we do in this example.
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await Flame.device.fullScreen();
|
||||
runApp(
|
||||
GameWidget(
|
||||
game: MyGame(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class MyGame extends Game {
|
||||
Parallax parallax;
|
||||
|
||||
@override
|
||||
Future<void> onLoad() async {
|
||||
parallax = await loadParallax(
|
||||
[
|
||||
'bg.png',
|
||||
'mountain-far.png',
|
||||
'mountains.png',
|
||||
'trees.png',
|
||||
'foreground-trees.png',
|
||||
],
|
||||
size,
|
||||
baseVelocity: Vector2(20, 0),
|
||||
velocityMultiplierDelta: Vector2(1.8, 1.0),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void update(double dt) {
|
||||
parallax.update(dt);
|
||||
}
|
||||
|
||||
@override
|
||||
void render(Canvas canvas) {
|
||||
parallax.render(canvas);
|
||||
}
|
||||
}
|
||||
@ -13,14 +13,17 @@ import 'position_component.dart';
|
||||
extension ParallaxComponentExtension on Game {
|
||||
Future<ParallaxComponent> loadParallaxComponent(
|
||||
List<String> paths, {
|
||||
Vector2 size,
|
||||
Vector2 baseVelocity,
|
||||
Vector2 velocityMultiplierDelta,
|
||||
ImageRepeat repeat = ImageRepeat.repeatX,
|
||||
Alignment alignment = Alignment.bottomLeft,
|
||||
LayerFill fill = LayerFill.height,
|
||||
}) {
|
||||
return ParallaxComponent.load(
|
||||
}) async {
|
||||
final componentSize = size ?? this.size;
|
||||
final component = await ParallaxComponent.load(
|
||||
paths,
|
||||
size: componentSize,
|
||||
baseVelocity: baseVelocity,
|
||||
velocityMultiplierDelta: velocityMultiplierDelta,
|
||||
repeat: repeat,
|
||||
@ -28,6 +31,8 @@ extension ParallaxComponentExtension on Game {
|
||||
fill: fill,
|
||||
images: images,
|
||||
);
|
||||
|
||||
return component..size.setFrom(componentSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,13 +71,7 @@ class ParallaxComponent extends PositionComponent {
|
||||
@override
|
||||
void render(Canvas canvas) {
|
||||
super.render(canvas);
|
||||
canvas.save();
|
||||
parallax?.layers?.forEach((layer) {
|
||||
canvas.save();
|
||||
layer.render(canvas);
|
||||
canvas.restore();
|
||||
});
|
||||
canvas.restore();
|
||||
parallax?.render(canvas);
|
||||
}
|
||||
|
||||
/// Note that this method only should be used if all of your layers should
|
||||
@ -80,7 +79,7 @@ class ParallaxComponent extends PositionComponent {
|
||||
/// and filled), otherwise load the [ParallaxLayer]s individually and use the
|
||||
/// normal constructor.
|
||||
///
|
||||
/// [load] takes a list of paths to all the images that you want to use in the
|
||||
/// [load] takes a list of paths to all the images and a size that you want to use in the
|
||||
/// parallax.
|
||||
/// Optionally arguments for the [baseVelocity] and [layerDelta] can be passed
|
||||
/// in, [baseVelocity] defines what the base velocity of the layers should be
|
||||
@ -94,6 +93,7 @@ class ParallaxComponent extends PositionComponent {
|
||||
/// If no image cache is set, the global flame cache is used.
|
||||
static Future<ParallaxComponent> load(
|
||||
List<String> paths, {
|
||||
Vector2 size,
|
||||
Vector2 baseVelocity,
|
||||
Vector2 velocityMultiplierDelta,
|
||||
ImageRepeat repeat = ImageRepeat.repeatX,
|
||||
@ -101,9 +101,10 @@ class ParallaxComponent extends PositionComponent {
|
||||
LayerFill fill = LayerFill.height,
|
||||
Images images,
|
||||
}) async {
|
||||
return ParallaxComponent.fromParallax(
|
||||
final component = ParallaxComponent.fromParallax(
|
||||
await Parallax.load(
|
||||
paths,
|
||||
size,
|
||||
baseVelocity: baseVelocity,
|
||||
velocityMultiplierDelta: velocityMultiplierDelta,
|
||||
repeat: repeat,
|
||||
@ -112,5 +113,11 @@ class ParallaxComponent extends PositionComponent {
|
||||
images: images,
|
||||
),
|
||||
);
|
||||
|
||||
if (size != null) {
|
||||
component.size.setFrom(size);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,12 +6,14 @@ import 'package:flutter/painting.dart';
|
||||
import 'assets/images.dart';
|
||||
import 'extensions/rect.dart';
|
||||
import 'extensions/vector2.dart';
|
||||
import 'extensions/canvas.dart';
|
||||
import 'flame.dart';
|
||||
import 'game/game.dart';
|
||||
|
||||
extension ParallaxExtension on Game {
|
||||
Future<Parallax> loadParallax(
|
||||
List<String> paths, {
|
||||
List<String> paths,
|
||||
Vector2 size, {
|
||||
Vector2 baseVelocity,
|
||||
Vector2 velocityMultiplierDelta,
|
||||
ImageRepeat repeat = ImageRepeat.repeatX,
|
||||
@ -20,6 +22,7 @@ extension ParallaxExtension on Game {
|
||||
}) {
|
||||
return Parallax.load(
|
||||
paths,
|
||||
size,
|
||||
baseVelocity: baseVelocity,
|
||||
velocityMultiplierDelta: velocityMultiplierDelta,
|
||||
repeat: repeat,
|
||||
@ -235,12 +238,19 @@ enum LayerFill { height, width, none }
|
||||
/// layer moves with different velocities to give an effect of depth.
|
||||
class Parallax {
|
||||
Vector2 baseVelocity;
|
||||
Vector2 _size = Vector2.zero();
|
||||
Rect _clipRect;
|
||||
final List<ParallaxLayer> layers;
|
||||
|
||||
Parallax(
|
||||
this.layers, {
|
||||
this.layers,
|
||||
Vector2 size, {
|
||||
Vector2 baseVelocity,
|
||||
}) : baseVelocity = baseVelocity ?? Vector2.zero();
|
||||
}) : assert(layers != null),
|
||||
assert(size != null) {
|
||||
this.baseVelocity = baseVelocity ?? Vector2.zero();
|
||||
resize(size);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@ -248,7 +258,13 @@ class Parallax {
|
||||
|
||||
/// If the `ParallaxComponent` isn't used your own wrapper needs to call this
|
||||
/// on creation.
|
||||
void resize(Vector2 size) => layers.forEach((layer) => layer.resize(size));
|
||||
void resize(Vector2 newSize) {
|
||||
if (newSize != _size) {
|
||||
_size = newSize;
|
||||
_clipRect = newSize.toRect();
|
||||
layers.forEach((layer) => layer.resize(newSize));
|
||||
}
|
||||
}
|
||||
|
||||
void update(double t) {
|
||||
layers.forEach((layer) {
|
||||
@ -276,7 +292,8 @@ class Parallax {
|
||||
/// used can also be passed in.
|
||||
/// If no image cache is set, the global flame cache is used.
|
||||
static Future<Parallax> load(
|
||||
List<String> paths, {
|
||||
List<String> paths,
|
||||
Vector2 size, {
|
||||
Vector2 baseVelocity,
|
||||
Vector2 velocityMultiplierDelta,
|
||||
ImageRepeat repeat = ImageRepeat.repeatX,
|
||||
@ -309,7 +326,22 @@ class Parallax {
|
||||
);
|
||||
return Parallax(
|
||||
layers,
|
||||
size,
|
||||
baseVelocity: baseVelocity,
|
||||
);
|
||||
}
|
||||
|
||||
void render(Canvas canvas, {Vector2 position}) {
|
||||
canvas.save();
|
||||
if (position != null) {
|
||||
canvas.translateVector(position);
|
||||
}
|
||||
canvas.clipRect(_clipRect);
|
||||
layers.forEach((layer) {
|
||||
canvas.save();
|
||||
layer.render(canvas);
|
||||
canvas.restore();
|
||||
});
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user