Got animated sprites working, but its mirrored.
This commit is contained in:
parent
8a40f24d65
commit
e7daca1d8c
7 changed files with 131 additions and 17 deletions
BIN
assets/stacked_sprites/animated/bla/0.png
Normal file
BIN
assets/stacked_sprites/animated/bla/0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 168 B |
BIN
assets/stacked_sprites/animated/bla/1.png
Normal file
BIN
assets/stacked_sprites/animated/bla/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 121 B |
BIN
assets/stacked_sprites/animated/bla/2.png
Normal file
BIN
assets/stacked_sprites/animated/bla/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 179 B |
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
import pygame.draw
|
||||
|
||||
import os
|
||||
from settings import *
|
||||
|
||||
|
||||
|
@ -21,6 +21,15 @@ class Cache:
|
|||
layer_array = self.get_layer_array(attrs)
|
||||
self.run_prerender(object_name, layer_array, attrs)
|
||||
|
||||
for object_name in ANIMATED_SPRITE_ATTRS:
|
||||
self.stacked_sprite_cache[object_name] = {
|
||||
"frames": {}
|
||||
}
|
||||
|
||||
attrs = ANIMATED_SPRITE_ATTRS[object_name]
|
||||
frames = self.get_frame_dict(attrs)
|
||||
self.run_animation_prerender(object_name, frames, attrs)
|
||||
|
||||
def run_prerender(self, object_name, layer_array, attrs):
|
||||
outline = attrs.get("outline", True)
|
||||
|
||||
|
@ -29,7 +38,7 @@ class Cache:
|
|||
surface = pygame.transform.rotate(surface, angle * self.viewing_angle)
|
||||
sprite_surface = pygame.Surface([
|
||||
surface.get_width(),
|
||||
surface.get_height() + attrs["num_layers"] * attrs["scale"]
|
||||
surface.get_height() + attrs["layers"] * attrs["scale"]
|
||||
])
|
||||
|
||||
sprite_surface.fill(TRANSP_COLOR)
|
||||
|
@ -47,15 +56,51 @@ class Cache:
|
|||
image = pygame.transform.flip(sprite_surface, True, True)
|
||||
self.stacked_sprite_cache[object_name]["rotated_sprites"][angle] = image
|
||||
|
||||
def get_layer_array(self, attrs):
|
||||
def run_animation_prerender(self, object_name, frames, attrs):
|
||||
outline = attrs.get("outline", True)
|
||||
|
||||
for angle in range(NUM_ANGLES):
|
||||
surface = pygame.Surface(list(frames.items())[0][1][0].get_size())
|
||||
surface = pygame.transform.rotate(surface, angle * self.viewing_angle)
|
||||
surface_default = pygame.Surface([
|
||||
surface.get_width(),
|
||||
surface.get_height() + attrs["layers"] * attrs["scale"]
|
||||
])
|
||||
|
||||
for frame_name, layer_array in frames.items():
|
||||
sprite_surface = surface_default
|
||||
|
||||
sprite_surface.fill(TRANSP_COLOR)
|
||||
sprite_surface.set_colorkey(TRANSP_COLOR)
|
||||
|
||||
for i, layer in enumerate(layer_array):
|
||||
layer = pygame.transform.rotate(layer, angle * self.viewing_angle)
|
||||
sprite_surface.blit(layer, (0, i * attrs["scale"]))
|
||||
|
||||
# get outline
|
||||
if outline:
|
||||
outline_coords = pygame.mask.from_surface(sprite_surface).outline()
|
||||
pygame.draw.polygon(sprite_surface, "black", outline_coords, self.outline_thickness)
|
||||
|
||||
image = pygame.transform.flip(sprite_surface, True, True)
|
||||
|
||||
if not frame_name in self.stacked_sprite_cache[object_name]["frames"]:
|
||||
self.stacked_sprite_cache[object_name]["frames"][frame_name] = {"rotated_sprites": {}}
|
||||
|
||||
self.stacked_sprite_cache[object_name]["frames"][frame_name]["rotated_sprites"][angle] = image
|
||||
|
||||
def get_layer_array(self, attrs, path=None):
|
||||
if not path is None:
|
||||
attrs["path"] = path
|
||||
|
||||
# load sprite sheet
|
||||
sprite_sheet = pygame.image.load(attrs["path"]).convert_alpha()
|
||||
# scaling
|
||||
sprite_sheet = pygame.transform.scale(sprite_sheet, vec2(sprite_sheet.get_size()) * attrs["scale"])
|
||||
sheet_width, sheet_height = sprite_sheet.get_size()
|
||||
sprite_width = sheet_width // attrs["num_layers"]
|
||||
sprite_width = sheet_width // attrs["layers"]
|
||||
# new width to prevent error
|
||||
sheet_width = sprite_width * attrs["num_layers"]
|
||||
sheet_width = sprite_width * attrs["layers"]
|
||||
|
||||
# get sprites
|
||||
layer_array = []
|
||||
|
@ -64,3 +109,14 @@ class Cache:
|
|||
layer_array.append(sprite)
|
||||
|
||||
return layer_array
|
||||
|
||||
def get_frame_dict(self, attrs):
|
||||
frames = {}
|
||||
|
||||
for path, folders, files in os.walk(attrs["path"]): # loop through all frames and add them to the sheet list
|
||||
for file in files:
|
||||
# use the name of the file without the file format specifier (the part before the dot) as the frame name
|
||||
# and store the layer array
|
||||
frames[file.split(".")[0]] = self.get_layer_array(attrs, f"{path}/{file}")
|
||||
|
||||
return frames
|
||||
|
|
|
@ -4,7 +4,7 @@ from stacked_sprite import *
|
|||
from random import uniform
|
||||
|
||||
P = "player"
|
||||
A, B = "Robot", "Building"
|
||||
A, B, C = "Robot", "Building", "Bla"
|
||||
|
||||
MAP = [
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
|
@ -13,7 +13,7 @@ MAP = [
|
|||
[0, 0, A, A, 0, B, B, B, B],
|
||||
[0, 0, A, A, P, B, B, B, B],
|
||||
[0, 0, A, A, 0, B, B, B, B],
|
||||
[0, 0, 0, 0, 0, B, B, B, B],
|
||||
[0, 0, 0, 0, C, B, B, B, B],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
]
|
||||
|
@ -39,4 +39,8 @@ class Scene:
|
|||
self.app.player.offset = pos * TILE_SIZE
|
||||
|
||||
elif name:
|
||||
StackedSprite(self.app, name=name, pos=rand_pos(pos), rot=rand_rot())
|
||||
if name == "Bla":
|
||||
AnimatedStackedSprite(self.app, name=name, pos=rand_pos(pos), rot=rand_rot())
|
||||
|
||||
else:
|
||||
StackedSprite(self.app, name=name, pos=rand_pos(pos), rot=rand_rot())
|
||||
|
|
|
@ -18,14 +18,20 @@ TRANSP_COLOR = (43, 64, 36)
|
|||
SPRITE_ATTRS = {
|
||||
"Robot": {
|
||||
"path": "../assets/stacked_sprites/Robot.png",
|
||||
"num_layers": 16,
|
||||
"scale": 8,
|
||||
"y_offset": -8
|
||||
"layers": 16,
|
||||
"scale": 8
|
||||
},
|
||||
"Building": {
|
||||
"path": "../assets/stacked_sprites/Building.png",
|
||||
"num_layers": 80,
|
||||
"scale": 4,
|
||||
"y_offset": -40
|
||||
"layers": 80,
|
||||
"scale": 4
|
||||
}
|
||||
}
|
||||
|
||||
ANIMATED_SPRITE_ATTRS = {
|
||||
"Bla": {
|
||||
"path": "../assets/stacked_sprites/animated/bla/",
|
||||
"layers": 3,
|
||||
"scale": 16
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ import pygame
|
|||
|
||||
from settings import *
|
||||
import math
|
||||
from wobbl_tools import pg
|
||||
|
||||
|
||||
class StackedSprite(pygame.sprite.Sprite):
|
||||
|
@ -16,7 +15,7 @@ class StackedSprite(pygame.sprite.Sprite):
|
|||
super().__init__(self.group)
|
||||
|
||||
self.attrs = SPRITE_ATTRS[name]
|
||||
self.y_offset = vec2(0, -self.attrs["num_layers"] / 2 * self.attrs["scale"])
|
||||
self.y_offset = vec2(0, -self.attrs["layers"] / 2 * self.attrs["scale"])
|
||||
self.cache = self.app.cache.stacked_sprite_cache
|
||||
self.viewing_angle = app.cache.viewing_angle
|
||||
self.rotated_sprites = self.cache[name]["rotated_sprites"]
|
||||
|
@ -45,3 +44,52 @@ class StackedSprite(pygame.sprite.Sprite):
|
|||
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):
|
||||
def __init__(self, app, name, pos, rot=0):
|
||||
self.app = app
|
||||
self.name = name
|
||||
self.pos = vec2(pos) * TILE_SIZE
|
||||
self.player = self.app.player
|
||||
self.group = self.app.main_group
|
||||
super().__init__(self.group)
|
||||
|
||||
self.attrs = ANIMATED_SPRITE_ATTRS[name]
|
||||
self.attrs["animated"] = True
|
||||
self.y_offset = vec2(0, -self.attrs["layers"] / 2 * self.attrs["scale"])
|
||||
self.cache = self.app.cache.stacked_sprite_cache
|
||||
self.viewing_angle = app.cache.viewing_angle
|
||||
self.frame = list(self.cache[name]["frames"].keys())[0]
|
||||
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):
|
||||
self.frame = str(round(self.app.time) * 4 % 3)
|
||||
print(self.frame)
|
||||
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()
|
||||
|
|
Loading…
Reference in a new issue