Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/emilyhunt/SK8plotlib. Turn any matplotlib line chart into a line skateboarding game. 🛹 pypi.org/project/SK8plotlib
Something went wrong. Try again.
3.1 kB · 85 lines
Python
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586import numpy as npfrom .skater import Skater
class Camera: def __init__( self, fig, ax, skater: Skater, starting_scale: int = 100, scale: int = 10, velocity_zoom_response: float = 0.1, zoom_response: float = 0.025, max_camera_distance: float = 25, move_response: float = 1.5, ): self.fig, self.ax, self.skater = fig, ax, skater self.scale = starting_scale self.position = skater.position self.desired_scale = scale self.desired_position = skater.position
self.scale_response = velocity_zoom_response self.minimum_scale = scale self.maximum_scale = starting_scale self.zoom_response = zoom_response
self.max_camera_distance = max_camera_distance self.move_response = move_response
def move_camera(self): self._update_scale() self._update_position() self.ax.set( xlim=(self.position[0] - self.scale, self.position[0] + self.scale), ylim=(self.position[1] - self.scale, self.position[1] + self.scale), )
def _update_position(self): # We always aim to center on the skater, plus some velocity tolerance. We don't # let this get too big to try and stop the skater going off screen position_offset = self.skater.velocity * 0.3 position_offset_magnitude = np.linalg.norm(position_offset) if position_offset_magnitude > self.max_camera_distance: position_offset *= self.max_camera_distance / position_offset_magnitude self.desired_position = self.skater.position + position_offset
# BUT, we lag behind it. # We start by computing the difference between camera & skater difference = self.desired_position - self.position distance = np.linalg.norm(difference)
# The amount that we move the camera scales on a few things # If the distance is greater than our max distance, always move closer than that amount_to_move = distance / self.max_camera_distance
# Otherwise, we use a smooth scaling rule # if distance < self.max_camera_distance: amount_to_move = amount_to_move**self.move_response
self.position += difference * amount_to_move
def _update_scale(self): velocity = self.skater.velocity excess_velocity = np.linalg.norm(velocity) - 1 if excess_velocity > 10: self.desired_scale = np.clip( self.minimum_scale + excess_velocity * self.scale_response, self.minimum_scale, self.minimum_scale * 2.0, ) else: self.desired_scale = self.minimum_scale
scale_change = np.clip( (self.desired_scale - self.scale) * self.zoom_response, -np.inf, self.zoom_response, ) self.scale = np.clip( self.scale + scale_change, self.minimum_scale, self.maximum_scale )
self.skater.set_marker_scale(self.minimum_scale / self.scale)