import pygame import sys from sprite.BoundingBox import BoundingBox from sprite.PositionScale import PositionScale from sprite.Spritesheet import Spritesheet sys.path.append('./sprite') class Sprite: def __init__(self, spritesheet: Spritesheet): self.spritesheet = spritesheet self.animation_state = list(self.spritesheet.animations.keys())[0] self.animation_frame = 0 self.animation_delay = 0 self.position_scale = PositionScale() self.visible = True self.animated = True self.image = None self.is_collider = True def tick(self, dt: float): animation = self.spritesheet.animations[self.animation_state] if self.animated: self.animation_delay += dt while self.animation_delay >= animation['delays'][self.animation_frame % len(animation['delays'])]: self.animation_delay -= animation['delays'][self.animation_frame % len(animation['delays'])] self.animation_frame = (self.animation_frame + 1) % len(animation['images']) self.image = animation['images'][self.animation_frame % len(animation['images'])] def set_animation_state(self, state: str): if state in self.spritesheet.animations: self.animation_state = state self.animation_delay = 0 self.tick(0) def set_animation_frame(self, frame: int): self.animation_frame = frame self.tick(0) def draw(self, screen: pygame.Surface, screen_transform: PositionScale): if not self.visible: return if self.image is not None: target_scale = (screen_transform.scale[0] * self.position_scale.scale[0], screen_transform.scale[1] * self.position_scale.scale[1]) target_position = ((self.position_scale.position[0] + screen_transform.position[0]) * target_scale[0], (self.position_scale.position[1] + screen_transform.position[1]) * target_scale[1]) target_size = (int(target_scale[0] * self.image.get_width()), int(target_scale[1] * self.image.get_height())) target_image = self.get_scaled_image(self.image, target_size) screen.blit(target_image, target_position) def get_bounding_box(self) -> BoundingBox: return BoundingBox( self.position_scale.position[0], self.position_scale.position[1], self.image.get_width() * self.position_scale.scale[0], self.image.get_height() * self.position_scale.scale[1] ) def get_scaled_image(self, image, resize): return pygame.transform.scale(image, resize) def dump(self, file): # re-attach all the images to a single surface and save it to a file width = 0 height = 0 for animation in self.spritesheet.animations.values(): max_height = 0 total_width = 0 for image in animation['images']: total_width += image.get_width() max_height = max(max_height, image.get_height()) width = max(width, total_width) height += max_height sheet = pygame.Surface((width, height)) x = 0 y = 0 for animation in self.spritesheet.animations.values(): max_height = 0 for image in animation['images']: sheet.blit(image, (x, y)) x += image.get_width() max_height = max(max_height, image.get_height()) y += max_height x = 0 pygame.image.save(sheet, file)