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