Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Camera as a component #1355

Merged
merged 35 commits into from
Mar 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a2b667c
wip on new camera system
st-pasha Feb 4, 2022
0388b09
wip on Viewfinder
st-pasha Feb 4, 2022
2efc82f
wip on Camera2 and Viewfinder
st-pasha Feb 4, 2022
173ded7
Merge branch 'main' into ps/camera2
st-pasha Feb 4, 2022
9f9b926
extend Camera
st-pasha Feb 4, 2022
25f8d5e
initial camera2 example
st-pasha Feb 4, 2022
3c46367
Use World in camera2example
st-pasha Feb 4, 2022
e8f39ec
added magnifying glass
st-pasha Feb 5, 2022
370bd89
added description
st-pasha Feb 5, 2022
17c0ffc
expanded docs for camera2
st-pasha Feb 5, 2022
3b55ab5
adjust docs for Viewport
st-pasha Feb 5, 2022
6e39515
docs for Viewfinder
st-pasha Feb 5, 2022
5284e50
format
st-pasha Feb 5, 2022
c9978fd
docs for world
st-pasha Feb 5, 2022
d6c3df2
format
st-pasha Feb 5, 2022
ad0e237
Apply suggestions from code review
st-pasha Feb 9, 2022
0932007
feat: Added NoiseEffectController (#1356)
st-pasha Feb 6, 2022
040f2f1
fix: remove vector_math dependency (#1361)
christopherfujino Feb 9, 2022
5b3e293
minor
st-pasha Feb 9, 2022
9640e0d
Merge branch 'main' into ps/camera2
st-pasha Feb 9, 2022
a0f5725
Merge branch 'main' into ps/camera2
st-pasha Feb 10, 2022
84989d4
Merge branch 'main' into ps/camera2
st-pasha Feb 12, 2022
ec75cc7
Merge branch 'main' into ps/camera2
st-pasha Feb 23, 2022
3e77fb4
use offset.toVector2()
st-pasha Feb 23, 2022
2fe89f4
added docs; renamed handleResize -> onViewportResize
st-pasha Feb 23, 2022
44bb5e9
Merge branch 'main' into ps/camera2
st-pasha Feb 25, 2022
6e47c47
Merge branch 'main' into ps/camera2
st-pasha Mar 4, 2022
28a0ac0
rename Camera2 -> CameraComponent
st-pasha Mar 4, 2022
916c3a5
Create export experimental.dart file
st-pasha Mar 4, 2022
c8927cf
rename Camera2Example -> CameraComponentExample
st-pasha Mar 4, 2022
101732e
Added doc for the experimental.dart file
st-pasha Mar 4, 2022
567181e
fix re-adding components with children
st-pasha Mar 4, 2022
199b8e0
Added support for admonitions in the docs
st-pasha Mar 4, 2022
b21102a
Documentation for CameraComponent
st-pasha Mar 4, 2022
d2affe3
format
st-pasha Mar 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions doc/_sphinx/theme/flames.css
Original file line number Diff line number Diff line change
Expand Up @@ -706,3 +706,67 @@ div.highlight-box button.close {
font-size: 20px;
margin: 0 0 0 20px;
}


/*----------------------------------------------------------------------------*
* Admonitions
*----------------------------------------------------------------------------*/

div.admonition {
background: #333333;
border-left: 3px solid var(--admonition-border-color);
border-radius: 5px;
box-shadow: 1px 1px 4px black;
margin: 12pt 0;
padding: 0 0 6pt 0;
position: relative;
}

div.admonition > p.admonition-title {
background-color: var(--admonition-title-background-color);
border-radius: 5px 5px 0 0;
color: silver;
margin: 0 0 6pt 0;
padding: 4px 12px 4px 30px;
}

div.admonition > p.admonition-title:before {
color: var(--admonition-icon-color);
content: var(--admonition-icon);
font-family: var(--font-awesome);
left: 8px;
padding-right: 4pt;
position: absolute;
}

div.admonition > p {
margin: 0 12px 12px 30px;
}

div.admonition.warning {
--admonition-border-color: orange;
--admonition-icon: '\f071';
--admonition-icon-color: gold;
--admonition-title-background-color: #503e1a;
}

div.admonition.error {
--admonition-border-color: red;
--admonition-icon: '\f188';
--admonition-icon-color: #ff7c7c;
--admonition-title-background-color: #460202;
}

div.admonition.note {
--admonition-border-color: #6eb1cc;
--admonition-icon: '\f05a';
--admonition-icon-color: #ace3fa;
--admonition-title-background-color: #235179;
}

div.admonition.seealso {
--admonition-border-color: #54d452;
--admonition-icon: '\f064';
--admonition-icon-color: #acfab6;
--admonition-title-background-color: #285131;
}
114 changes: 114 additions & 0 deletions doc/flame/camera_component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Camera component

```{note}
This document describes a new experimental API. The more traditional approach
for handling a camera is described in [](camera_and_viewport.md).
```

Camera-as-a-component is an alternative way of structuring a game, an approach
that allows more flexibility in placing the camera, or even having more than
one camera simultaneously.

In order to understand how this approach works, imagine that your game world is
an entity that exists _somewhere_ independently from your application. Imagine
that your game is merely a window through which you can look into that world.
That you can close that window at any moment, and the game world would still be
there. Or, on the contrary, you can open multiple windows that all look at the
same world (or different worlds) at the same time.

With this mindset, we can now understand how camera-as-a-component works.

First, there is the [](#world) class, which contains all components that are
inside your game world. The `World` component can be mounted anywhere, for
example at the root of your game class.

Then, a [](#cameracomponent) class that "looks at" the `World`. The
`CameraComponent` has a `Viewport` and a `Viewfinder` inside, allowing both the
flexibility of rendering the world at any place on the screen, and also control
the viewing location and angle.


## World

This component should be used to host all other components that comprise your
game world. The main property of the `World` class is that it does not render
through traditional means -- instead, create one or more [](#cameracomponent)s
to "look at" the world.

A game can have multiple `World` instances that can be rendered either at the
same time, or at different times. For example, if you have two worlds A and B
and a single camera, then switching that camera's target from A to B will
instantaneously switch the view to world B without having to unmount A and
then mount B.


## CameraComponent

This is a component through which a `World` is rendered. It requires a
reference to a `World` instance during construction; however later the target
world can be replaced with another one. Multiple cameras can observe the same
world at the same time.

A `CameraComponent` has two other components inside: a [](#viewport) and a
[](#viewfinder). Unlike the `World` object, the camera owns the viewport and
the viewfinder, which means those components are children of the camera.

There is also a static property `CameraComponent.currentCamera` which is not
null only during the rendering stage, and it returns the camera object that
currently performs rendering. This is needed only for certain advanced use
cases where the rendering of a component depends on the camera settings. For
example, some components may decide to skip rendering themselves and their
children if they are outside of the camera's viewport.


## Viewport

The `Viewport` is a window through which the `World` is seen. That window
has a certain size, shape, and position on the screen. There are multiple kinds
of viewports available, and you can always implement your own.

The `Viewport` is a component, which means you can add other components to it.
These children components will be affected by the viewport's position, but not
by its clip mask. Thus, if a viewport is a "window" into the game world, then
its children are things that you can put on top of the window.

Adding elements to the viewport is a convenient way to implement "HUD"
components.

The following viewports are available:
- `MaxViewport` (default) -- this viewport expands to the maximum size allowed
by the game, i.e. it will be equal to the size of the game canvas.
- `FixedSizeViewport` -- a simple rectangular viewport with predefined size.
- `FixedAspectRatioViewport` -- a rectangular viewport which expands to fit
into the game canvas, but preserving its aspect ratio.
- `CircularViewport` -- a viewport in the shape of a circle, fixed size.


## Viewfinder

This part of the camera is responsible for knowing which location in the
underlying game world we are currently looking at. The `Viewfinder` also
controls the zoom level, and the rotation angle of the view.

Components added to the `Viewfinder` as children will be rendered as if they
were part of the world (but on top). It is more useful to add behavioral
components to the viewfinder, for example [](effects.md) or other controllers.


## Comparison to the traditional camera

Compared to the normal [Camera](camera_and_viewport.md), the `CameraComponent`
has several advantages and drawbacks.

Pros:
- Multiple cameras can be added to the game at the same time;
- More flexibility in choosing the placement and the size of the viewport;
- Switching camera from one world to another can happen instantaneously,
without having to unmount one world and then mount another;
- Support rotation of the world view;
- (NYI) Effects can be applied either to the viewport, or to the viewfinder;
- (NYI) More flexible camera controllers.

Cons (we are planning to address these in the near future):
- Camera controls are not yet implemented;
- Events propagation may not always work correctly.
1 change: 1 addition & 0 deletions doc/flame/flame.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Collision detection <collision_detection.md>
Effects <effects.md>
Camera & Viewport <camera_and_viewport.md>
Camera component <camera_component.md>
Inputs <inputs/inputs.md>
Rendering <rendering/rendering.md>
Other <other/other.md>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:dashbook/dashbook.dart';
import 'package:flame/game.dart';

import '../../commons/commons.dart';
import 'camera_component_example.dart';
import 'coordinate_systems_example.dart';
import 'fixed_resolution_example.dart';
import 'follow_component_example.dart';
Expand Down Expand Up @@ -59,5 +60,11 @@ void addCameraAndViewportStories(Dashbook dashbook) {
(context) => const CoordinateSystemsWidget(),
codeLink: baseLink('camera_and_viewport/coordinate_systems_example.dart'),
info: CoordinateSystemsExample.description,
)
..add(
'CameraComponent',
(context) => GameWidget(game: CameraComponentExample()),
codeLink: baseLink('camera_and_viewport/camera_component_example.dart'),
info: CameraComponentExample.description,
);
}
Loading