Added more comments.
This commit is contained in:
parent
4ffac24c2b
commit
98f6f9fa7e
4 changed files with 51 additions and 44 deletions
|
@ -13,17 +13,17 @@ class Cache:
|
||||||
self.get_stacked_sprite_cache()
|
self.get_stacked_sprite_cache()
|
||||||
|
|
||||||
def get_stacked_sprite_cache(self):
|
def get_stacked_sprite_cache(self):
|
||||||
for object_name in SPRITE_ATTRS:
|
for object_name in SPRITE_ATTRS: # loop through static sprites and create a dict with a dict inside for the -
|
||||||
self.stacked_sprite_cache[object_name] = {
|
self.stacked_sprite_cache[object_name] = { # stacked sprites of each rotation
|
||||||
"rotated_sprites": {}
|
"rotated_sprites": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs = SPRITE_ATTRS[object_name]
|
attrs = SPRITE_ATTRS[object_name]
|
||||||
layer_array = self.get_layer_array(attrs)
|
layer_array = self.get_layer_array(attrs) # get a list of all sprites
|
||||||
self.run_prerender(object_name, layer_array, attrs)
|
self.run_prerender(object_name, layer_array, attrs) # render the sprites into one 3d looking sprite
|
||||||
|
|
||||||
for object_name in ANIMATED_SPRITE_ATTRS:
|
for object_name in ANIMATED_SPRITE_ATTRS: # loop through all animated sprites and do the same as in the first -
|
||||||
self.stacked_sprite_cache[object_name] = {
|
self.stacked_sprite_cache[object_name] = { # loop but for every frame
|
||||||
"frames": {}
|
"frames": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,50 +31,53 @@ class Cache:
|
||||||
frames = self.get_frame_dict(attrs)
|
frames = self.get_frame_dict(attrs)
|
||||||
self.run_animation_prerender(object_name, frames, attrs)
|
self.run_animation_prerender(object_name, frames, attrs)
|
||||||
|
|
||||||
def run_prerender(self, object_name, layer_array, attrs):
|
def run_prerender(self, object_name, layer_array, attrs): # prerender static sprite
|
||||||
outline = attrs.get("outline", OUTLINE)
|
outline = attrs.get("outline", OUTLINE) # load the outline attribute of the sprite or use the default if the -
|
||||||
|
# attribute does not exist
|
||||||
|
|
||||||
for angle in range(NUM_ANGLES):
|
for angle in range(NUM_ANGLES): # prerender each angle
|
||||||
surface = pygame.Surface(layer_array[0].get_size())
|
surface = pygame.Surface(layer_array[0].get_size()) # this code lump calculates the size of the sprite -
|
||||||
surface = pygame.transform.rotate(surface, angle * self.viewing_angle)
|
surface = pygame.transform.rotate(surface, angle * self.viewing_angle) # surface and creates it
|
||||||
sprite_surface = pygame.Surface([
|
sprite_surface = pygame.Surface([
|
||||||
surface.get_width(),
|
surface.get_width(),
|
||||||
surface.get_height() + attrs["layers"] * attrs["scale"]
|
surface.get_height() + attrs["layers"] * attrs["scale"]
|
||||||
])
|
])
|
||||||
|
|
||||||
sprite_surface.fill(TRANSP_COLOR)
|
sprite_surface.fill(TRANSP_COLOR) # make just one color transparent to save the alpha channel and RAM usage
|
||||||
sprite_surface.set_colorkey(TRANSP_COLOR)
|
sprite_surface.set_colorkey(TRANSP_COLOR)
|
||||||
|
|
||||||
for i, layer in enumerate(layer_array):
|
for i, layer in enumerate(layer_array): # blit each layer onto the sprite surface
|
||||||
layer = pygame.transform.rotate(layer, angle * self.viewing_angle)
|
layer = pygame.transform.rotate(layer, angle * self.viewing_angle)
|
||||||
sprite_surface.blit(layer, (0, i * attrs["scale"]))
|
sprite_surface.blit(layer, (0, i * attrs["scale"]))
|
||||||
|
|
||||||
# get outline
|
# get outline
|
||||||
if outline:
|
if outline:
|
||||||
outline_coords = pygame.mask.from_surface(sprite_surface).outline()
|
outline_coords = pygame.mask.from_surface(sprite_surface).outline() # get the coordinates of the -
|
||||||
pygame.draw.polygon(sprite_surface, "black", outline_coords, self.outline_thickness)
|
# outline
|
||||||
|
pygame.draw.polygon(sprite_surface, "black", outline_coords, self.outline_thickness) # draw the -
|
||||||
|
# outline
|
||||||
|
|
||||||
image = pygame.transform.flip(sprite_surface, True, True)
|
image = pygame.transform.flip(sprite_surface, True, True) # mirror the image
|
||||||
self.stacked_sprite_cache[object_name]["rotated_sprites"][angle] = image
|
self.stacked_sprite_cache[object_name]["rotated_sprites"][angle] = image # add the surface to the cache
|
||||||
|
|
||||||
def run_animation_prerender(self, object_name, frames, attrs):
|
def run_animation_prerender(self, object_name, frames, attrs): # does the same as the run_prerender function but -
|
||||||
outline = attrs.get("outline", OUTLINE)
|
outline = attrs.get("outline", OUTLINE) # for every frame of the animated sprite
|
||||||
|
|
||||||
for angle in range(NUM_ANGLES):
|
for angle in range(NUM_ANGLES):
|
||||||
surface = pygame.Surface(list(frames.items())[0][1][0].get_size())
|
surface = pygame.Surface(list(frames.items())[0][1][0].get_size()) # empty sprite surface gets generated -
|
||||||
surface = pygame.transform.rotate(surface, angle * self.viewing_angle)
|
surface = pygame.transform.rotate(surface, angle * self.viewing_angle) # here as a default to improve -
|
||||||
surface_default = pygame.Surface([
|
surface_default = pygame.Surface([ # start time
|
||||||
surface.get_width(),
|
surface.get_width(),
|
||||||
surface.get_height() + attrs["layers"] * attrs["scale"]
|
surface.get_height() + attrs["layers"] * attrs["scale"]
|
||||||
])
|
])
|
||||||
|
|
||||||
for frame_name, layer_array in frames.items():
|
for frame_name, layer_array in frames.items(): # render all frames
|
||||||
sprite_surface = surface_default
|
sprite_surface = surface_default
|
||||||
|
|
||||||
sprite_surface.fill(TRANSP_COLOR)
|
sprite_surface.fill(TRANSP_COLOR)
|
||||||
sprite_surface.set_colorkey(TRANSP_COLOR)
|
sprite_surface.set_colorkey(TRANSP_COLOR)
|
||||||
|
|
||||||
for i, layer in enumerate(layer_array):
|
for i, layer in enumerate(layer_array): # blit each layer to the sprite surface
|
||||||
layer = pygame.transform.rotate(layer, angle * self.viewing_angle)
|
layer = pygame.transform.rotate(layer, angle * self.viewing_angle)
|
||||||
sprite_surface.blit(layer, (0, i * attrs["scale"]))
|
sprite_surface.blit(layer, (0, i * attrs["scale"]))
|
||||||
|
|
||||||
|
@ -85,14 +88,16 @@ class Cache:
|
||||||
|
|
||||||
image = pygame.transform.flip(sprite_surface, True, True)
|
image = pygame.transform.flip(sprite_surface, True, True)
|
||||||
|
|
||||||
if not frame_name in self.stacked_sprite_cache[object_name]["frames"]:
|
if not frame_name in self.stacked_sprite_cache[object_name]["frames"]: # add the frame's subdict with -
|
||||||
|
# the rotated sprites cache
|
||||||
self.stacked_sprite_cache[object_name]["frames"][frame_name] = {"rotated_sprites": {}}
|
self.stacked_sprite_cache[object_name]["frames"][frame_name] = {"rotated_sprites": {}}
|
||||||
|
|
||||||
|
# save the frame's sprite
|
||||||
self.stacked_sprite_cache[object_name]["frames"][frame_name]["rotated_sprites"][angle] = image
|
self.stacked_sprite_cache[object_name]["frames"][frame_name]["rotated_sprites"][angle] = image
|
||||||
|
|
||||||
def get_layer_array(self, attrs, path=None):
|
def get_layer_array(self, attrs, path=None):
|
||||||
if not path is None:
|
if not path is None: # use path parameter if it is an animated sprite because animated sprites have a path to -
|
||||||
attrs["path"] = path
|
attrs["path"] = path # a folder instead of a path to just one image file as attribute
|
||||||
|
|
||||||
# load sprite sheet
|
# load sprite sheet
|
||||||
sprite_sheet = pygame.image.load(attrs["path"]).convert_alpha()
|
sprite_sheet = pygame.image.load(attrs["path"]).convert_alpha()
|
||||||
|
@ -116,8 +121,8 @@ class Cache:
|
||||||
|
|
||||||
for path, folders, files in os.walk(attrs["path"]): # loop through all frames and add them to the sheet list
|
for path, folders, files in os.walk(attrs["path"]): # loop through all frames and add them to the sheet list
|
||||||
for file in files:
|
for file in files:
|
||||||
# use the name of the file without the file format specifier (the part before the dot) as the frame name
|
# use the name of the file without the file format specifier (the part before the dot) as the frame -
|
||||||
# and store the layer array
|
# name and store the layer array
|
||||||
frames[file.split(".")[0]] = self.get_layer_array(attrs, f"{path}/{file}")
|
frames[file.split(".")[0]] = self.get_layer_array(attrs, f"{path}/{file}")
|
||||||
|
|
||||||
return frames
|
return frames
|
||||||
|
|
|
@ -10,9 +10,10 @@ class Player(pygame.sprite.Sprite):
|
||||||
self.group = app.main_group
|
self.group = app.main_group
|
||||||
super().__init__(self.group)
|
super().__init__(self.group)
|
||||||
|
|
||||||
self.group.change_layer(self, CENTER.y)
|
self.group.change_layer(self, CENTER.y) # simpy set the layer to the y center of the screen because that is -
|
||||||
|
# the position of the player on the screen
|
||||||
|
|
||||||
size = vec2([50, 50])
|
size = vec2([50, 50]) # create a surface with a red dot on it
|
||||||
self.image = pygame.Surface(size, pygame.SRCALPHA)
|
self.image = pygame.Surface(size, pygame.SRCALPHA)
|
||||||
pygame.draw.circle(self.image, "red", size / 2, size[0] / 2)
|
pygame.draw.circle(self.image, "red", size / 2, size[0] / 2)
|
||||||
self.rect = self.image.get_rect(center=CENTER)
|
self.rect = self.image.get_rect(center=CENTER)
|
||||||
|
@ -22,7 +23,7 @@ class Player(pygame.sprite.Sprite):
|
||||||
self.angle = 0
|
self.angle = 0
|
||||||
self.diag_move_corr = 1 / math.sqrt(2)
|
self.diag_move_corr = 1 / math.sqrt(2)
|
||||||
|
|
||||||
def control(self):
|
def control(self): # move the player and rotate the view according to the key presses
|
||||||
self.inc = vec2(0)
|
self.inc = vec2(0)
|
||||||
speed = PLAYER_SPEED * self.app.delta_time
|
speed = PLAYER_SPEED * self.app.delta_time
|
||||||
rot_speed = PLAYER_ROT_SPEED * self.app.delta_time
|
rot_speed = PLAYER_ROT_SPEED * self.app.delta_time
|
||||||
|
|
|
@ -6,7 +6,7 @@ from random import uniform
|
||||||
P = "player"
|
P = "player"
|
||||||
A, B, C = "Robot", "Building", "Bla"
|
A, B, C = "Robot", "Building", "Bla"
|
||||||
|
|
||||||
MAP = [
|
MAP = [ # two dimensional object matrix
|
||||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
[0, 0, 0, 0, 0, B, B, B, B],
|
[0, 0, 0, 0, 0, B, B, B, B],
|
||||||
|
@ -31,7 +31,7 @@ class Scene:
|
||||||
rand_rot = lambda: uniform(0, 360)
|
rand_rot = lambda: uniform(0, 360)
|
||||||
rand_pos = lambda pos: pos + vec2(uniform(-0.25, 0.25))
|
rand_pos = lambda pos: pos + vec2(uniform(-0.25, 0.25))
|
||||||
|
|
||||||
for j, row in enumerate(MAP):
|
for j, row in enumerate(MAP): # loop through all objects on the map
|
||||||
for i, name in enumerate(row):
|
for i, name in enumerate(row):
|
||||||
pos = vec2(i, j) + vec2(0.5)
|
pos = vec2(i, j) + vec2(0.5)
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,9 @@ class StackedSprite(pygame.sprite.Sprite):
|
||||||
self.group = self.app.main_group
|
self.group = self.app.main_group
|
||||||
super().__init__(self.group)
|
super().__init__(self.group)
|
||||||
|
|
||||||
self.attrs = SPRITE_ATTRS[name]
|
self.attrs = SPRITE_ATTRS[name] # get attributes
|
||||||
self.y_offset = vec2(0, -self.attrs["layers"] / 2 * self.attrs["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 = self.app.cache.stacked_sprite_cache
|
self.cache = self.app.cache.stacked_sprite_cache
|
||||||
self.viewing_angle = app.cache.viewing_angle
|
self.viewing_angle = app.cache.viewing_angle
|
||||||
self.rotated_sprites = self.cache[name]["rotated_sprites"]
|
self.rotated_sprites = self.cache[name]["rotated_sprites"]
|
||||||
|
@ -23,15 +24,15 @@ class StackedSprite(pygame.sprite.Sprite):
|
||||||
self.screen_position = vec2(0)
|
self.screen_position = vec2(0)
|
||||||
self.rot = (rot % 360) // self.viewing_angle
|
self.rot = (rot % 360) // self.viewing_angle
|
||||||
|
|
||||||
def transform(self):
|
def transform(self): # recalculate position and rotation
|
||||||
pos = self.pos - self.player.offset
|
pos = self.pos - self.player.offset
|
||||||
pos = pos.rotate_rad(self.player.angle)
|
pos = pos.rotate_rad(self.player.angle)
|
||||||
self.screen_position = pos + CENTER
|
self.screen_position = pos + CENTER
|
||||||
|
|
||||||
def change_layer(self):
|
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)
|
self.group.change_layer(self, self.screen_position.y)
|
||||||
|
|
||||||
def get_angle(self):
|
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 = -math.degrees(self.player.angle) // self.viewing_angle + self.rot
|
||||||
self.angle = int(self.angle % NUM_ANGLES)
|
self.angle = int(self.angle % NUM_ANGLES)
|
||||||
|
|
||||||
|
@ -46,7 +47,7 @@ class StackedSprite(pygame.sprite.Sprite):
|
||||||
self.rect = self.image.get_rect(center=self.screen_position + self.y_offset)
|
self.rect = self.image.get_rect(center=self.screen_position + self.y_offset)
|
||||||
|
|
||||||
|
|
||||||
class AnimatedStackedSprite(pygame.sprite.Sprite):
|
class AnimatedStackedSprite(pygame.sprite.Sprite): # stacked sprite class for animated sprites, works nearly the same
|
||||||
def __init__(self, app, name, pos, rot=0):
|
def __init__(self, app, name, pos, rot=0):
|
||||||
self.app = app
|
self.app = app
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -56,11 +57,11 @@ class AnimatedStackedSprite(pygame.sprite.Sprite):
|
||||||
super().__init__(self.group)
|
super().__init__(self.group)
|
||||||
|
|
||||||
self.attrs = ANIMATED_SPRITE_ATTRS[name]
|
self.attrs = ANIMATED_SPRITE_ATTRS[name]
|
||||||
self.attrs["animated"] = True
|
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"])
|
self.y_offset = vec2(0, -self.attrs["layers"] / 2 * self.attrs["scale"]) # is animated
|
||||||
self.cache = self.app.cache.stacked_sprite_cache
|
self.cache = self.app.cache.stacked_sprite_cache
|
||||||
self.viewing_angle = app.cache.viewing_angle
|
self.viewing_angle = app.cache.viewing_angle
|
||||||
self.frame = list(self.cache[name]["frames"].keys())[0]
|
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.rotated_sprites = self.cache[name]["frames"][self.frame]["rotated_sprites"]
|
||||||
self.angle = 0
|
self.angle = 0
|
||||||
self.screen_position = vec2(0)
|
self.screen_position = vec2(0)
|
||||||
|
@ -78,7 +79,7 @@ class AnimatedStackedSprite(pygame.sprite.Sprite):
|
||||||
self.angle = -math.degrees(self.player.angle) // self.viewing_angle + self.rot
|
self.angle = -math.degrees(self.player.angle) // self.viewing_angle + self.rot
|
||||||
self.angle = int(self.angle % NUM_ANGLES)
|
self.angle = int(self.angle % NUM_ANGLES)
|
||||||
|
|
||||||
def animate(self):
|
def animate(self): # change the layer to display another frame
|
||||||
self.frame = str(round(self.app.time) * 4 % 3)
|
self.frame = str(round(self.app.time) * 4 % 3)
|
||||||
self.rotated_sprites = self.cache[self.name]["frames"][self.frame]["rotated_sprites"]
|
self.rotated_sprites = self.cache[self.name]["frames"][self.frame]["rotated_sprites"]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue