Skip to content

View these Examples #2407

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

Merged
merged 21 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e78e41e
Updated Tetris example to use View and improved stone selection logic
DragonMoffon Oct 7, 2024
d14a1e6
Updated text localisation example to use View and removed unneccisary…
DragonMoffon Oct 7, 2024
f5dad99
Updated Timer example to use View and GLOBAL_CLOCK
DragonMoffon Oct 7, 2024
6274ca8
Convert template platformer to use a View, and greatly imrpove multip…
DragonMoffon Oct 8, 2024
7512def
Updated tiled map examples to use View, and corrected many mistakes w…
DragonMoffon Oct 9, 2024
e6f8a88
Updated tank example and fixed more glaring issues
DragonMoffon Oct 9, 2024
b916b11
Merge remote-tracking branch 'origin/development'
DragonMoffon Oct 9, 2024
994d1fe
Added aliases for window properties commonly used in views
DragonMoffon Oct 10, 2024
f7cb6b3
Updated sprite enemies in platformer to use a View, and added ability…
DragonMoffon Oct 10, 2024
b2d3735
Updated pymunk joint builder to use View and fixed assertion error
DragonMoffon Oct 10, 2024
2cdb8d8
Updated the perspective example to use View, and Camera. Plus created…
DragonMoffon Oct 10, 2024
b5a5a1b
Update transform_multi example to not use custom window
DragonMoffon Oct 10, 2024
64a659e
Updated all standard examples to use a View over a custom Window
DragonMoffon Oct 10, 2024
d464313
Renaming all `MyGame` instances to `GameVIew`
DragonMoffon Oct 10, 2024
55e4584
Linting, and testing pass
DragonMoffon Oct 10, 2024
69d994b
tank example cleanup
DragonMoffon Oct 10, 2024
4e4e0dd
This ProxyWindow is getting on my nerves
DragonMoffon Oct 10, 2024
32d1da4
thanks eurvanos for the catch!
DragonMoffon Oct 10, 2024
95d889e
updating minimap rst
DragonMoffon Oct 10, 2024
6d63768
Updated view to store a per-instance background color rather than an …
DragonMoffon Oct 10, 2024
4d09f3a
:sparkles: black magic :sparkles:
DragonMoffon Oct 10, 2024
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
49 changes: 48 additions & 1 deletion arcade/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -1233,8 +1233,11 @@ class View:
window is used. (Normally you don't need to provide this).
"""

def __init__(self, window: Window | None = None) -> None:
def __init__(
self, window: Window | None = None, background_color: RGBOrA255 | None = None
) -> None:
self.window = arcade.get_window() if window is None else window
self.background_color: RGBOrA255 | None = background_color

def clear(
self,
Expand All @@ -1258,6 +1261,8 @@ def clear(
viewport (optional):
The viewport range to clear
"""
if color is None and color_normalized is None:
color = self.background_color
self.window.clear(color=color, color_normalized=color_normalized, viewport=viewport)

def on_update(self, delta_time: float) -> bool | None:
Expand Down Expand Up @@ -1520,3 +1525,45 @@ def on_mouse_leave(self, x: int, y: int) -> bool | None:
y: The y position the mouse entered the window
"""
pass

@property
def size(self) -> tuple[float, float]:
"""
An alias for `arcade.Window.size`
"""
return self.window.size

@property
def width(self) -> float:
"""
An alias for `arcade.Window.width`
"""
return self.window.width

@property
def height(self) -> float:
"""
An alias for `arcade.Window.height`
"""
return self.window.height

@property
def center(self) -> tuple[float, float]:
"""
An alias for `arcade.Window.center`
"""
return self.window.center

@property
def center_x(self) -> float:
"""
An alias for `arcade.Window.center_x`
"""
return self.window.center_x

@property
def center_y(self) -> float:
"""
An alias for `arcade.Window.center_y`
"""
return self.window.center_y
57 changes: 47 additions & 10 deletions arcade/camera/camera_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,15 @@ def unproject(self, screen_coordinate: Point) -> Vec3:
_view = generate_view_matrix(self.view_data)
return unproject_orthographic(screen_coordinate, self.viewport.viewport, _view, _projection)

def equalise(self) -> None:
"""
Forces the projection to match the size of the viewport.
When matching the projection to the viewport the method keeps
the projections center in the same relative place.
"""
x, y = self._projection_data.rect.x, self._projection_data.rect.y
self._projection_data.rect = XYWH(x, y, self.viewport_width, self.viewport_height)

def match_screen(
self,
and_projection: bool = True,
Expand Down Expand Up @@ -350,6 +359,44 @@ def match_screen(
aspect=aspect,
)

def match_target(
self,
and_projection: bool = True,
and_scissor: bool = True,
and_position: bool = False,
aspect: float | None = None,
) -> None:
"""
Sets the viewport to the size of the Camera2D's render target.

Args:
and_projection: Flag whether to also equalize the projection to the viewport.
On by default
and_scissor: Flag whether to also equalize the scissor box to the viewport.
On by default
and_position: Flag whether to also center the camera to the viewport.
Off by default
aspect_ratio: The ratio between width and height that the viewport should
be constrained to. If unset then the viewport just matches the window
size. The aspect ratio describes how much larger the width should be
compared to the height. i.e. for an aspect ratio of ``4:3`` you should
input ``4.0/3.0`` or ``1.33333...``. Cannot be equal to zero.
Raises:
ValueError: Will be raised if the Camera2D was has no render target.
"""
if self.render_target is None:
raise ValueError(
"Tried to match a non-exsistant render target. Please use `match_screen` instead"
)

self.update_viewport(
LRBT(*self.render_target.viewport),
and_projection=and_projection,
and_scissor=and_scissor,
and_position=and_position,
aspect=aspect,
)

def update_viewport(
self,
new_viewport: Rect,
Expand Down Expand Up @@ -396,7 +443,6 @@ def update_viewport(
self.position = self.viewport.center

def aabb(self) -> Rect:
# TODO test
"""
Retrieve the axis-aligned bounds box of the camera's view area.
If the camera isn't rotated , this will be precisely the view area,
Expand Down Expand Up @@ -820,15 +866,6 @@ def zoom(self, _zoom: float) -> None:
"""
self._camera_data.zoom = _zoom

def equalise(self) -> None:
"""
Forces the projection to match the size of the viewport.
When matching the projection to the viewport the method keeps
the projections center in the same relative place.
"""
x, y = self._projection_data.rect.x, self._projection_data.rect.y
self._projection_data.rect = XYWH(x, y, self.viewport_width, self.viewport_height)

# top_left
@property
def top_left(self) -> Vec2:
Expand Down
3 changes: 3 additions & 0 deletions arcade/camera/grips/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
constrain_boundary_xz,
constrain_boundary_xyz,
)
from arcade.camera.grips.position import look_at, orbit


__all__ = (
Expand All @@ -43,4 +44,6 @@
"constrain_boundary_yz",
"constrain_boundary_xz",
"constrain_boundary_xyz",
"look_at",
"orbit",
)
48 changes: 48 additions & 0 deletions arcade/camera/grips/position.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from __future__ import annotations

from pyglet.math import Vec3

from arcade.camera import CameraData
from arcade.math import quaternion_rotation
from arcade.types import Point3


def look_at(camera: CameraData, target: Point3, up: Point3 | None = None) -> tuple[Point3, Point3]:
"""
Calculate the neccisary forward and up vectors to have the camera look towards
the target point.

Uses the camera's up if none is provided.
Args:
camera: The CameraData to work from
target: The point in 3D world space to look at
up: An optional up axis to refer to when calculating the true up vector.
"""
px, py, pz = camera.position
tx, ty, tz = target
dx, dy, dz = tx - px, ty - py, tz - pz

up = up or camera.up

f = Vec3(dx, dy, dz).normalize()
r = f.cross(up)
u = r.cross(f).normalize()

return f, u


def orbit(camera: CameraData, origin: Point3, axis: Point3, angle: float) -> Point3:
"""
Find the new position for the camera when rotated around the origin

Args:
camera: The CameraData to work from
origin: The point around which to orbit
axis: The axis to rotate around, like the stick on a spinning top.
angle: The angle in degrees to rotate by
"""
px, py, pz = camera.position
tx, ty, tz = origin

rx, ry, rz = quaternion_rotation(axis, (px - tx, py - ty, pz - tz), angle)
return tx + rx, ty + ry, tz + rz
24 changes: 17 additions & 7 deletions arcade/examples/array_backed_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,22 @@
MARGIN = 5

# Do the math to figure out our screen dimensions
SCREEN_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
SCREEN_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
SCREEN_TITLE = "Array Backed Grid Example"
WINDOW_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
WINDOW_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
WINDOW_TITLE = "Array Backed Grid Example"


class MyGame(arcade.Window):
class GameView(arcade.View):
"""
Main application class.
"""

def __init__(self, width, height, title):
def __init__(self):
"""
Set up the application.
"""

super().__init__(width, height, title)
super().__init__()

# Create a 2 dimensional array. A two-dimensional
# array is simply a list of lists.
Expand Down Expand Up @@ -104,7 +104,17 @@ def on_mouse_press(self, x, y, button, modifiers):


def main():
MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
""" Main function """
# Create a window class. This is what actually shows up on screen
window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)

# Create the GameView
game = GameView()

# Show GameView on screen
window.show_view(game)

# Start the arcade game loop
arcade.run()


Expand Down
24 changes: 17 additions & 7 deletions arcade/examples/array_backed_grid_buffered.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@
MARGIN = 5

# Do the math to figure out our screen dimensions
SCREEN_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
SCREEN_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
SCREEN_TITLE = "Array Backed Grid Buffered Example"
WINDOW_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
WINDOW_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
WINDOW_TITLE = "Array Backed Grid Buffered Example"


class MyGame(arcade.Window):
class GameView(arcade.View):
"""
Main application class.
"""

def __init__(self, width, height, title):
def __init__(self):
"""
Set up the application.
"""
super().__init__(width, height, title)
super().__init__()
self.shape_list = None

# Create a 2 dimensional array. A two dimensional
Expand Down Expand Up @@ -136,7 +136,17 @@ def on_mouse_press(self, x, y, button, modifiers):


def main():
MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
""" Main function """
# Create a window class. This is what actually shows up on screen
window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)

# Create the GameView
game = GameView()

# Show GameView on screen
window.show_view(game)

# Start the arcade game loop
arcade.run()


Expand Down
24 changes: 17 additions & 7 deletions arcade/examples/array_backed_grid_sprites_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,21 @@
MARGIN = 5

# Do the math to figure out our screen dimensions
SCREEN_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
SCREEN_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
SCREEN_TITLE = "Array Backed Grid Example"
WINDOW_WIDTH = (WIDTH + MARGIN) * COLUMN_COUNT + MARGIN
WINDOW_HEIGHT = (HEIGHT + MARGIN) * ROW_COUNT + MARGIN
WINDOW_TITLE = "Array Backed Grid Example"


class MyGame(arcade.Window):
class GameView(arcade.View):
"""
Main application class.
"""

def __init__(self, width, height, title):
def __init__(self):
"""
Set up the application.
"""
super().__init__(width, height, title)
super().__init__()

# Create a 2 dimensional array. A two dimensional
# array is simply a list of lists.
Expand Down Expand Up @@ -143,7 +143,17 @@ def on_mouse_press(self, x, y, button, modifiers):


def main():
MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
""" Main function """
# Create a window class. This is what actually shows up on screen
window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)

# Create the GameView
game = GameView()

# Show GameView on screen
window.show_view(game)

# Start the arcade game loop
arcade.run()


Expand Down
Loading
Loading