From b4c5a703155a156911e7d3793c8a5392590e2a71 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sun, 13 Jan 2019 16:08:11 -0500 Subject: [PATCH 01/15] sprites.py: Update Side to not directly mutate --- ppb/sprites.py | 55 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index 73c3dd27..bb0afd6f 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -80,8 +80,7 @@ def top(self): @top.setter def top(self, value): self._attribute_gate(TOP, [TOP, BOTTOM]) - setattr(self.parent, self.side, value[0]) - self.parent.top = value[1] + self.parent.position = self._mk_update_vector_side(TOP, value) @property def bottom(self): @@ -91,8 +90,7 @@ def bottom(self): @bottom.setter def bottom(self, value): self._attribute_gate(BOTTOM, [TOP, BOTTOM]) - setattr(self.parent, self.side, value[0]) - self.parent.bottom = value[1] + self.parent.position = self._mk_update_vector_side(BOTTOM, value) @property def left(self): @@ -102,8 +100,7 @@ def left(self): @left.setter def left(self, value): self._attribute_gate(LEFT, [LEFT, RIGHT]) - setattr(self.parent, self.side, value[1]) - self.parent.left = value[0] + self.parent.position = self._mk_update_vector_side(LEFT, value) @property def right(self): @@ -113,8 +110,7 @@ def right(self): @right.setter def right(self, value): self._attribute_gate(RIGHT, [LEFT, RIGHT]) - setattr(self.parent, self.side, value[1]) - self.parent.right = value[0] + self.parent.position = self._mk_update_vector_side(RIGHT, value) @property def center(self): @@ -125,12 +121,43 @@ def center(self): @center.setter def center(self, value): - if self.side in (TOP, BOTTOM): - setattr(self.parent, self.side, value[1]) - self.parent.center.x = value[0] - else: - setattr(self.parent, self.side, value[0]) - self.parent.position.y = value[1] + self.parent.position = self._mk_update_vector_center(value) + + def _mk_update_vector_side(self, attribute, value): + value = Vector(*value) + assert attribute != 'center' + # Does a bunch of dynamc resolution: + # Sprite.top.left + # ^ ^ attribute + # self.side + self_dimension, self_sign = Side.sides[self.side] + self_offset = self_sign * self.parent._offset_value + + attr_dimension, attr_sign = Side.sides[attribute] + attr_offset = attr_sign * self.parent._offset_value + + assert self_dimension != attr_dimension + + fields = { + self_dimension: value[self_dimension] - self_offset, + attr_dimension: value[attr_dimension] - attr_offset, + } + return Vector(**fields) + + def _mk_update_vector_center(self, value): + value = Vector(*value) + # Pretty similar to ._mk_update_vector_side() + self_dimension, self_sign = Side.sides[self.side] + self_offset = self_sign * self.parent._offset_value + + attr_dimension = 'y' if self_dimension == 'x' else 'x' + + fields = { + self_dimension: value[self_dimension] - self_offset, + attr_dimension: value[attr_dimension] + } + + return Vector(**fields) def _attribute_gate(self, attribute, bad_sides): if self.side in bad_sides: From 5b33f4189ddf9494d2f259167bd5a30a0e94e2d2 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sun, 13 Jan 2019 16:12:00 -0500 Subject: [PATCH 02/15] sprites.py: Update Sprite to not mutate vectors --- ppb/sprites.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index bb0afd6f..c62d0f47 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -212,10 +212,7 @@ def center(self) -> Vector: @center.setter def center(self, value: Sequence[float]): - x = value[0] - y = value[1] - self.position.x = x - self.position.y = y + self.position = Vector(*value) @property def left(self) -> Side: @@ -223,7 +220,7 @@ def left(self) -> Side: @left.setter def left(self, value: float): - self.position.x = value + self._offset_value + self.position = Vector(value + self._offset_value, self.position.y) @property def right(self) -> Side: @@ -231,7 +228,7 @@ def right(self) -> Side: @right.setter def right(self, value): - self.position.x = value - self._offset_value + self.position = Vector(value - self._offset_value, self.position.y) @property def top(self): @@ -239,7 +236,7 @@ def top(self): @top.setter def top(self, value): - self.position.y = value + self._offset_value + self.position = Vector(self.position.x, value + self._offset_value) @property def bottom(self): @@ -247,7 +244,7 @@ def bottom(self): @bottom.setter def bottom(self, value): - self.position.y = value - self._offset_value + self.position = Vector(self.position.x, value - self._offset_value) @property def _offset_value(self): From 8b45c373aa3d3ad3275d9bc1e18d36583b56000c Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sun, 13 Jan 2019 16:15:58 -0500 Subject: [PATCH 03/15] sprites.py: Side: Refactor into _lookup_side() --- ppb/sprites.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index c62d0f47..603c84ee 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -66,11 +66,14 @@ def __gt__(self, other): def __lt__(self, other): return self.value < other + def _lookup_side(self, side): + dimension, sign = self.sides[side] + return dimension, sign * self.parent._offset_value + @property def value(self): - coordinate, multiplier = self.sides[self.side] - offset = self.parent._offset_value - return self.parent.position[coordinate] + (offset * multiplier) + dimension, offset = self._lookup_side(self.side) + return self.parent.position[dimension] + offset @property def top(self): @@ -130,11 +133,9 @@ def _mk_update_vector_side(self, attribute, value): # Sprite.top.left # ^ ^ attribute # self.side - self_dimension, self_sign = Side.sides[self.side] - self_offset = self_sign * self.parent._offset_value + self_dimension, self_offset = self._lookup_side(self.side) - attr_dimension, attr_sign = Side.sides[attribute] - attr_offset = attr_sign * self.parent._offset_value + attr_dimension, attr_offset = self._lookup_side(attribute) assert self_dimension != attr_dimension @@ -147,8 +148,7 @@ def _mk_update_vector_side(self, attribute, value): def _mk_update_vector_center(self, value): value = Vector(*value) # Pretty similar to ._mk_update_vector_side() - self_dimension, self_sign = Side.sides[self.side] - self_offset = self_sign * self.parent._offset_value + self_dimension, self_offset = self._lookup_side(self.side) attr_dimension = 'y' if self_dimension == 'x' else 'x' From cd2b94ded464056366d861317572a9d320833f4f Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sun, 13 Jan 2019 16:17:43 -0500 Subject: [PATCH 04/15] sprites.py: Update Sprite.rotate() to actually do something. It was assuming that Vector.rotate() did an in-place mutation, which is not the case. --- ppb/sprites.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index 603c84ee..91580661 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -251,7 +251,7 @@ def _offset_value(self): return self.size / 2 def rotate(self, degrees: Number): - self.facing.rotate(degrees) + self.facing = self.facing.rotate(degrees) def __image__(self): if self.image is None: From 1976023b256a70fa529a2512e88bf3939ee65bd2 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sun, 13 Jan 2019 16:19:00 -0500 Subject: [PATCH 05/15] sprites.py: Update for new Vector API --- ppb/sprites.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index 91580661..6e409df1 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -127,7 +127,7 @@ def center(self, value): self.parent.position = self._mk_update_vector_center(value) def _mk_update_vector_side(self, attribute, value): - value = Vector(*value) + value = Vector.convert(value) assert attribute != 'center' # Does a bunch of dynamc resolution: # Sprite.top.left @@ -146,7 +146,7 @@ def _mk_update_vector_side(self, attribute, value): return Vector(**fields) def _mk_update_vector_center(self, value): - value = Vector(*value) + value = Vector.convert(value) # Pretty similar to ._mk_update_vector_side() self_dimension, self_offset = self._lookup_side(self.side) @@ -212,7 +212,7 @@ def center(self) -> Vector: @center.setter def center(self, value: Sequence[float]): - self.position = Vector(*value) + self.position = Vector.convert(value) @property def left(self) -> Side: From dd7cdc25ad9e27b6f740b8eff315878f37a659ef Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Sun, 13 Jan 2019 16:28:11 -0500 Subject: [PATCH 06/15] Some vector API updates --- ppb/sprites.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index 6e409df1..11b89aa5 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -2,7 +2,7 @@ from numbers import Number from os.path import realpath from pathlib import Path -from typing import Dict, Iterable, AnyStr, Sequence +from typing import Dict, Iterable, Sequence from typing import Union from ppb import Vector @@ -26,7 +26,7 @@ class Side: BOTTOM: ('y', 1) } - def __init__(self, parent: 'BaseSprite',side: AnyStr): + def __init__(self, parent: 'BaseSprite', side: str): self.side = side self.parent = parent @@ -190,8 +190,8 @@ def __init__(self, **kwargs): # Make these instance properties with fresh instances # Don't use Vector.convert() because we need copying - self.position = Vector(*self.position) - self.facing = Vector(*self.facing) + self.position = Vector(self.position) + self.facing = Vector(self.facing) # Initialize things for k, v in kwargs.items(): @@ -200,7 +200,7 @@ def __init__(self, **kwargs): k = 'position' # Castings if k in ('position', 'facing'): - v = Vector(*v) # Vector.convert() when that ships. + v = Vector.convert(v) setattr(self, k, v) # Trigger some calculations From b8c7158b0aa0e7cd399463420a2e3023e5d453ad Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Thu, 4 Apr 2019 17:41:06 -0400 Subject: [PATCH 07/15] Remove the use of `.convert()` --- ppb/sprites.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index 11b89aa5..b40704a6 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -127,7 +127,7 @@ def center(self, value): self.parent.position = self._mk_update_vector_center(value) def _mk_update_vector_side(self, attribute, value): - value = Vector.convert(value) + value = Vector(value) assert attribute != 'center' # Does a bunch of dynamc resolution: # Sprite.top.left @@ -146,7 +146,7 @@ def _mk_update_vector_side(self, attribute, value): return Vector(**fields) def _mk_update_vector_center(self, value): - value = Vector.convert(value) + value = Vector(value) # Pretty similar to ._mk_update_vector_side() self_dimension, self_offset = self._lookup_side(self.side) From 13a1f7d51540765681ae0f8c59bffc90b581f823 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Fri, 12 Apr 2019 20:50:27 -0400 Subject: [PATCH 08/15] Require ppb-vector 1.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0424c85e..62abc412 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ pygame -ppb-vector +ppb-vector>=1.0a1 dataclasses; python_version < "3.7" From fa9c88419d4488fb2a6c83ed501942d2d9cd2d55 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Fri, 12 Apr 2019 21:01:26 -0400 Subject: [PATCH 09/15] Strip the last remanants of old Vector construction --- ppb/sprites.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index ec54d14e..a605e5d9 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -127,6 +127,9 @@ def center(self, value): self.parent.position = self._mk_update_vector_center(value) def _mk_update_vector_side(self, attribute, value): + """ + Calculate the updated vector for the given corner + """ value = Vector(value) assert attribute != 'center' # Does a bunch of dynamc resolution: @@ -143,9 +146,12 @@ def _mk_update_vector_side(self, attribute, value): self_dimension: value[self_dimension] - self_offset, attr_dimension: value[attr_dimension] - attr_offset, } - return Vector(**fields) + return Vector(fields) def _mk_update_vector_center(self, value): + """ + Calculate the update vector for the midpoint of this side + """ value = Vector(value) # Pretty similar to ._mk_update_vector_side() self_dimension, self_offset = self._lookup_side(self.side) @@ -157,7 +163,7 @@ def _mk_update_vector_center(self, value): attr_dimension: value[attr_dimension] } - return Vector(**fields) + return Vector(fields) def _attribute_gate(self, attribute, bad_sides): if self.side in bad_sides: @@ -235,7 +241,7 @@ def center(self) -> Vector: @center.setter def center(self, value: Sequence[float]): - self.position = Vector.convert(value) + self.position = Vector(value) @property def left(self) -> Side: From 1ee4553d7640340ce2e6f3014ed8a9f7f9453f7b Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Fri, 12 Apr 2019 21:08:14 -0400 Subject: [PATCH 10/15] Fix rotation stuff: * Add facing setter * Remove redundant .rotate() definition --- ppb/sprites.py | 7 ++++--- tests/test_sprites.py | 9 --------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index a605e5d9..6eacb880 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -187,6 +187,10 @@ class Rotatable: def facing(self): return Vector(*self.basis).rotate(self.rotation).normalize() + @facing.setter + def facing(self, value): + self.rotation = self.basis.angle(value) + @property def rotation(self): return self._rotation @@ -279,9 +283,6 @@ def bottom(self, value): def _offset_value(self): return self.size / 2 - def rotate(self, degrees: Number): - self.facing = self.facing.rotate(degrees) - def __image__(self): if self.image is None: self.image = f"{type(self).__name__.lower()}.png" diff --git a/tests/test_sprites.py b/tests/test_sprites.py index 4e766955..1a264f1f 100644 --- a/tests/test_sprites.py +++ b/tests/test_sprites.py @@ -82,15 +82,6 @@ def test_bottom(self): self.assertEqual(self.sprite.position.x, 0) self.assertEqual(self.sprite.position.y, 1.5) - def test_center_accessors(self): - self.sprite.center.x = 20 - self.assertEqual(self.sprite.position.x, 20) - self.assertEqual(self.sprite.position.y, 0) - - self.sprite.center.y = 15 - self.assertEqual(self.sprite.position.x, 20) - self.assertEqual(self.sprite.position.y, 15) - def test_left_top(self): self.assertEqual(self.sprite.left.top, Vector(-0.5, -0.5)) From bf0c6fe87fdee645f2cd5cf55935739f2ea5efbe Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Fri, 12 Apr 2019 21:21:31 -0400 Subject: [PATCH 11/15] Update Sequence[float] to correct annotation Co-Authored-By: astronouth7303 --- ppb/sprites.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ppb/sprites.py b/ppb/sprites.py index 6eacb880..2643a71a 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -244,7 +244,7 @@ def center(self) -> Vector: return self.position @center.setter - def center(self, value: Sequence[float]): + def center(self, value: ppb_vector.vector2.VectorLike): self.position = Vector(value) @property From 0aac18f898aed7fa48bf1f66c27378f7580493e6 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Fri, 12 Apr 2019 23:12:55 -0400 Subject: [PATCH 12/15] Forgot an import --- ppb/sprites.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ppb/sprites.py b/ppb/sprites.py index 6eacb880..3e0dcd77 100644 --- a/ppb/sprites.py +++ b/ppb/sprites.py @@ -8,6 +8,8 @@ from ppb import Vector from ppb.events import EventMixin +import ppb_vector.vector2 + TOP = "top" BOTTOM = "bottom" From 303a30124baf229f94360675baeffacc71ae21ff Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 14 Apr 2019 18:45:11 -0400 Subject: [PATCH 13/15] requirements.txt: Set upper limit on compatibility Co-Authored-By: astronouth7303 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 62abc412..bd6546a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ pygame -ppb-vector>=1.0a1 +ppb-vector >= 1.0a1, < 2 dataclasses; python_version < "3.7" From ec06f84a08e95d9c7c83af5cd8d428ebb7271561 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Tue, 23 Apr 2019 17:09:31 -0400 Subject: [PATCH 14/15] Flip Y-axis --- ppb/camera.py | 14 +++++++++++--- tests/test_camera.py | 14 +++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/ppb/camera.py b/ppb/camera.py index 10528c6e..77d1cfae 100644 --- a/ppb/camera.py +++ b/ppb/camera.py @@ -96,10 +96,18 @@ def in_frame(self, sprite: BaseSprite) -> bool: self.frame_bottom >= sprite.top ) - def translate_to_frame(self, point:Vector) -> Vector: + def translate_to_frame(self, point: Vector) -> Vector: + """ + Converts a vector from PyGame to in-game coordinate space + """ offset = (point - self.viewport_offset) * (1/self.pixel_ratio) - return self.position + offset + loc = self.position + offset + return loc.update(y=-loc.y) - def translate_to_viewport(self, point:Vector) -> Vector: + def translate_to_viewport(self, point: Vector) -> Vector: + """ + Converts a vector from in-game to PyGame coordinate space + """ + point = point.update(y=-point.y) offset = (point - self.position) * self.pixel_ratio return self.viewport_offset + offset diff --git a/tests/test_camera.py b/tests/test_camera.py index 6b29781e..b28bfec7 100644 --- a/tests/test_camera.py +++ b/tests/test_camera.py @@ -30,20 +30,20 @@ def test_camera_translate_to_frame(): cam = Camera(viewport=(0, 0, 800, 600), pixel_ratio=80) assert cam.position == Vector(0, 0) assert cam.translate_to_frame(Vector(400, 300)) == Vector(0, 0) - assert cam.translate_to_frame(Vector(560, 220)) == Vector(2, -1) + assert cam.translate_to_frame(Vector(560, 220)) == Vector(2, 1) cam.position = Vector(5, 5) - assert cam.translate_to_frame(Vector(400, 300)) == Vector(5, 5) - assert cam.translate_to_frame(Vector(560, 220)) == Vector(7, 4) + assert cam.translate_to_frame(Vector(400, 300)) == Vector(5, -5) + assert cam.translate_to_frame(Vector(560, 220)) == Vector(7, -4) def test_camera_translate_to_viewport(): cam = Camera(viewport=(0, 0, 800, 600), pixel_ratio=80) assert cam.position == Vector(0, 0) assert cam.translate_to_viewport(Vector(0, 0)) == Vector(400, 300) - assert cam.translate_to_viewport(Vector(2, -1)) == Vector(560, 220) + assert cam.translate_to_viewport(Vector(2, 1)) == Vector(560, 220) cam.position = Vector(5, 5) - assert cam.translate_to_viewport(Vector(5, 5)) == Vector(400, 300) - assert cam.translate_to_viewport(Vector(7, 4)) == Vector(560, 220) + assert cam.translate_to_viewport(Vector(5, -5)) == Vector(400, 300) + assert cam.translate_to_viewport(Vector(7, -4)) == Vector(560, 220) def test_sprite_in_viewport(): @@ -70,4 +70,4 @@ def test_viewport_change_affects_frame_height(): cam = Camera(viewport=(0, 0, 800, 600), pixel_ratio=80) assert cam.frame_left == -5 cam.viewport_width = 400 - assert cam.frame_left == -2.5 \ No newline at end of file + assert cam.frame_left == -2.5 From 4da70cb96150ef0c3f886cca181f004f9cad2f21 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Tue, 23 Apr 2019 17:33:03 -0400 Subject: [PATCH 15/15] Camera: Remove specific references to PyGame from docstrings --- ppb/camera.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ppb/camera.py b/ppb/camera.py index 77d1cfae..6a9d58ee 100644 --- a/ppb/camera.py +++ b/ppb/camera.py @@ -98,7 +98,7 @@ def in_frame(self, sprite: BaseSprite) -> bool: def translate_to_frame(self, point: Vector) -> Vector: """ - Converts a vector from PyGame to in-game coordinate space + Converts a vector from pixel-based window to in-game coordinate space """ offset = (point - self.viewport_offset) * (1/self.pixel_ratio) loc = self.position + offset @@ -106,7 +106,7 @@ def translate_to_frame(self, point: Vector) -> Vector: def translate_to_viewport(self, point: Vector) -> Vector: """ - Converts a vector from in-game to PyGame coordinate space + Converts a vector from in-game to pixel-based window coordinate space """ point = point.update(y=-point.y) offset = (point - self.position) * self.pixel_ratio