81 lines
2.8 KiB
Python

import json
import pygame
from pygame import transform, gfxdraw, Vector2, Surface
from math import sin, cos, pi
from time import time, sleep
from random import random
class Star:
def __init__(self, sid: str, x: int, y: int, alpha: float, rot: float, scale: float, offset: float, image: pygame.Surface):
self.sid = sid
self.x = x
self.y = y
self.rot = rot
self.alpha = alpha
self.scale = scale
self.offset = offset
self.image = image
class Screen:
def __init__(self, stars: list[Star], background: Surface | None) -> None:
if not pygame.get_init():
pygame.init()
self.screen = pygame.display.set_mode((1920, 1080))
self.clock = pygame.time.Clock()
self.stars = stars
self.last = time()
self.brightness = 1.0
self.active_scene = 0
self.last_scene = 0
self.scene_time: float = 0
self.background = background
def update(self, scene_data):
self.screen.fill((0, 0, 0))
now = time()
delta = now - self.last
self.last = now
self.scene_time += delta
weight = sin(min(self.scene_time, pi/2)) ** 2
def update_star_scene(star, old, new, weight):
star.x = weight*new[star.sid]['x'] + (1-weight)*old[star.sid]['x']
star.y = weight*new[star.sid]['y'] + (1-weight)*old[star.sid]['y']
star.rot = weight*new[star.sid]['rot'] + (1-weight)*old[star.sid]['rot']
star.scale = weight*new[star.sid]['scale'] + (1-weight)*old[star.sid]['scale']
# first draw the background, if any
if self.background:
ratio_x = self.screen.get_width() / self.background.get_width()
ratio_y = self.screen.get_height() / self.background.get_height()
scaled_background = transform.rotozoom(self.background, 0, max(ratio_x, ratio_y))
bg_pos = (
(self.screen.get_width() - scaled_background.get_width()) / 2,
(self.screen.get_height() - scaled_background.get_height()) / 2
)
self.screen.blit(scaled_background, bg_pos)
# draw all the star objects
for star in self.stars:
update_star_scene(star, scene_data[self.last_scene], scene_data[self.active_scene], weight)
star.alpha += star.rot * delta
scaled = transform.rotozoom(star.image, star.alpha, star.scale)
(w, h) = scaled.get_size()
pos = (star.x*self.screen.get_width() - w/2, star.y*self.screen.get_height() - h/2)
self.screen.blit(scaled, pos)
overlay = pygame.surface.Surface((1920, 1080), depth=32)
overlay.set_alpha(int(255 * (1 - self.brightness)))
self.screen.blit(overlay, (0, 0))
pygame.display.flip()
self.clock.tick(60)
def close(self):
pygame.quit()