mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-11 18:11:12 +08:00
Improve camera (#770)
This commit is contained in:
@@ -24,7 +24,7 @@ class MovableSquare extends SquareComponent
|
|||||||
timer = Timer(3.0)
|
timer = Timer(3.0)
|
||||||
..stop()
|
..stop()
|
||||||
..callback = () {
|
..callback = () {
|
||||||
gameRef.camera.setRelativeOffset(Anchor.center.toVector2());
|
gameRef.camera.setRelativeOffset(Anchor.center);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ class MovableSquare extends SquareComponent
|
|||||||
@override
|
@override
|
||||||
void onCollision(Set<Vector2> points, Collidable other) {
|
void onCollision(Set<Vector2> points, Collidable other) {
|
||||||
if (other is Rock) {
|
if (other is Rock) {
|
||||||
gameRef.camera.setRelativeOffset(Anchor.topCenter.toVector2());
|
gameRef.camera.setRelativeOffset(Anchor.topCenter);
|
||||||
timer.start();
|
timer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
- Adding `SpriteAnimationGroupComponent`
|
- Adding `SpriteAnimationGroupComponent`
|
||||||
- Allow isometric tile maps with custom heights
|
- Allow isometric tile maps with custom heights
|
||||||
- Add a new renderRect method to Sprite
|
- Add a new renderRect method to Sprite
|
||||||
|
- Addresses the TODO to change the camera public APIs to take Anchors for relativePositions
|
||||||
|
- Adds methods to support moving the camera relative to its current position
|
||||||
|
|
||||||
## [1.0.0-rc9]
|
## [1.0.0-rc9]
|
||||||
- Fix input bug with other anchors than center
|
- Fix input bug with other anchors than center
|
||||||
|
|||||||
@@ -179,6 +179,8 @@ class Camera extends Projector {
|
|||||||
update(0);
|
update(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Coordinates
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Vector2 unprojectVector(Vector2 screenCoordinates) {
|
Vector2 unprojectVector(Vector2 screenCoordinates) {
|
||||||
return screenCoordinates * zoom + _position;
|
return screenCoordinates * zoom + _position;
|
||||||
@@ -199,6 +201,13 @@ class Camera extends Projector {
|
|||||||
return worldCoordinates / zoom;
|
return worldCoordinates / zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is the (current) absolute target of the camera, i.e., the
|
||||||
|
/// coordinate that should be on the top left, regardless of relative
|
||||||
|
/// offset, world boundaries or shake.
|
||||||
|
Vector2 absoluteTarget() {
|
||||||
|
return _currentCameraDelta ?? follow ?? Vector2.zero();
|
||||||
|
}
|
||||||
|
|
||||||
// Follow
|
// Follow
|
||||||
|
|
||||||
/// Immediately snaps the camera to start following the [component].
|
/// Immediately snaps the camera to start following the [component].
|
||||||
@@ -214,7 +223,7 @@ class Camera extends Projector {
|
|||||||
/// position, set the components anchor to center.
|
/// position, set the components anchor to center.
|
||||||
void followComponent(
|
void followComponent(
|
||||||
PositionComponent component, {
|
PositionComponent component, {
|
||||||
Vector2? relativeOffset,
|
Anchor relativeOffset = Anchor.center,
|
||||||
Rect? worldBounds,
|
Rect? worldBounds,
|
||||||
}) {
|
}) {
|
||||||
followVector2(
|
followVector2(
|
||||||
@@ -234,12 +243,12 @@ class Camera extends Projector {
|
|||||||
/// camera is allowed to move.
|
/// camera is allowed to move.
|
||||||
void followVector2(
|
void followVector2(
|
||||||
Vector2 vector2, {
|
Vector2 vector2, {
|
||||||
Vector2? relativeOffset,
|
Anchor relativeOffset = Anchor.center,
|
||||||
Rect? worldBounds,
|
Rect? worldBounds,
|
||||||
}) {
|
}) {
|
||||||
follow = vector2;
|
follow = vector2;
|
||||||
this.worldBounds = worldBounds;
|
this.worldBounds = worldBounds;
|
||||||
_targetRelativeOffset.setFrom(relativeOffset ?? Anchor.center.toVector2());
|
_targetRelativeOffset.setFrom(relativeOffset.toVector2());
|
||||||
_currentRelativeOffset.setFrom(_targetRelativeOffset);
|
_currentRelativeOffset.setFrom(_targetRelativeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,9 +258,8 @@ class Camera extends Projector {
|
|||||||
/// you have two different options for the player to choose or your have a
|
/// you have two different options for the player to choose or your have a
|
||||||
/// "dialog" camera that puts the player in a better place to show the
|
/// "dialog" camera that puts the player in a better place to show the
|
||||||
/// dialog UI.
|
/// dialog UI.
|
||||||
/// TODO(luan) this should be an anchor
|
void setRelativeOffset(Anchor newRelativeOffset) {
|
||||||
void setRelativeOffset(Vector2 newRelativeOffset) {
|
_targetRelativeOffset.setFrom(newRelativeOffset.toVector2());
|
||||||
_targetRelativeOffset.setFrom(newRelativeOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 _screenDelta() {
|
Vector2 _screenDelta() {
|
||||||
@@ -259,7 +267,7 @@ class Camera extends Projector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector2 _target() {
|
Vector2 _target() {
|
||||||
final target = _currentCameraDelta ?? follow ?? Vector2.zero();
|
final target = absoluteTarget();
|
||||||
final attemptedTarget = target - _screenDelta();
|
final attemptedTarget = target - _screenDelta();
|
||||||
|
|
||||||
final bounds = worldBounds;
|
final bounds = worldBounds;
|
||||||
@@ -294,6 +302,13 @@ class Camera extends Projector {
|
|||||||
|
|
||||||
// Movement
|
// Movement
|
||||||
|
|
||||||
|
/// Moves the camera by a given [displacement] (delta). This is the same as
|
||||||
|
/// [moveTo] but instead of providing an absolute end position, you can
|
||||||
|
/// provide a desired translation vector.
|
||||||
|
void translateBy(Vector2 displacement) {
|
||||||
|
moveTo(absoluteTarget() + displacement);
|
||||||
|
}
|
||||||
|
|
||||||
/// Applies an ad-hoc movement to the camera towards the target, bypassing
|
/// Applies an ad-hoc movement to the camera towards the target, bypassing
|
||||||
/// follow. Once it arrives the camera will not move until [resetMovement]
|
/// follow. Once it arrives the camera will not move until [resetMovement]
|
||||||
/// is called.
|
/// is called.
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ void main() {
|
|||||||
game.add(p);
|
game.add(p);
|
||||||
game.update(0);
|
game.update(0);
|
||||||
// this would be a typical vertical shoot-em-up
|
// this would be a typical vertical shoot-em-up
|
||||||
game.camera.followComponent(p, relativeOffset: Vector2(0.5, 0.8));
|
game.camera.followComponent(p, relativeOffset: const Anchor(0.5, 0.8));
|
||||||
|
|
||||||
expect(game.camera.position, Vector2.all(0.0));
|
expect(game.camera.position, Vector2.all(0.0));
|
||||||
p.position.setValues(600.0, 2000.0);
|
p.position.setValues(600.0, 2000.0);
|
||||||
@@ -296,7 +296,7 @@ void main() {
|
|||||||
final game = BaseGame();
|
final game = BaseGame();
|
||||||
game.onResize(Vector2.all(200.0));
|
game.onResize(Vector2.all(200.0));
|
||||||
|
|
||||||
game.camera.setRelativeOffset(Anchor.center.toVector2());
|
game.camera.setRelativeOffset(Anchor.center);
|
||||||
|
|
||||||
game.update(0);
|
game.update(0);
|
||||||
expect(game.camera.position, Vector2.zero());
|
expect(game.camera.position, Vector2.zero());
|
||||||
@@ -339,8 +339,9 @@ void main() {
|
|||||||
game.add(p);
|
game.add(p);
|
||||||
game.camera.followComponent(
|
game.camera.followComponent(
|
||||||
p,
|
p,
|
||||||
// this could be a typical mario-like platformer, where the player is more on the bottom left to allow the scenario to be seem
|
// this could be a typical mario-like platformer, where the player is
|
||||||
relativeOffset: Vector2(0.25, 0.25),
|
// more on the bottom left to allow the scenario to be seem
|
||||||
|
relativeOffset: const Anchor(0.25, 0.25),
|
||||||
worldBounds: const Rect.fromLTWH(0, 0, 1000, 1000),
|
worldBounds: const Rect.fromLTWH(0, 0, 1000, 1000),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ void main() {
|
|||||||
game.onResize(Vector2.all(10));
|
game.onResize(Vector2.all(10));
|
||||||
|
|
||||||
// no-op because the default is already top left
|
// no-op because the default is already top left
|
||||||
game.camera.setRelativeOffset(Anchor.topLeft.toVector2());
|
game.camera.setRelativeOffset(Anchor.topLeft);
|
||||||
// top left corner of the screen is (-100, -100)
|
// top left corner of the screen is (-100, -100)
|
||||||
game.camera.snapTo(Vector2.all(-100));
|
game.camera.snapTo(Vector2.all(-100));
|
||||||
// zoom is 2x, meaning every 1 unit you walk away of (-100, -100)
|
// zoom is 2x, meaning every 1 unit you walk away of (-100, -100)
|
||||||
@@ -118,7 +118,7 @@ void main() {
|
|||||||
|
|
||||||
// note: in the current implementation, if we change the relative position
|
// note: in the current implementation, if we change the relative position
|
||||||
// the zoom is still applied w.r.t. the top left of the screen
|
// the zoom is still applied w.r.t. the top left of the screen
|
||||||
game.camera.setRelativeOffset(Anchor.center.toVector2());
|
game.camera.setRelativeOffset(Anchor.center);
|
||||||
game.camera.snap();
|
game.camera.snap();
|
||||||
|
|
||||||
// that means that the center would be -100, -100 if the zoom was 1
|
// that means that the center would be -100, -100 if the zoom was 1
|
||||||
|
|||||||
Reference in New Issue
Block a user