-
Notifications
You must be signed in to change notification settings - Fork 222
Control Screensaver Animation Speed Acroos Different Hardware & Emulator #733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -96,7 +96,7 @@ def _render(self): | |
# Display version num below SeedSigner logo | ||
font = Fonts.get_font(GUIConstants.get_body_font_name(), GUIConstants.get_top_nav_title_font_size()) | ||
version = f"v{controller.VERSION}" | ||
|
||
# The logo png is 240x240, but the actual logo is 70px tall, vertically centered | ||
logo_height = 70 | ||
version_x = int(self.renderer.canvas_width/2) | ||
|
@@ -150,28 +150,39 @@ def __init__(self, buttons): | |
|
||
self.min_coords = (0, 0) | ||
self.max_coords = (self.logo.size[0], self.logo.size[1]) | ||
|
||
self.increment_x = self.rand_increment() | ||
self.increment_y = self.rand_increment() | ||
|
||
# Movement vector components - includes both direction and magnitude | ||
self.vector_x = self.rand_direction() | ||
self.vector_y = self.rand_direction() | ||
|
||
self.cur_x = int(self.logo.size[0] / 2) | ||
self.cur_y = int(self.logo.size[1] / 2) | ||
|
||
self._is_running = False | ||
self.last_screen = None | ||
|
||
# Calculate min/max speed based on minimum screen dimension | ||
min_screen_dimension = min(self.renderer.canvas_width, self.renderer.canvas_height) | ||
# Min speed: cross the screen in 3 seconds, max: cross in 1 second | ||
self.min_speed = min_screen_dimension / 3.0 # pixels per second | ||
self.max_speed = min_screen_dimension / 1.0 # pixels per second | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my testing, min / max speeds worked best if it took 1.5s - 10s to cross the screen in any one dimension. But note that because of your
|
||
|
||
|
||
@property | ||
def is_running(self): | ||
return self._is_running | ||
|
||
def rand_speed(self): | ||
"""Returns a random speed in pixels per second between min_speed and max_speed""" | ||
return random.uniform(self.min_speed, self.max_speed) | ||
|
||
|
||
|
||
def rand_direction(self): | ||
"""Returns a random direction component between -1.0 and 1.0""" | ||
return random.uniform(-1.0, 1.0) | ||
|
||
|
||
def rand_increment(self): | ||
max_increment = 10.0 | ||
min_increment = 1.0 | ||
increment = random.uniform(min_increment, max_increment) | ||
if random.uniform(-1.0, 1.0) < 0.0: | ||
return -1.0 * increment | ||
return increment | ||
|
||
|
||
def start(self): | ||
|
@@ -183,47 +194,76 @@ def start(self): | |
# Store the current screen in order to restore it later | ||
self.last_screen = self.renderer.canvas.copy() | ||
|
||
screensaver_start = int(time.time() * 1000) | ||
# Accumulate sub-pixel movements to avoid getting stuck at zero | ||
accumulated_x = 0 | ||
accumulated_y = 0 | ||
|
||
# Screensaver must block any attempts to use the Renderer in another thread so it | ||
# never gives up the lock until it returns. | ||
with self.renderer.lock: | ||
try: | ||
last_update_time = time.time() | ||
current_speed = self.rand_speed() | ||
|
||
while self._is_running: | ||
if self.buttons.has_any_input() or self.buttons.override_ind: | ||
break | ||
|
||
current_time = time.time() | ||
elapsed_time = current_time - last_update_time | ||
|
||
# Calculate pixel movement based on elapsed time and target speed | ||
# Accumulate fractional movements to avoid getting stuck at zero | ||
accumulated_x += elapsed_time * current_speed * self.vector_x | ||
accumulated_y += elapsed_time * current_speed * self.vector_y | ||
|
||
# Only move when we've accumulated at least 1 pixel of movement | ||
pixels_to_move_x = int(accumulated_x) | ||
pixels_to_move_y = int(accumulated_y) | ||
|
||
# Remove the used whole pixels from accumulator | ||
accumulated_x -= pixels_to_move_x | ||
accumulated_y -= pixels_to_move_y | ||
|
||
# Apply movement | ||
if pixels_to_move_x != 0 or pixels_to_move_y != 0: | ||
self.cur_x += pixels_to_move_x | ||
self.cur_y += pixels_to_move_y | ||
|
||
# Must crop the image to the exact display size | ||
crop = self.image.crop(( | ||
self.cur_x, self.cur_y, | ||
self.cur_x + self.renderer.canvas_width, self.cur_y + self.renderer.canvas_height)) | ||
self.renderer.disp.ShowImage(crop, 0, 0) | ||
|
||
self.cur_x += self.increment_x | ||
self.cur_y += self.increment_y | ||
|
||
# At each edge bump, calculate a new random rate of change for that axis | ||
if self.cur_x < self.min_coords[0]: | ||
self.cur_x = self.min_coords[0] | ||
self.increment_x = self.rand_increment() | ||
if self.increment_x < 0.0: | ||
self.increment_x *= -1.0 | ||
elif self.cur_x > self.max_coords[0]: | ||
self.cur_x = self.max_coords[0] | ||
self.increment_x = self.rand_increment() | ||
if self.increment_x > 0.0: | ||
self.increment_x *= -1.0 | ||
|
||
if self.cur_y < self.min_coords[1]: | ||
self.cur_y = self.min_coords[1] | ||
self.increment_y = self.rand_increment() | ||
if self.increment_y < 0.0: | ||
self.increment_y *= -1.0 | ||
elif self.cur_y > self.max_coords[1]: | ||
self.cur_y = self.max_coords[1] | ||
self.increment_y = self.rand_increment() | ||
if self.increment_y > 0.0: | ||
self.increment_y *= -1.0 | ||
# Handle boundary collisions and ensure we don't get stuck | ||
if self.cur_x <= self.min_coords[0]: | ||
self.cur_x = self.min_coords[0] + 1 # Move slightly away from edge | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to worry about 1 pixel differences. The logo bounce is calculated from the center of the logo; there aren't any extreme edge scenarios to worry about. |
||
self.vector_x = abs(self.rand_direction()) # Force positive | ||
current_speed = self.rand_speed() | ||
# Clear accumulator when changing direction | ||
accumulated_x = 0 | ||
elif self.cur_x >= self.max_coords[0]: | ||
self.cur_x = self.max_coords[0] - 1 # Move slightly away from edge | ||
self.vector_x = -abs(self.rand_direction()) # Force negative | ||
current_speed = self.rand_speed() | ||
accumulated_x = 0 | ||
|
||
if self.cur_y <= self.min_coords[1]: | ||
self.cur_y = self.min_coords[1] + 1 # Move slightly away from edge | ||
self.vector_y = abs(self.rand_direction()) # Force positive | ||
current_speed = self.rand_speed() | ||
accumulated_y = 0 | ||
elif self.cur_y >= self.max_coords[1]: | ||
self.cur_y = self.max_coords[1] - 1 # Move slightly away from edge | ||
self.vector_y = -abs(self.rand_direction()) # Force negative | ||
current_speed = self.rand_speed() | ||
accumulated_y = 0 | ||
|
||
last_update_time = current_time | ||
|
||
# Small sleep to prevent 100% CPU usage on faster hardware | ||
time.sleep(0.001) | ||
|
||
except KeyboardInterrupt as e: | ||
# Exit triggered; close gracefully | ||
|
@@ -239,8 +279,11 @@ def start(self): | |
self.renderer.show_image(self.last_screen) | ||
|
||
|
||
|
||
def stop(self): | ||
""" | ||
Stops the screensaver animation cleanly. | ||
""" | ||
logger.info("Stopping screensaver") | ||
self._is_running = False | ||
|
||
|
This comment was marked as resolved.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.