def test_class_attrs(): class TestSprite(BaseSprite): position = Vector(4, 2) sprite = TestSprite() assert sprite.position == Vector(4, 2) sprite = TestSprite(position=(2, 4)) assert sprite.position == Vector(2, 4)
def __init__(self, *p, **kw): super().__init__(*p, **kw) # Set up sprites self.add(Player(position=Vector(0, 0)), tags=['player']) # 5 targets in x = -3.75 -> 3.75, with margin for x in (-3, -1.5, 0, 1.5, 3): self.add(Target(position=Vector(x, -1.875)), tags=['target'])
def __init__(self, engine, background_color=(0, 0, 0), **kwargs): super().__init__(engine=engine, background_color=background_color, **kwargs) chest = ClosedChest(self, Vector(750, 750)) player = Player(self, chest) Enemy(self, Vector(600, 600), player) self.groups["terrain"].empty() self.controller = Controller(player, self.groups["interact"])
def __init__(self, size: int = 1, pos: Iterable = (0, 0), blackboard: Dict = None, facing: Vector = Vector(0, -1)): super().__init__() self.position = Vector(*pos) self.offset_value = size / 2 self.game_unit_size = size self.facing = facing self.blackboard = blackboard or {}
class Santa(DirtySprite): limit = 50 minimum = 25 max_move = 1 min_move = 0.5 layer = Layers.SANTA.value drop_offset = Vector(0, 20) speed = Vector(-50, 0) def __init__(self, scene: Game, center_point: Vector, gift_group, *groups: LayeredDirty): # Sprite stuff super().__init__(*groups) self.image = sprites["santa"] self.image = scale(self.image, 2) self.rect = self.image.get_rect() self.rect.center = tuple(center_point) # Relationships self.scene = scene self.gift_group = gift_group # State self.anchor_point = center_point self.count_down = 0.5 self.direction = Vector(0, -1) self.dirty = 1 self.position = center_point self.throw_gift = False def activate(self): self.scene.spawner.spawn(Gift, self.scene, self.position + self.drop_offset, self.gift_group) def change_direction(self): self.direction *= -1 self.count_down = rand() * (( (self.max_move - self.min_move) + 1) + self.min_move) def pre_draw(self): pass def update(self, time_delta): self.count_down -= time_delta if self.count_down <= 0 or (self.position - self.anchor_point).length >= self.limit: self.change_direction() speed = randint(self.minimum, self.limit * 2) self.position += self.direction * speed * time_delta self.rect.center = tuple(self.position) self.dirty = 1
def test_camera_translate_to_frame(): cam = Camera(viewport=(0, 0, 800, 600), pixel_ratio=80) assert cam.position == Vector(0, 0) assert cam.frame_top == 3.75 assert cam.frame_bottom == -3.75 assert cam.frame_left == -5 assert cam.frame_right == 5 assert cam.translate_to_frame(Vector(400, 300)) == Vector(0, 0) 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, 6)
def test_bottom_left(self): self.assertEqual(self.sprite.bottom.left, Vector(-0.5, 0.5)) self.sprite.bottom.left = (2, 2) self.assertEqual(self.sprite.bottom.left, Vector(2, 2)) self.sprite.bottom.left += (2, 2) self.assertEqual(self.sprite.bottom.left, Vector(4, 4)) result = self.sprite.bottom.left + (3, 3) self.assertEqual(result, Vector(7, 7)) self.assertEqual(self.sprite.position, Vector(4.5, 3.5))
def test_bottom_right(self): self.assertEqual(self.sprite.bottom.right, Vector(0.5, 0.5)) self.sprite.bottom.right = (1, 1) self.assertEqual(self.sprite.bottom.right, Vector(1, 1)) self.sprite.bottom.right += (2, 1) self.assertEqual(self.sprite.bottom.right, Vector(3, 2)) result = self.sprite.bottom.right + (2, 3) self.assertEqual(result, Vector(5, 5)) self.assertEqual(self.sprite.position, Vector(2.5, 1.5))
def __init__(self, scene, position: Vector, player: 'Player'): super().__init__(scene.groups["interact"]) self.image = image.load(path.join(path.dirname(__file__), "enemy.png")) self.rect = self.image.get_rect() self.rect.center = tuple(position) self._position = position self.direction = Vector(0, 1).rotate(random.randint(0, 359)) self.dirty = 1 self.scene = scene self.speed = 30 self.reach = 20 self.sense_limit = 200 self.player = player
def test_right_top(self): self.assertEqual(self.sprite.right.top, Vector(0.5, 0.5)) self.sprite.right.top = (1, 1) self.assertEqual(self.sprite.right.top, Vector(1, 1)) self.sprite.right.top += (2, 1) self.assertEqual(self.sprite.right.top, Vector(3, 2)) result = self.sprite.right.top + (2, 3) self.assertEqual(result, Vector(5, 5)) self.assertEqual(self.sprite.position, Vector(2.5, 1.5))
def test_left_top(self): self.assertEqual(self.sprite.left.top, Vector(-0.5, -0.5)) self.sprite.left.top = (2, 2) self.assertEqual(self.sprite.left.top, Vector(2, 2)) self.sprite.left.top += (2, 2) self.assertEqual(self.sprite.left.top, Vector(4, 4)) result = self.sprite.left.top + (3, 3) self.assertEqual(result, Vector(7, 7)) self.assertEqual(self.sprite.position, Vector(4.5, 4.5))
def on_update(self, event, signal): player = event.scene.player if (player.position - self.position).length < .6: push_vector = Vector(0, 0) if self.point_is_in(player.bottom.left): push_vector += UP_RIGHT if self.point_is_in(player.bottom.right): push_vector += UP_LEFT if self.point_is_in(player.top.right): push_vector += DOWN_LEFT if self.point_is_in(player.top.left): push_vector += DOWN_RIGHT player.position += push_vector.normalize() * .3
def test_right_bottom(self): self.assertEqual(self.sprite.right.bottom, Vector(0.5, -0.5)) self.sprite.right.bottom = (1, 1) self.assertEqual(self.sprite.right.bottom, Vector(1, 1)) self.sprite.right.bottom += (2, 1) self.assertEqual(self.sprite.right.bottom, Vector(3, 2)) result = self.sprite.right.bottom + (2, 3) self.assertEqual(result, Vector(5, 5)) self.assertEqual(self.sprite.position, Vector(2.5, 2.5))
def test_right_center(self): self.assertEqual(self.sprite.right.center, Vector(0.5, 0)) self.sprite.right.center = (1, 1) self.assertEqual(self.sprite.right.center, Vector(1, 1)) self.sprite.right.center += (2, 1) self.assertEqual(self.sprite.right.center, Vector(3, 2)) result = self.sprite.right.center + (2, 3) self.assertEqual(result, Vector(5, 5)) self.assertEqual(self.sprite.position, Vector(2.5, 2))
def mouse_motion(self, event, scene): screen_position = Vector(*event.pos) camera = scene.main_camera scene_position = camera.translate_to_frame(screen_position) delta = Vector(*event.rel) * (1 / camera.pixel_ratio) buttons = { self.button_map[btn + 1] for btn, value in enumerate(event.buttons) if value } return events.MouseMotion(position=scene_position, screen_position=screen_position, delta=delta, buttons=buttons)
def test_top_right(self): self.assertEqual(self.sprite.top.right, Vector(0.5, -0.5)) self.sprite.top.right = (1, 1) self.assertEqual(self.sprite.top.right, Vector(1, 1)) self.sprite.top.right += (2, 1) self.assertEqual(self.sprite.top.right, Vector(3, 2)) result = self.sprite.top.right + (2, 3) self.assertEqual(result, Vector(5, 5)) self.assertEqual(self.sprite.position, Vector(2.5, 2.5))
def setup(scene): scene.add( Planet(position=(3, 0), velocity=Vector(0, 1), image=ppb.Circle(40, 200, 150))) scene.add( Planet(position=(-3, 3), velocity=Vector(1, -1), image=ppb.Circle(200, 150, 40))) scene.add( Planet(position=(-3, -3), velocity=Vector(-1, 0), image=ppb.Circle(150, 40, 200)))
def test_left_bottom(self): self.assertEqual(self.sprite.left.bottom, Vector(-0.5, 0.5)) self.sprite.left.bottom = (1, 2) self.assertEqual(self.sprite.left.bottom, Vector(1, 2)) self.sprite.left.bottom += (2, 1) self.assertEqual(self.sprite.left.bottom, Vector(3, 3)) result = self.sprite.left.bottom + (3, 2) self.assertEqual(result, Vector(6, 5)) self.assertEqual(self.sprite.position, Vector(3.5, 2.5))
class Arrow(PlayerHurtBox): image = Triangle(224, 218, 56) target = Vector(0, 4) origin = Vector(0, 0) speed = 8 size = 0.25 layer = 20 def on_update(self, event, _): self.position += (self.target - self.position).scale_to( self.speed) * event.time_delta if (self.target - self.origin).length <= (self.origin - self.position).length: event.scene.remove(self)
def test_sprite_in_viewport(): cam = Camera(viewport=(0, 0, 800, 600)) class Thing(BaseSprite): def __init__(self, position=Vector(2, 2)): super().__init__() self.game_unit_size = 2 self.position = position sprite_in = Thing(Vector(-3, -1)) sprite_half_in = Thing(Vector(5, -2)) sprite_out = Thing(Vector(2, 5)) assert not cam.in_frame(sprite_out) assert cam.in_frame(sprite_in) assert cam.in_frame(sprite_half_in)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.wander_angle = randint(0, 359) self.velocity = Vector(-1, 0).rotate(self.wander_angle).scale( self.speed * _random()) self.state = state.wander self.target = None
def translate_to_viewport(self, point: Vector) -> Vector: """ 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 return self.viewport_offset + offset
def translate_to_viewport(self, point: Vector) -> Vector: """ Converts a vector from in-game to pixel-based window coordinate space """ # 1. Reposition based on frame edges # 2. Scale from game units to pixels return Vector(point.x - self.frame_left, self.frame_top - point.y) * self.pixel_ratio
def test_target_sprite_linear(): target_sprite = TargetSprite() target_sprite.target = Vector(3, 4) target_sprite.speed = 5.0 target_sprite.on_update(ppb.events.Update(0.2), lambda x: None) assert target_sprite.position.isclose((0.6, 0.8))
class Rotatable: """ A simple rotation mixin. Can be included with sprites. """ _rotation = 0 # This is necessary to make facing do the thing while also being adjustable. basis = Vector(0, -1) # Considered making basis private, the only reason to do so is to # discourage people from relying on it as data. @property 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 @rotation.setter def rotation(self, value): self._rotation = value % 360 def rotate(self, degrees): """Rotate the sprite by a given angle (in degrees).""" self.rotation += degrees
def __init__(self, *args, next_scene=None, **kwargs): super().__init__() c = 255, 255, 255 a = RectangleSprite(image=Text( "A", font=Font("pathunstrom_splash/Comfortaa_Bold.ttf", size=64), color=c), height=2, position=Vector(0, -2), opacity=text_opacity) name = RectangleSprite(image=Text( "Piper Thunstrom", font=Font("pathunstrom_splash/Comfortaa_Bold.ttf", size=64), color=c), height=2, opacity=text_opacity) game = RectangleSprite(image=Text( "Game", font=Font("pathunstrom_splash/Comfortaa_Bold.ttf", size=64), color=c), height=2, opacity=text_opacity) icon = Sprite(image=Image("pathunstrom_splash/piper.png"), size=5) icon.bottom = a.top + 1 name.top = a.bottom game.top = name.bottom self.add(a) self.add(name) self.add(game) self.add(icon) self.start = perf_counter() self.next_scene = next_scene
def test_target_sprite_exponential(): target_sprite = TargetSprite() target_sprite.target = Vector(3, -4) target_sprite.speed = 0.0 target_sprite.exponential_speed = 0.5 target_sprite.on_update(ppb.events.Update(2.0), lambda x: None) assert target_sprite.position.isclose((2.25, -3.0))
def test_target_sprite_min_speed(): target_sprite = TargetSprite() target_sprite.target = Vector(-3, -4) target_sprite.speed = 0.0 target_sprite.min_speed = 2.0 target_sprite.on_update(ppb.events.Update(1.0), lambda x: None) assert target_sprite.position.isclose((-1.2, -1.6))
def __init__(self, **kwargs): super().__init__() self.position = Vector(self.position) # Initialize things for k, v in kwargs.items(): # Abbreviations if k == 'pos': k = 'position' # Castings if k == 'position': v = Vector(v) setattr(self, k, v) # Trigger some calculations self.size = self.size
def test_rotatable_subclass(): class TestRotatable(Rotatable): _rotation = 180 basis = Vector(0, 1) rotatable = TestRotatable() assert rotatable.rotation == 180 assert rotatable.facing == Vector(0, -1)
def on_update(self, update_event, signal): delta = Vector(self.controller.horizontal, self.controller.vertical) self.position += delta.scale(self.speed) * update_event.time_delta