mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-11-04 04:47:13 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			102 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'dart:ui';
 | 
						|
 | 
						|
import 'package:box2d/box2d.dart';
 | 
						|
import 'package:flame/box2d/box2d_component.dart';
 | 
						|
 | 
						|
class Viewport extends ViewportTransform {
 | 
						|
  Size size;
 | 
						|
 | 
						|
  double scale;
 | 
						|
 | 
						|
  Viewport(this.size, this.scale)
 | 
						|
      : super(new Vector2(size.width / 2, size.height / 2),
 | 
						|
            new Vector2(size.width / 2, size.height / 2), scale);
 | 
						|
 | 
						|
  double worldAlignBottom(double height) => -(size.height / 2 / scale) + height;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Resizes the current view port.
 | 
						|
   */
 | 
						|
  void resize(Size size) {
 | 
						|
    this.size = size;
 | 
						|
    this.extents =
 | 
						|
        new Vector2.copy(new Vector2(size.width / 2, size.height / 2));
 | 
						|
    this.center =
 | 
						|
        new Vector2.copy(new Vector2(size.width / 2, size.height / 2));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Computes the number of horizontal world meters of this viewport considering a
 | 
						|
   * percentage of its width.
 | 
						|
   *
 | 
						|
   * @param percent percetage of the width in [0, 1] range
 | 
						|
   */
 | 
						|
  double worldWidth(double percent) {
 | 
						|
    return percent * (size.width / scale);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Computes the scroll percentage of total screen width of the current viwerport
 | 
						|
   * center position.
 | 
						|
   *
 | 
						|
   * @param screens multiplies the visible screen with to create a bigger virtual
 | 
						|
   * screen.
 | 
						|
   * @return the percentage in the range of [0, 1]
 | 
						|
   */
 | 
						|
  double getCenterHorizontalScreenPercentage({double screens: 1.0}) {
 | 
						|
    var width = size.width * screens;
 | 
						|
    var x = center.x + ((screens - 1) * size.width / 2);
 | 
						|
    double rest = x.abs() % width;
 | 
						|
    double scroll = rest / width;
 | 
						|
    return x > 0 ? scroll : 1 - scroll;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Follows the spececified body component using a sliding focus window
 | 
						|
   * defined as a percentage of the total viewport.
 | 
						|
   *
 | 
						|
   * @param component to follow.
 | 
						|
   * @param horizontal percentage of the horizontal viewport. Null means no horizontal following.
 | 
						|
   * @param vertical percentage of the vertical viewport. Null means no vertical following.
 | 
						|
   */
 | 
						|
  void cameraFollow(BodyComponent component,
 | 
						|
      {double horizontal, double vertical}) {
 | 
						|
    Vector2 position = component.center;
 | 
						|
 | 
						|
    double x = center.x;
 | 
						|
    double y = center.y;
 | 
						|
 | 
						|
    if (horizontal != null) {
 | 
						|
      Vector2 temp = new Vector2.zero();
 | 
						|
      getWorldToScreen(position, temp);
 | 
						|
 | 
						|
      var margin = horizontal / 2 * size.width / 2;
 | 
						|
      var focus = size.width / 2 - temp.x;
 | 
						|
 | 
						|
      if (focus.abs() > margin) {
 | 
						|
        x = size.width / 2 +
 | 
						|
            (position.x * scale) +
 | 
						|
            (focus > 0 ? margin : -margin);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (vertical != null) {
 | 
						|
      Vector2 temp = new Vector2.zero();
 | 
						|
      getWorldToScreen(position, temp);
 | 
						|
 | 
						|
      var margin = vertical / 2 * size.height / 2;
 | 
						|
      var focus = size.height / 2 - temp.y;
 | 
						|
 | 
						|
      if (focus.abs() > margin) {
 | 
						|
        y = size.height / 2 +
 | 
						|
            (position.y * scale) +
 | 
						|
            (focus < 0 ? margin : -margin);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if (x != center.x || y != center.y) {
 | 
						|
      setCamera(x, y, scale);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |