Ejemplo n.º 1
0
 def bottom(self, value: Union[float, int]):
     self.position = Vector(self.position.x, value + (self.height / 2))
Ejemplo n.º 2
0
def test_convert_roundtrip(coerce, x: Vector):
    assert x == Vector(coerce(x))
Ejemplo n.º 3
0
#!/usr/bin/env python3
import pyperf  # type: ignore

from ppb_vector import Vector
from utils import *

r = pyperf.Runner()
x = Vector(1, 1)
y = Vector(0, 1)
scalar = 123

for f in BINARY_OPS | BINARY_SCALAR_OPS | BOOL_OPS:  # type: ignore
    r.bench_func(f.__name__, f, x, y)

for f in UNARY_OPS | UNARY_SCALAR_OPS:  # type: ignore
    r.bench_func(f.__name__, f, x)

for f in SCALAR_OPS:  # type: ignore
    r.bench_func(f.__name__, f, x, scalar)  # type: ignore
Ejemplo n.º 4
0
 def top(self, value):
     self.position = Vector(self.position.x, value - self._offset_value)
Ejemplo n.º 5
0
class Camera(RectangleShapeMixin, GameObject):
    """
    A simple Camera.

    Intentionally tightly coupled to the renderer to allow information flow
    back and forth.

    There is a one-to-one relationship between cameras and scenes.

    You can subclass Camera to add event handlers. If you do so, set the
    camera_class class attribute of your scene to your subclass. The renderer
    will instantiate the correct type.
    """
    position = Vector(0, 0)
    size = 0  # Cameras never render, so their logical game unit size is 0

    def __init__(self, renderer, target_game_unit_width: Real,
                 viewport_dimensions: Tuple[int, int]):
        """
        You shouldn't instantiate your own camera in general. If you want to
        override the Camera, see above.

        :param renderer: The renderer associated with the camera.
        :type renderer: ~ppb.systems.renderer.Renderer
        :param target_game_unit_width: The number of game units wide you
           would like to display. The actual width may be less than this
           depending on the ratio to the viewport (as it can only be as wide
           as there are pixels.)
        :type target_game_unit_width: Real
        :param viewport_dimensions: The pixel dimensions of the rendered
           viewport in (width, height) form.
        :type viewport_dimensions: Tuple[int, int]
        """
        self.renderer = renderer
        self.target_game_unit_width = target_game_unit_width
        self.viewport_dimensions = viewport_dimensions
        self.pixel_ratio = None
        self._width = None
        self._height = None
        self._set_dimensions(target_width=target_game_unit_width)

    @property
    def width(self) -> Real:
        """
        The game unit width of the viewport.

        See :mod:`ppb.sprites` for details about game units.

        When setting this property, the resulting width may be slightly
        different from the value provided based on the ratio between the width
        of the window in screen pixels and desired number of game units to
        represent.

        When you set the width, the height will change as well.
        """
        return self._width

    @width.setter
    def width(self, target_width):
        self._set_dimensions(target_width=target_width)

    @property
    def height(self) -> Real:
        """
        The game unit height of the viewport.

        See :mod:`ppb.sprites` for details about game units.

        When setting this property, the resulting height may be slightly
        different from the value provided based on the ratio between the height
        of the window in screen pixels and desired number of game units to
        represent.

        When you set the height, the width will change as well.
        """
        return self._height

    @height.setter
    def height(self, target_height):
        self._set_dimensions(target_height=target_height)

    def point_is_visible(self, point: Vector) -> bool:
        """
        Determine if a given point is in view of the camera.

        :param point: A vector representation of a point in game units.
        :type point: Vector
        :return: Whether the point is in view or not.
        :rtype: bool
        """
        return (self.left <= point.x <= self.right
                and self.bottom <= point.y <= self.top)

    def sprite_in_view(self, sprite: Sprite) -> bool:
        """
        Determine if a given sprite is in view of the camera.

        Does not guarantee that the sprite will be rendered, only that it
        exists in the visible space.

        A sprite without area (size=0 or lacking width, height, or any of the
        sides accessors) behave as :meth:`point_is_visible`.

        :param sprite: The sprite to check
        :type: Sprite
        :return: Whether the sprite is in the space in view of the camera.
        :rtype: bool
        """
        if not _sprite_has_rectangular_region(sprite):
            return self.point_is_visible(sprite.position)

        width = max(self.right, sprite.right) - min(self.left, sprite.left)
        height = max(self.top, sprite.top) - min(self.bottom, sprite.bottom)
        max_width = self.width + sprite.width
        max_height = self.height + sprite.height
        print(f"W: {width}, H: {height}, MW: {max_width}, MH: {max_height}")
        return width < max_width and height < max_height

    def translate_point_to_screen(self, point: Vector) -> Vector:
        """
        Convert a vector from game position to screen position.

        :param point: A vector in game units
        :type point: Vector
        :return: A vector in pixels.
        :rtype: Vector
        """
        return Vector(point.x - self.left,
                      self.top - point.y) * self.pixel_ratio

    def translate_point_to_game_space(self, point: Vector) -> Vector:
        """
        Convert a vector from screen position to game position.

        :param point: A vector in pixels
        :type point: Vector
        :return: A vector in game units.
        :rtype: Vector
        """
        scaled = point / self.pixel_ratio
        return Vector(self.left + scaled.x, self.top - scaled.y)

    def _set_dimensions(self, target_width=None, target_height=None):
        # Set new pixel ratio
        viewport_width, viewport_height = self.viewport_dimensions
        if target_width is not None and target_height is not None:
            raise ValueError("Can only set one dimension at a time.")
        elif target_width is not None:
            game_unit_target = target_width
            pixel_value = viewport_width
        elif target_height is not None:
            game_unit_target = target_height
            pixel_value = viewport_height
        else:
            raise ValueError("Must set target_width or target_height")
        self.pixel_ratio = pixel_value / game_unit_target
        self._width = viewport_width / self.pixel_ratio
        self._height = viewport_height / self.pixel_ratio
