-
-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
456: (WIP) TargetSprite r=pathunstrom a=serin-delaunay Class `TargetSprite` with parameters `target` and `speed`. Moves towards target at the given speed, and stops there. Will resolve #382. Co-authored-by: Serin Delaunay <serin.delaunay@gmail.com>
- Loading branch information
Showing
3 changed files
with
88 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import ppb | ||
import math | ||
|
||
|
||
class TargetSprite(ppb.Sprite): | ||
"""Sprite that moves to a given target. | ||
:param target: Vector that the sprite moves towards. | ||
:param speed: Distance per second that the sprite travels with linear motion. | ||
:param exponential_speed: Fraction of the distance to the target that the sprite travels | ||
per second with exponential motion. Should normally be in the range [0.0, 1.0]. | ||
:param max_speed: Maximum distance per second that the sprite can travel. | ||
:param min_speed: Minimum distance per second that the sprite travels when not in range of the target. | ||
""" | ||
target = ppb.Vector(0, 0) | ||
speed = 1.0 | ||
exponential_speed = 0.0 | ||
max_speed = math.inf | ||
min_speed = -math.inf | ||
|
||
def on_update(self, update_event, signal): | ||
if self.max_speed < self.min_speed: | ||
raise ValueError("TargetSprite maximum speed cannot be less than minimum speed.") | ||
offset = self.target - self.position | ||
distance_to_target = offset.length | ||
max_distance = self.max_speed * update_event.time_delta | ||
min_distance = self.min_speed * update_event.time_delta | ||
linear_distance = self.speed * update_event.time_delta | ||
exponential_distance = distance_to_target * self._exponential_decay(update_event.time_delta) | ||
total_distance = linear_distance + exponential_distance | ||
total_distance = min(total_distance, max_distance) | ||
total_distance = max(total_distance, min_distance) | ||
if distance_to_target <= total_distance: | ||
self.position = self.target | ||
else: | ||
direction = offset.normalize() | ||
self.position += direction * total_distance | ||
|
||
def _exponential_decay(self, time_delta): | ||
decay_rate = 1. - self.exponential_speed | ||
remaining = decay_rate ** time_delta | ||
decay_amount = 1. - remaining | ||
return decay_amount |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import unittest | ||
import ppb | ||
from ppb import Vector | ||
from ppb.features.default_sprites import TargetSprite | ||
|
||
|
||
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)) | ||
|
||
|
||
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_max_speed(): | ||
target_sprite = TargetSprite() | ||
target_sprite.target = Vector(-3, 4) | ||
target_sprite.speed = 500. | ||
target_sprite.exponential_speed = 0.99 | ||
target_sprite.max_speed = 1.0 | ||
target_sprite.on_update(ppb.events.Update(2.0), lambda x: None) | ||
|
||
assert target_sprite.position.isclose((-1.2, 1.6)) | ||
|
||
|
||
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)) |