mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-04 04:47:13 +08:00
Improve camera (#770)
This commit is contained in:
@ -24,7 +24,7 @@ class MovableSquare extends SquareComponent
|
||||
timer = Timer(3.0)
|
||||
..stop()
|
||||
..callback = () {
|
||||
gameRef.camera.setRelativeOffset(Anchor.center.toVector2());
|
||||
gameRef.camera.setRelativeOffset(Anchor.center);
|
||||
};
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ class MovableSquare extends SquareComponent
|
||||
@override
|
||||
void onCollision(Set<Vector2> points, Collidable other) {
|
||||
if (other is Rock) {
|
||||
gameRef.camera.setRelativeOffset(Anchor.topCenter.toVector2());
|
||||
gameRef.camera.setRelativeOffset(Anchor.topCenter);
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
- Adding `SpriteAnimationGroupComponent`
|
||||
- Allow isometric tile maps with custom heights
|
||||
- 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]
|
||||
- Fix input bug with other anchors than center
|
||||
|
||||
@ -179,6 +179,8 @@ class Camera extends Projector {
|
||||
update(0);
|
||||
}
|
||||
|
||||
// Coordinates
|
||||
|
||||
@override
|
||||
Vector2 unprojectVector(Vector2 screenCoordinates) {
|
||||
return screenCoordinates * zoom + _position;
|
||||
@ -199,6 +201,13 @@ class Camera extends Projector {
|
||||
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
|
||||
|
||||
/// Immediately snaps the camera to start following the [component].
|
||||
@ -214,7 +223,7 @@ class Camera extends Projector {
|
||||
/// position, set the components anchor to center.
|
||||
void followComponent(
|
||||
PositionComponent component, {
|
||||
Vector2? relativeOffset,
|
||||
Anchor relativeOffset = Anchor.center,
|
||||
Rect? worldBounds,
|
||||
}) {
|
||||
followVector2(
|
||||
@ -234,12 +243,12 @@ class Camera extends Projector {
|
||||
/// camera is allowed to move.
|
||||
void followVector2(
|
||||
Vector2 vector2, {
|
||||
Vector2? relativeOffset,
|
||||
Anchor relativeOffset = Anchor.center,
|
||||
Rect? worldBounds,
|
||||
}) {
|
||||
follow = vector2;
|
||||
this.worldBounds = worldBounds;
|
||||
_targetRelativeOffset.setFrom(relativeOffset ?? Anchor.center.toVector2());
|
||||
_targetRelativeOffset.setFrom(relativeOffset.toVector2());
|
||||
_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
|
||||
/// "dialog" camera that puts the player in a better place to show the
|
||||
/// dialog UI.
|
||||
/// TODO(luan) this should be an anchor
|
||||
void setRelativeOffset(Vector2 newRelativeOffset) {
|
||||
_targetRelativeOffset.setFrom(newRelativeOffset);
|
||||
void setRelativeOffset(Anchor newRelativeOffset) {
|
||||
_targetRelativeOffset.setFrom(newRelativeOffset.toVector2());
|
||||
}
|
||||
|
||||
Vector2 _screenDelta() {
|
||||
@ -259,7 +267,7 @@ class Camera extends Projector {
|
||||
}
|
||||
|
||||
Vector2 _target() {
|
||||
final target = _currentCameraDelta ?? follow ?? Vector2.zero();
|
||||
final target = absoluteTarget();
|
||||
final attemptedTarget = target - _screenDelta();
|
||||
|
||||
final bounds = worldBounds;
|
||||
@ -294,6 +302,13 @@ class Camera extends Projector {
|
||||
|
||||
// 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
|
||||
/// follow. Once it arrives the camera will not move until [resetMovement]
|
||||
/// is called.
|
||||
|
||||
@ -214,7 +214,7 @@ void main() {
|
||||
game.add(p);
|
||||
game.update(0);
|
||||
// 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));
|
||||
p.position.setValues(600.0, 2000.0);
|
||||
@ -296,7 +296,7 @@ void main() {
|
||||
final game = BaseGame();
|
||||
game.onResize(Vector2.all(200.0));
|
||||
|
||||
game.camera.setRelativeOffset(Anchor.center.toVector2());
|
||||
game.camera.setRelativeOffset(Anchor.center);
|
||||
|
||||
game.update(0);
|
||||
expect(game.camera.position, Vector2.zero());
|
||||
@ -339,8 +339,9 @@ void main() {
|
||||
game.add(p);
|
||||
game.camera.followComponent(
|
||||
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
|
||||
relativeOffset: Vector2(0.25, 0.25),
|
||||
// this could be a typical mario-like platformer, where the player is
|
||||
// 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),
|
||||
);
|
||||
|
||||
|
||||
@ -102,7 +102,7 @@ void main() {
|
||||
game.onResize(Vector2.all(10));
|
||||
|
||||
// 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)
|
||||
game.camera.snapTo(Vector2.all(-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
|
||||
// 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();
|
||||
|
||||
// that means that the center would be -100, -100 if the zoom was 1
|
||||
|
||||
Reference in New Issue
Block a user