mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-02 03:15:43 +08:00
Rename isHud to respectCamera (#1159)
* Camera as an internal component * Correct respectCamera * Added changelog entry * Add super call that will later be removed * Rename callRender -> callOwnRender * Don't call render when root * Remove callOwnRender * Skip CameraWrapper in own renderTree * Too complex to have camera as component * Revert test * Update docs for respectCamera * Move down field * Fix changelog
This commit is contained in:
@ -24,8 +24,9 @@ component before the next update loop. It will then no longer be rendered or upd
|
|||||||
`game.remove(Component c)` and `component.removeFromParent()` also can be used to remove components
|
`game.remove(Component c)` and `component.removeFromParent()` also can be used to remove components
|
||||||
from its parent.
|
from its parent.
|
||||||
|
|
||||||
The `isHUD` variable can be overridden or set to true (defaults to `false`) to make the `FlameGame`
|
The `respectCamera` variable can be overridden or set to `false` (defaults to `true`) to make the
|
||||||
ignore the `camera` for this element, making it static in relation to the screen that is.
|
`FlameGame` ignore the `camera` for this component, making it static in relation to the viewport
|
||||||
|
that is.
|
||||||
Do note that this currently only works if the component is added directly to the root `FlameGame`.
|
Do note that this currently only works if the component is added directly to the root `FlameGame`.
|
||||||
|
|
||||||
The `onRemove` method can be overridden to run code before the component is removed from the game,
|
The `onRemove` method can be overridden to run code before the component is removed from the game,
|
||||||
|
|||||||
@ -111,7 +111,7 @@ you handle this through the `button` component.
|
|||||||
|
|
||||||
As the name suggests this button is a hud by default, which means that it will be static on your
|
As the name suggests this button is a hud by default, which means that it will be static on your
|
||||||
screen even if the camera for the game moves around. You can also use this component as a non-hud by
|
screen even if the camera for the game moves around. You can also use this component as a non-hud by
|
||||||
setting `hudButtonComponent.isHud = false;`.
|
setting `hudButtonComponent.respectCamera = true;`.
|
||||||
|
|
||||||
If you want to act upon the button being pressed (which would be the common thing to do) you can either pass in
|
If you want to act upon the button being pressed (which would be the common thing to do) you can either pass in
|
||||||
a callback function as the `onPressed` argument, or you extend the component and override
|
a callback function as the `onPressed` argument, or you extend the component and override
|
||||||
|
|||||||
@ -163,11 +163,11 @@ class JoystickAdvancedExample extends FlameGame
|
|||||||
speedText = TextComponent(
|
speedText = TextComponent(
|
||||||
text: 'Speed: 0',
|
text: 'Speed: 0',
|
||||||
textRenderer: _regular,
|
textRenderer: _regular,
|
||||||
)..isHud = true;
|
)..respectCamera = false;
|
||||||
directionText = TextComponent(
|
directionText = TextComponent(
|
||||||
text: 'Direction: idle',
|
text: 'Direction: idle',
|
||||||
textRenderer: _regular,
|
textRenderer: _regular,
|
||||||
)..isHud = true;
|
)..respectCamera = false;
|
||||||
|
|
||||||
final speedWithMargin = HudMarginComponent(
|
final speedWithMargin = HudMarginComponent(
|
||||||
margin: const EdgeInsets.only(
|
margin: const EdgeInsets.only(
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
- Export new effects system
|
- Export new effects system
|
||||||
- Introduce `updateTree` to follow the `renderTree` convention
|
- Introduce `updateTree` to follow the `renderTree` convention
|
||||||
- Fix `Parallax.load` with different loading times
|
- Fix `Parallax.load` with different loading times
|
||||||
|
- `isHud` renamed to `respectCamera`
|
||||||
|
|
||||||
## [1.0.0-releasecandidate.18]
|
## [1.0.0-releasecandidate.18]
|
||||||
- Forcing portrait and landscape mode is now supported on web
|
- Forcing portrait and landscape mode is now supported on web
|
||||||
|
|||||||
@ -18,11 +18,15 @@ import 'cache/value_cache.dart';
|
|||||||
/// called automatically once the component is added to the component tree in
|
/// called automatically once the component is added to the component tree in
|
||||||
/// your game (with `game.add`).
|
/// your game (with `game.add`).
|
||||||
class Component with Loadable {
|
class Component with Loadable {
|
||||||
/// Whether this component is a HUD (Heads-up display) object or not.
|
/// Whether this component should respect the camera or not.
|
||||||
///
|
///
|
||||||
/// HUD objects ignore the FlameGame.camera when rendered (so their position
|
/// Components that have this property set to false will ignore the
|
||||||
/// coordinates are considered relative to the device screen).
|
/// `FlameGame.camera` when rendered (so their position coordinates are
|
||||||
bool isHud = false;
|
/// considered relative only to the viewport instead).
|
||||||
|
///
|
||||||
|
/// Do note that this currently only works if the component is added directly
|
||||||
|
/// to the root `FlameGame`.
|
||||||
|
bool respectCamera = true;
|
||||||
|
|
||||||
/// Whether this component has been prepared and is ready to be added to the
|
/// Whether this component has been prepared and is ready to be added to the
|
||||||
/// game loop.
|
/// game loop.
|
||||||
@ -153,7 +157,9 @@ class Component with Loadable {
|
|||||||
|
|
||||||
@protected
|
@protected
|
||||||
Vector2 eventPosition(PositionInfo info) {
|
Vector2 eventPosition(PositionInfo info) {
|
||||||
return isHud ? info.eventPosition.viewportOnly : info.eventPosition.game;
|
return respectCamera
|
||||||
|
? info.eventPosition.game
|
||||||
|
: info.eventPosition.viewportOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove the component from its parent in the next tick.
|
/// Remove the component from its parent in the next tick.
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import '../../../game.dart';
|
|||||||
class HudMarginComponent<T extends FlameGame> extends PositionComponent
|
class HudMarginComponent<T extends FlameGame> extends PositionComponent
|
||||||
with HasGameRef<T> {
|
with HasGameRef<T> {
|
||||||
@override
|
@override
|
||||||
bool isHud = true;
|
bool respectCamera = false;
|
||||||
|
|
||||||
/// Instead of setting a position of the [HudMarginComponent] a margin
|
/// Instead of setting a position of the [HudMarginComponent] a margin
|
||||||
/// from the edges of the viewport can be used instead.
|
/// from the edges of the viewport can be used instead.
|
||||||
|
|||||||
@ -38,7 +38,7 @@ import '../projector.dart';
|
|||||||
///
|
///
|
||||||
/// Note: in the context of the FlameGame, the camera effectively translates
|
/// Note: in the context of the FlameGame, the camera effectively translates
|
||||||
/// the position where components are rendered with relation to the Viewport.
|
/// the position where components are rendered with relation to the Viewport.
|
||||||
/// Components marked as `isHud = true` are always rendered in screen
|
/// Components marked as `respectCamera = false` are always rendered in screen
|
||||||
/// coordinates, bypassing the camera altogether.
|
/// coordinates, bypassing the camera altogether.
|
||||||
class Camera extends Projector {
|
class Camera extends Projector {
|
||||||
Camera() : _viewport = DefaultViewport() {
|
Camera() : _viewport = DefaultViewport() {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
import '../../../components.dart';
|
import '../../../components.dart';
|
||||||
import 'camera.dart';
|
import 'camera.dart';
|
||||||
|
|
||||||
@ -7,6 +9,7 @@ import 'camera.dart';
|
|||||||
/// converted into a proper Component in a future release, but until then
|
/// converted into a proper Component in a future release, but until then
|
||||||
/// using it in any code other than the FlameGame class is unsafe and
|
/// using it in any code other than the FlameGame class is unsafe and
|
||||||
/// not recommended.
|
/// not recommended.
|
||||||
|
@internal
|
||||||
class CameraWrapper {
|
class CameraWrapper {
|
||||||
// TODO(st-pasha): extend from Component
|
// TODO(st-pasha): extend from Component
|
||||||
CameraWrapper(this.camera, this.world);
|
CameraWrapper(this.camera, this.world);
|
||||||
@ -19,16 +22,14 @@ class CameraWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void render(Canvas canvas) {
|
void render(Canvas canvas) {
|
||||||
// TODO(st-pasha): it would be easier to keep the world and the
|
|
||||||
// HUD as two separate component trees.
|
|
||||||
camera.viewport.render(canvas, (_canvas) {
|
camera.viewport.render(canvas, (_canvas) {
|
||||||
var hasCamera = false; // so we don't apply unecessary transformations
|
var hasCamera = false; // so we don't apply unnecessary transformations
|
||||||
world.forEach((component) {
|
world.forEach((component) {
|
||||||
if (!component.isHud && !hasCamera) {
|
if (component.respectCamera && !hasCamera) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
camera.apply(canvas);
|
camera.apply(canvas);
|
||||||
hasCamera = true;
|
hasCamera = true;
|
||||||
} else if (component.isHud && hasCamera) {
|
} else if (!component.respectCamera && hasCamera) {
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
hasCamera = false;
|
hasCamera = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,13 +21,11 @@ class FlameGame extends Component with Game {
|
|||||||
_cameraWrapper = CameraWrapper(camera ?? Camera(), children);
|
_cameraWrapper = CameraWrapper(camera ?? Camera(), children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
late final CameraWrapper _cameraWrapper;
|
||||||
|
|
||||||
/// The camera translates the coordinate space after the viewport is applied.
|
/// The camera translates the coordinate space after the viewport is applied.
|
||||||
Camera get camera => _cameraWrapper.camera;
|
Camera get camera => _cameraWrapper.camera;
|
||||||
|
|
||||||
// When the Game becomes a Component (#906), this could be added directly
|
|
||||||
// into the component tree.
|
|
||||||
late final CameraWrapper _cameraWrapper;
|
|
||||||
|
|
||||||
/// This is overwritten to consider the viewport transformation.
|
/// This is overwritten to consider the viewport transformation.
|
||||||
///
|
///
|
||||||
/// Which means that this is the logical size of the game screen area as
|
/// Which means that this is the logical size of the game screen area as
|
||||||
@ -64,7 +62,17 @@ class FlameGame extends Component with Game {
|
|||||||
/// interfering with each others rendering.
|
/// interfering with each others rendering.
|
||||||
@override
|
@override
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void render(Canvas canvas) => _cameraWrapper.render(canvas);
|
void render(Canvas canvas) {
|
||||||
|
if (parent == null) {
|
||||||
|
renderTree(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void renderTree(Canvas canvas) {
|
||||||
|
// Don't call super.renderTree, since the tree is rendered by the camera
|
||||||
|
_cameraWrapper.render(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
/// This updates every component in the tree.
|
/// This updates every component in the tree.
|
||||||
///
|
///
|
||||||
@ -75,10 +83,11 @@ class FlameGame extends Component with Game {
|
|||||||
@override
|
@override
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void update(double dt) {
|
void update(double dt) {
|
||||||
|
super.update(dt);
|
||||||
|
_cameraWrapper.update(dt);
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
super.updateTree(dt, callOwnUpdate: false);
|
super.updateTree(dt, callOwnUpdate: false);
|
||||||
}
|
}
|
||||||
_cameraWrapper.update(dt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This passes the new size along to every component in the tree via their
|
/// This passes the new size along to every component in the tree via their
|
||||||
|
|||||||
@ -116,7 +116,7 @@ mixin Game on Loadable {
|
|||||||
onAttach();
|
onAttach();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the game has been attached. This can be overriden
|
/// Called when the game has been attached. This can be overridden
|
||||||
/// to add logic that requires the game to already be attached
|
/// to add logic that requires the game to already be attached
|
||||||
/// to the widget tree.
|
/// to the widget tree.
|
||||||
void onAttach() {}
|
void onAttach() {}
|
||||||
@ -131,7 +131,7 @@ mixin Game on Loadable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called after the game has left the widget tree.
|
/// Called after the game has left the widget tree.
|
||||||
/// This can be overriden to add logic that requires the game
|
/// This can be overridden to add logic that requires the game
|
||||||
/// not be on the flutter widget tree anymore.
|
/// not be on the flutter widget tree anymore.
|
||||||
void onDetach() {}
|
void onDetach() {}
|
||||||
|
|
||||||
@ -157,12 +157,14 @@ mixin Game on Loadable {
|
|||||||
return _gameRenderBox!.localToGlobal(point.toOffset()).toVector2();
|
return _gameRenderBox!.localToGlobal(point.toOffset()).toVector2();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the projector used by non-isHUD components.
|
/// This is the projector used by all components that respect the camera
|
||||||
/// This can be overriden on your [Game] implementation.
|
/// (`respectCamera = true`).
|
||||||
|
/// This can be overridden on your [Game] implementation.
|
||||||
Projector projector = IdentityProjector();
|
Projector projector = IdentityProjector();
|
||||||
|
|
||||||
/// This is the projector used by isHUD components.
|
/// This is the projector used by components that don't respect the camera
|
||||||
/// This can be overriden on your [Game] implementation.
|
/// (`respectCamera = false`).
|
||||||
|
/// This can be overridden on your [Game] implementation.
|
||||||
Projector viewportProjector = IdentityProjector();
|
Projector viewportProjector = IdentityProjector();
|
||||||
|
|
||||||
/// Utility method to load and cache the image for a sprite based on its
|
/// Utility method to load and cache the image for a sprite based on its
|
||||||
|
|||||||
@ -11,9 +11,10 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
|
|
||||||
class _MyComponent extends Component {
|
class _MyComponent extends Component {
|
||||||
@override
|
@override
|
||||||
bool isHud;
|
bool respectCamera;
|
||||||
|
|
||||||
_MyComponent(int priority, {this.isHud = false}) : super(priority: priority);
|
_MyComponent(int priority, {this.respectCamera = true})
|
||||||
|
: super(priority: priority);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void render(Canvas canvas) {
|
void render(Canvas canvas) {
|
||||||
@ -54,9 +55,9 @@ void main() {
|
|||||||
'only HUD components',
|
'only HUD components',
|
||||||
(game) async {
|
(game) async {
|
||||||
await game.ensureAddAll([
|
await game.ensureAddAll([
|
||||||
_MyComponent(4, isHud: true),
|
_MyComponent(4, respectCamera: false),
|
||||||
_MyComponent(1, isHud: true),
|
_MyComponent(1, respectCamera: false),
|
||||||
_MyComponent(2, isHud: true),
|
_MyComponent(2, respectCamera: false),
|
||||||
]);
|
]);
|
||||||
final canvas = MockCanvas();
|
final canvas = MockCanvas();
|
||||||
game.camera.snapTo(Vector2(12.0, 18.0));
|
game.camera.snapTo(Vector2(12.0, 18.0));
|
||||||
@ -78,9 +79,9 @@ void main() {
|
|||||||
await game.ensureAddAll([
|
await game.ensureAddAll([
|
||||||
_MyComponent(4),
|
_MyComponent(4),
|
||||||
_MyComponent(1),
|
_MyComponent(1),
|
||||||
_MyComponent(2, isHud: true),
|
_MyComponent(2, respectCamera: false),
|
||||||
_MyComponent(5, isHud: true),
|
_MyComponent(5, respectCamera: false),
|
||||||
_MyComponent(3, isHud: true),
|
_MyComponent(3, respectCamera: false),
|
||||||
_MyComponent(0),
|
_MyComponent(0),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user