Ejemplo n.º 6
0
 def right(self) -> Vector:
     """
     Get the corner vector
     """
     self._attribute_gate(RIGHT, [LEFT, RIGHT])
     return Vector(float(self.parent.right), float(self))
Ejemplo n.º 7
0
 def left(self, value: float):
     self.position = Vector(value + self._offset_value, self.position.y)
Ejemplo n.º 8
0
 def right_middle(self, value: VectorLike):
     value = Vector(value)
     self.position = Vector(value.x - self.width / 2, value.y)
Ejemplo n.º 9
0
 def top_middle(self, value: VectorLike):
     value = Vector(value)
     self.position = Vector(value.x, value.y - self.height / 2)
Ejemplo n.º 10
0
 def bottom_middle(self, value: VectorLike):
     value = Vector(value)
     self.position = Vector(value.x, value.y + self.height / 2)
Ejemplo n.º 11
0
 def left_middle(self, value: VectorLike):
     value = Vector(value)
     self.position = Vector(value.x + self.width / 2, value.y)
Ejemplo n.º 12
0
 def bottom_right(self) -> Vector:
     return Vector(self.right, self.bottom)
Ejemplo n.º 13
0
 def bottom_left(self, vector: Vector):
     vector = Vector(vector)
     x = vector.x + (self.width / 2)
     y = vector.y + (self.height / 2)
     self.position = Vector(x, y)
Ejemplo n.º 14
0
 def top_right(self, vector: Vector):
     vector = Vector(vector)
     x = vector.x - (self.width / 2)
     y = vector.y - (self.height / 2)
     self.position = Vector(x, y)
Ejemplo n.º 15
0
 def top(self) -> Vector:
     """
     Get the corner vector
     """
     self._attribute_gate(TOP, [TOP, BOTTOM])
     return Vector(float(self), float(self.parent.top))
Ejemplo n.º 16
0
 def center(self, vector: Vector):
     self.position = Vector(vector)
