105 lines
4 KiB
Python
105 lines
4 KiB
Python
#!/usr/bin/python3
|
|
import pygame
|
|
|
|
from sprite_stacking_engine.settings import *
|
|
import math
|
|
|
|
|
|
class StackedSprite(pygame.sprite.Sprite):
|
|
def __init__(self, engine, name, pos, rot=0):
|
|
self.engine = engine
|
|
self.app = engine.app
|
|
self.name = name
|
|
self.pos = vec2(pos) * TILE_SIZE
|
|
self.player = engine.player
|
|
self.group = engine.main_group
|
|
super().__init__(self.group)
|
|
|
|
self.attrs = SPRITE_ATTRS[name] # get attributes
|
|
|
|
if not "scale" in self.attrs:
|
|
self.attrs["scale"] = DEFAULT_SCALE
|
|
|
|
self.y_offset = vec2(0, -self.attrs["layers"] / 2 * self.attrs["scale"]) # calculate the y offset because the -
|
|
# images position in pygame is the position of the top left corner of the image and we use the bottom position
|
|
self.cache = engine.cache.stacked_sprite_cache
|
|
self.viewing_angle = engine.cache.viewing_angle
|
|
self.rotated_sprites = self.cache[name]["rotated_sprites"]
|
|
self.angle = 0
|
|
self.screen_position = vec2(0)
|
|
self.rot = (rot % 360) // self.viewing_angle
|
|
|
|
def transform(self): # recalculate position and rotation
|
|
pos = self.pos - self.player.offset
|
|
pos = pos.rotate_rad(self.player.angle)
|
|
self.screen_position = pos + CENTER
|
|
|
|
def change_layer(self): # calculate the layer to draw over the things behind it and not the other way
|
|
self.group.change_layer(self, self.screen_position.y)
|
|
|
|
def get_angle(self): # calculate the angle to draw the right sprite
|
|
self.angle = -math.degrees(self.player.angle) // self.viewing_angle + self.rot
|
|
self.angle = int(self.angle % NUM_ANGLES)
|
|
|
|
def update(self):
|
|
self.transform()
|
|
self.get_angle()
|
|
self.get_image()
|
|
self.change_layer()
|
|
|
|
def get_image(self):
|
|
self.image = self.rotated_sprites[self.angle]
|
|
self.rect = self.image.get_rect(center=self.screen_position + self.y_offset)
|
|
|
|
|
|
class AnimatedStackedSprite(pygame.sprite.Sprite): # stacked sprite class for animated sprites, works nearly the same
|
|
def __init__(self, engine, name, pos, rot=0):
|
|
self.engine = engine
|
|
self.app = engine.app
|
|
self.name = name
|
|
self.pos = vec2(pos) * TILE_SIZE
|
|
self.player = engine.player
|
|
self.group = engine.main_group
|
|
super().__init__(self.group)
|
|
|
|
self.attrs = ANIMATED_SPRITE_ATTRS[name]
|
|
|
|
if not "scale" in self.attrs:
|
|
self.attrs["scale"] = DEFAULT_SCALE
|
|
|
|
self.attrs["animated"] = True # set the animated attribute to true so that the cache knows that this sprite -
|
|
self.y_offset = vec2(0, -self.attrs["layers"] / 2 * self.attrs["scale"]) # is animated
|
|
self.cache = engine.cache.stacked_sprite_cache
|
|
self.viewing_angle = engine.cache.viewing_angle
|
|
self.frame = list(self.cache[name]["frames"].keys())[0] # set the frame to the first frame
|
|
self.rotated_sprites = self.cache[name]["frames"][self.frame]["rotated_sprites"]
|
|
self.angle = 0
|
|
self.screen_position = vec2(0)
|
|
self.rot = (rot % 360) // self.viewing_angle
|
|
|
|
def transform(self):
|
|
pos = self.pos - self.player.offset
|
|
pos = pos.rotate_rad(self.player.angle)
|
|
self.screen_position = pos + CENTER
|
|
|
|
def change_layer(self):
|
|
self.group.change_layer(self, self.screen_position.y)
|
|
|
|
def get_angle(self):
|
|
self.angle = -math.degrees(self.player.angle) // self.viewing_angle + self.rot
|
|
self.angle = int(self.angle % NUM_ANGLES)
|
|
|
|
def animate(self): # change the layer to display another frame
|
|
self.frame = str(round(self.app.time) * 4 % 3)
|
|
self.rotated_sprites = self.cache[self.name]["frames"][self.frame]["rotated_sprites"]
|
|
|
|
def get_image(self):
|
|
self.image = self.rotated_sprites[self.angle]
|
|
self.rect = self.image.get_rect(center=self.screen_position + self.y_offset)
|
|
|
|
def update(self):
|
|
self.transform()
|
|
self.get_angle()
|
|
self.animate()
|
|
self.get_image()
|
|
self.change_layer()
|