mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 03:15:43 +08:00
91 lines
2.8 KiB
Dart
91 lines
2.8 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:box2d_flame/box2d.dart';
|
|
import 'package:flame/box2d/box2d_component.dart';
|
|
|
|
class Viewport extends ViewportTransform {
|
|
Size size;
|
|
|
|
@override
|
|
double scale;
|
|
|
|
Viewport(this.size, this.scale)
|
|
: super(Vector2(size.width / 2, size.height / 2),
|
|
Vector2(size.width / 2, size.height / 2), scale);
|
|
|
|
double worldAlignBottom(double height) => -(size.height / 2 / scale) + height;
|
|
|
|
/// Resizes the current viewport.
|
|
void resize(Size size) {
|
|
this.size = size;
|
|
extents = Vector2.copy(Vector2(size.width / 2, size.height / 2));
|
|
center = Vector2.copy(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 percentage of the width in [0, 1] range.
|
|
double worldWidth(double percent) {
|
|
return percent * (size.width / scale);
|
|
}
|
|
|
|
double get width => size.width / scale / window.devicePixelRatio;
|
|
|
|
double get height => size.height / scale / window.devicePixelRatio;
|
|
|
|
/// Computes the scroll percentage of total screen width of the current viewport 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}) {
|
|
final width = size.width * screens;
|
|
final x = center.x + ((screens - 1) * size.width / 2);
|
|
final double rest = x.abs() % width;
|
|
final double scroll = rest / width;
|
|
return x > 0 ? scroll : 1 - scroll;
|
|
}
|
|
|
|
/// Follows the specified 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}) {
|
|
final Vector2 position = component.center;
|
|
|
|
double x = center.x;
|
|
double y = center.y;
|
|
|
|
if (horizontal != null) {
|
|
final temp = getWorldToScreen(position);
|
|
|
|
final margin = horizontal / 2 * size.width / 2;
|
|
final focus = size.width / 2 - temp.x;
|
|
|
|
if (focus.abs() > margin) {
|
|
x = size.width / 2 +
|
|
(position.x * scale) +
|
|
(focus > 0 ? margin : -margin);
|
|
}
|
|
}
|
|
|
|
if (vertical != null) {
|
|
final temp = getWorldToScreen(position);
|
|
|
|
final margin = vertical / 2 * size.height / 2;
|
|
final 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);
|
|
}
|
|
}
|
|
}
|