Ejemplo n.º 17
0
 def bottom(self) -> Vector:
     """
     Get the corner vector
     """
     self._attribute_gate(BOTTOM, [TOP, BOTTOM])
     return Vector(float(self), float(self.parent.bottom))
Ejemplo n.º 18
0
def test_ctor_noncopy_same(v: Vector):
    assert Vector(v) is v
Ejemplo n.º 19
0
 def center(self, value: ppb_vector.VectorLike):
     self.position = Vector(value)
Ejemplo n.º 20
0
def test_ctor_vector_like(v: Vector):
    for v_like in vector_likes(v):
        vector = Vector(v_like)
        assert vector == v == v_like
Ejemplo n.º 21
0
 def right(self, value):
     self.position = Vector(value - self._offset_value, self.position.y)
Ejemplo n.º 22
0
import math
from math import cos, fabs, radians, sin, sqrt

import hypothesis.strategies as st
import pytest  # type: ignore
from hypothesis import assume, example, given, note

from ppb_vector import Vector
from utils import angle_isclose, angles, floats, isclose, vectors


data_exact = [
    (Vector(1, 1), -90, Vector(1, -1)),
    (Vector(1, 1), 0, Vector(1, 1)),
    (Vector(1, 1), 90, Vector(-1, 1)),
    (Vector(1, 1), 180, Vector(-1, -1)),
]


@pytest.mark.parametrize("input, angle, expected", data_exact,
                         ids=[str(angle) for _, angle, _ in data_exact])
def test_exact_rotations(input, angle, expected):
    assert input.rotate(angle) == expected
    assert input.angle(expected) == angle


# angle (in degrees) -> (sin, cos)
#  values from 0 to 45°
#  lifted from https://en.wikibooks.org/wiki/Trigonometry/Selected_Angles_Reference
remarkable_angles = {
    15: ((sqrt(6) + sqrt(2)) / 4, (sqrt(6) - sqrt(2)) / 4),
Ejemplo n.º 23
0
 def bottom(self, value):
     self.position = Vector(self.position.x, value + self._offset_value)
Ejemplo n.º 24
0
def test_multiples_values(x, y, expected):
    assert (Vector(x) + y) == expected
Ejemplo n.º 25
0
def test_convert_class(vector_like):
    vector = Vector(vector_like)
    assert isinstance(vector, Vector)
    assert vector == vector_like
Ejemplo n.º 26
0
"""
The ordinal directions.

A collection of normalized vectors to be referenced by name.

Best used for the positions or facings of :class:`Sprites <ppb.Sprite>`.
"""
from ppb_vector import Vector

Up = Vector(
    0, 1).normalize()  #: Unit vector to the top of the screen from center.
Down = Vector(
    0, -1).normalize()  #: Unit vector to the bottom of the screen from center.
Left = Vector(
    -1, 0).normalize()  #: Unit vector to the left of the screen from center.
Right = Vector(
    1, 0).normalize()  #: Unit vector to the right of the screen from center.
UpAndLeft = (Up + Left).normalize(
)  #: Unit vector diagonally up and to the left of the screen from center.
UpAndRight = (Up + Right).normalize(
)  #: Unit vector diagonally up and to the right of the screen from center.
DownAndLeft = (Down + Left).normalize(
)  #: Unit vector diagonally down and to the left of the screen from center.
DownAndRight = (Down + Right).normalize(
)  #: Unit vector diagonally down and to the right of the screen from center.
Ejemplo n.º 27
0
def test_convert_roundtrip_positional(coerce, x: Vector):
    assert x == Vector(*coerce(x))
Ejemplo n.º 28
0
 def facing(self):
     """
     The direction the "front" is facing
     """
     return Vector(*self.basis).rotate(self.rotation).normalize()
Ejemplo n.º 29
0
 def viewport_width(self, value: int):
     self._viewport_width = value
     self.viewport_offset = Vector(value / 2, self.viewport_height / 2)
Ejemplo n.º 30
0
 def top(self, value: Union[int, float]):
     self.position = Vector(self.position.x, value - (self.height / 2))