Merge pull request #22 from n0remac/character-animation

Character animation
This commit is contained in:
2020-04-20 00:14:31 -05:00
committed by GitHub
42 changed files with 121 additions and 49 deletions
+2
View File
@@ -15,6 +15,8 @@ class Config(object):
SCREEN_HEIGHT = 1000 SCREEN_HEIGHT = 1000
SCREEN_TITLE = "Triple Dungeon" SCREEN_TITLE = "Triple Dungeon"
TILE_WIDTH = 63 TILE_WIDTH = 63
IDLE_UPDATES_PER_FRAME = 20
RUN_UPDATES_PER_FRAME = 10
# Constants used to scale our sprites from their original size # Constants used to scale our sprites from their original size
CHARACTER_SCALING = 1 CHARACTER_SCALING = 1
+40 -31
View File
@@ -8,8 +8,7 @@ import arcade
from config import Config from config import Config
from map import Dungeon from map import Dungeon
from mobs import Player from mobs import Player, Enemy
from mobs import Enemy
class Game(arcade.Window): class Game(arcade.Window):
@@ -29,14 +28,14 @@ class Game(arcade.Window):
self.player_list = None self.player_list = None
# Separate variable that holds the player sprite # Separate variable that holds the player sprite
self.player_sprite = None self.player = None
# list to keep track of keypresses
self.prev_keypress = []
# Our physics engine # Our physics engine
self.physics_engine = None self.physics_engine = None
# list to keep track of keypresses
self.prev_keypress = []
# Used to keep track of our scrolling # Used to keep track of our scrolling
self.view_bottom = 0 self.view_bottom = 0
self.view_left = 0 self.view_left = 0
@@ -47,24 +46,31 @@ class Game(arcade.Window):
""" Set up the game here. Call this function to restart the game. """ """ Set up the game here. Call this function to restart the game. """
# Create the Sprite lists # Create the Sprite lists
self.player_list = arcade.SpriteList()
self.wall_list = arcade.SpriteList() self.wall_list = arcade.SpriteList()
self.floor_list = arcade.SpriteList() self.floor_list = arcade.SpriteList()
self.enemy_list = arcade.SpriteList() self.enemy_list = arcade.SpriteList()
# Set up the player, specifically placing it at these coordinates. # Set up the player, specifically placing it at these coordinates.
Player.setup(self) self.player = Player()
self.player.scale = 1
self.player.center_x = Config.SCREEN_WIDTH / 2
self.player.center_y = Config.SCREEN_HEIGHT / 2
self.player_list = self.player
# Create the dungeon # Create the dungeon
dungeon = Dungeon() dungeon = Dungeon()
self.floor_list, self.wall_list = dungeon.get_lists() self.floor_list = dungeon.floor_list
self.wall_list = dungeon.wall_list
# Create monsters # Create monsters
self.enemy_list.append(Enemy("resources/images/monsters/ghost/ghost1.png", 200, 200).get_enemy()) # This needs to be updated to comply with the new mobs.py code
self.enemy_list.append(Enemy("resources/images/monsters/frog/frog1.png", 200, 1000).get_enemy()) #self.enemy_list.append(Enemy("resources/images/monsters/ghost/ghost1.png", 200, 200, 4).get_enemy())
#self.enemy_list.append(Enemy("resources/images/monsters/frog/frog1.png", 200, 1000, 4).get_enemy())
# Create the 'physics engine' # Create the 'physics engine'
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list) self.physics_engine = arcade.PhysicsEngineSimple(self.player, self.wall_list)
def on_draw(self): def on_draw(self):
""" Render the screen. """ """ Render the screen. """
@@ -74,7 +80,7 @@ class Game(arcade.Window):
# Draw our sprites # Draw our sprites
self.floor_list.draw() self.floor_list.draw()
self.player_sprite.draw() self.player_list.draw()
self.enemy_list.draw() self.enemy_list.draw()
self.wall_list.draw() self.wall_list.draw()
@@ -82,34 +88,35 @@ class Game(arcade.Window):
"""Called whenever a key is pressed. """ """Called whenever a key is pressed. """
if key == arcade.key.UP or key == arcade.key.W: if key == arcade.key.UP or key == arcade.key.W:
self.player_sprite.change_y = Config.PLAYER_MOVEMENT_SPEED self.player_list.change_y = Config.PLAYER_MOVEMENT_SPEED
self.prev_keypress.append(key) self.prev_keypress.append(key)
elif key == arcade.key.DOWN or key == arcade.key.S: elif key == arcade.key.DOWN or key == arcade.key.S:
self.player_sprite.change_y = -Config.PLAYER_MOVEMENT_SPEED self.player_list.change_y = -Config.PLAYER_MOVEMENT_SPEED
self.prev_keypress.append(key) self.prev_keypress.append(key)
elif key == arcade.key.LEFT or key == arcade.key.A: elif key == arcade.key.LEFT or key == arcade.key.A:
self.player_sprite.change_x = -Config.PLAYER_MOVEMENT_SPEED self.player_list.change_x = -Config.PLAYER_MOVEMENT_SPEED
self.prev_keypress.append(key) self.prev_keypress.append(key)
elif key == arcade.key.RIGHT or key == arcade.key.D: elif key == arcade.key.RIGHT or key == arcade.key.D:
self.player_sprite.change_x = Config.PLAYER_MOVEMENT_SPEED self.player_list.change_x = Config.PLAYER_MOVEMENT_SPEED
self.prev_keypress.append(key) self.prev_keypress.append(key)
elif key == 65307:
self.close()
def on_key_release(self, key, modifiers): def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """ """Called when the user releases a key. """
if key == arcade.key.UP or key == arcade.key.W: if key == arcade.key.UP or key == arcade.key.W:
self.player_sprite.change_y = 0 self.player_list.change_y = 0
self.prev_keypress.remove(key) self.prev_keypress.remove(key)
elif key == arcade.key.DOWN or key == arcade.key.S: elif key == arcade.key.DOWN or key == arcade.key.S:
self.player_sprite.change_y = 0 self.player_list.change_y = 0
self.prev_keypress.remove(key) self.prev_keypress.remove(key)
elif key == arcade.key.LEFT or key == arcade.key.A: elif key == arcade.key.LEFT or key == arcade.key.A:
self.player_sprite.change_x = 0 self.player_list.change_x = 0
self.prev_keypress.remove(key) self.prev_keypress.remove(key)
elif key == arcade.key.RIGHT or key == arcade.key.D: elif key == arcade.key.RIGHT or key == arcade.key.D:
self.player_sprite.change_x = 0 self.player_list.change_x = 0
self.prev_keypress.remove(key) self.prev_keypress.remove(key)
if self.prev_keypress: if self.prev_keypress:
self.on_key_press(self.prev_keypress.pop(0), 0) self.on_key_press(self.prev_keypress.pop(0), 0)
@@ -118,28 +125,30 @@ class Game(arcade.Window):
# Move the player with the physics engine # Move the player with the physics engine
self.physics_engine.update() self.physics_engine.update()
self.player_list.update_animation()
changed = False # Track if we need to change the viewport changed = False # Track if we need to change the viewport
# Below manages all scrolling mechanics # Below manages all scrolling mechanics
# Scroll left # Scroll left
left_boundary = self.view_left + Config.LEFT_VIEWPORT_MARGIN left_boundary = self.view_left + Config.LEFT_VIEWPORT_MARGIN
if self.player_sprite.left < left_boundary: if self.player_list.left < left_boundary:
self.view_left -= left_boundary - self.player_sprite.left self.view_left -= left_boundary - self.player_list.left
changed = True changed = True
# Scroll right # Scroll right
right_boundary = self.view_left + Config.SCREEN_WIDTH - Config.RIGHT_VIEWPORT_MARGIN right_boundary = self.view_left + Config.SCREEN_WIDTH - Config.RIGHT_VIEWPORT_MARGIN
if self.player_sprite.right > right_boundary: if self.player_list.right > right_boundary:
self.view_left += self.player_sprite.right - right_boundary self.view_left += self.player_list.right - right_boundary
changed = True changed = True
# Scroll up # Scroll up
top_boundary = self.view_bottom + Config.SCREEN_HEIGHT - Config.TOP_VIEWPORT_MARGIN top_boundary = self.view_bottom + Config.SCREEN_HEIGHT - Config.TOP_VIEWPORT_MARGIN
if self.player_sprite.top > top_boundary: if self.player_list.top > top_boundary:
self.view_bottom += self.player_sprite.top - top_boundary self.view_bottom += self.player_list.top - top_boundary
changed = True changed = True
# Scroll down # Scroll down
bottom_boundary = self.view_bottom + Config.BOTTOM_VIEWPORT_MARGIN bottom_boundary = self.view_bottom + Config.BOTTOM_VIEWPORT_MARGIN
if self.player_sprite.bottom < bottom_boundary: if self.player_list.bottom < bottom_boundary:
self.view_bottom -= bottom_boundary - self.player_sprite.bottom self.view_bottom -= bottom_boundary - self.player_list.bottom
changed = True changed = True
if changed: if changed:
-4
View File
@@ -63,9 +63,6 @@ class Dungeon(object):
#self.level_count, self.size = level_count, size #self.level_count, self.size = level_count, size
#self.levels = [[None for y in range(size)] for x in range(size)] # array[x][y] style access #self.levels = [[None for y in range(size)] for x in range(size)] # array[x][y] style access
def get_lists(self):
return (self.floor_list, self.wall_list)
def add_level(self, sprit_list): def add_level(self, sprit_list):
for x in sprit_list: for x in sprit_list:
self.levels.append(x) self.levels.append(x)
@@ -154,7 +151,6 @@ class Level:
def rotate_level(self, times_rotated): def rotate_level(self, times_rotated):
m = np.array(self.level) m = np.array(self.level)
print(m)
for i in range(0, times_rotated): for i in range(0, times_rotated):
m = np.rot90(m) m = np.rot90(m)
self.level = m.tolist() self.level = m.tolist()
+79 -14
View File
@@ -7,19 +7,28 @@ import arcade
from config import Config from config import Config
# Constants used to track if the player is facing left or right
RIGHT_FACING = 0
LEFT_FACING = 1
FRONT_FACING = 2
UP_FACING = 3
DOWN_FACING = 4
class Mob(object): class Mob(arcade.Sprite):
""" """
Represents a Mob. No defined behaviour, it has no intelligence. Represents a Mob. No defined behaviour, it has no intelligence.
""" """
def __init__(self, sprite, x, y, max_health=100, max_armor=0) -> None: def __init__(self, max_health=100, max_armor=0, *args, **kwargs) -> None:
self.sprite_path = sprite # Set up parent class
self.sprite = arcade.Sprite(self.sprite_path, Config.CHARACTER_SCALING) super().__init__()
self.max_health, self.max_armor = max_health, max_armor self.max_health, self.max_armor = max_health, max_armor
self.health, self.armor = max_health, max_armor self.health, self.armor = max_health, max_armor
self.sprite.scale = 4 self.idle_textures = []
self.sprite.center_x = x self.walking_textures = []
self.sprite.center_y = y self.up_textures = []
self.down_textures = []
self.cur_texture = 0
def tick(self) -> None: def tick(self) -> None:
""" """
@@ -36,12 +45,68 @@ class Player(Mob):
def __init__(self, *args, **kwargs) -> None: def __init__(self, *args, **kwargs) -> None:
super(Player, self).__init__(*args, **kwargs) super(Player, self).__init__(*args, **kwargs)
def setup(self): main_path = "resources/images/character/knight/"
image_source = "resources/images/monsters/skeleton.png"
self.player_sprite = arcade.Sprite(image_source, Config.CHARACTER_SCALING) # Default to face-front
self.player_sprite.center_x = Config.SCREEN_WIDTH / 2 self.character_face_direction = FRONT_FACING
self.player_sprite.center_y = Config.SCREEN_HEIGHT / 2
self.player_sprite.scale = 4 # Load textures for idle standing
for i in range(4):
texture = arcade.load_texture(f"{main_path}knight iso char_idle_{i}.png")
self.idle_textures.append(texture)
# Load textures for running horizontally
for i in range(6):
self.walking_textures.append([arcade.load_texture(f"{main_path}knight iso char_run left_{i}.png"),arcade.load_texture(f"{main_path}knight iso char_run left_{i}.png", mirrored=True)])
# Load textures for running down
for i in range(5):
self.down_textures.append(arcade.load_texture(f"{main_path}knight iso char_run down_{i}.png"))
# Load textures for running up
for i in range(5):
self.up_textures.append(arcade.load_texture(f"{main_path}knight iso char_run up_{i}.png"))
def update_animation(self, delta_time: float = 1/60):
# Figure out if we need to flip face left, right, up, or down
if self.change_x > 0:
self.character_face_direction = LEFT_FACING
elif self.change_x < 0:
self.character_face_direction = RIGHT_FACING
elif self.change_x == 0 and self.change_y == 0:
self.character_face_direction = FRONT_FACING
# idle animation
if self.change_x == 0 and self.change_y == 0:
self.cur_texture += 1
if self.cur_texture > 3 * Config.IDLE_UPDATES_PER_FRAME:
self.cur_texture = 0
self.texture = self.idle_textures[self.cur_texture // Config.IDLE_UPDATES_PER_FRAME]
return
#walk up animation
if self.change_y > 0:
self.cur_texture += 1
if self.cur_texture > 4 * Config.RUN_UPDATES_PER_FRAME:
self.cur_texture = 0
self.texture = self.up_textures[self.cur_texture // Config.RUN_UPDATES_PER_FRAME]
return
#walk down animation
if self.change_y < 0:
self.cur_texture += 1
if self.cur_texture > 4 * Config.RUN_UPDATES_PER_FRAME:
self.cur_texture = 0
self.texture = self.down_textures[self.cur_texture // Config.RUN_UPDATES_PER_FRAME]
return
# Walking left/right animation
self.cur_texture += 1
if self.cur_texture > 5 * Config.RUN_UPDATES_PER_FRAME:
self.cur_texture = 0
self.texture = self.walking_textures[self.cur_texture // Config.RUN_UPDATES_PER_FRAME][self.character_face_direction]
def tick(self): def tick(self):
""" """
@@ -60,7 +125,7 @@ class Enemy(Mob):
super(Enemy, self).__init__(*args, **kwargs) super(Enemy, self).__init__(*args, **kwargs)
def get_enemy(self): def get_enemy(self):
return self.sprite return self
def tick(self) -> None: def tick(self) -> None:
""" """
Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 547 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B