Added kill list and recipes. Checks every three kills.

This commit is contained in:
Cameron Smart
2020-04-22 20:18:00 -07:00
parent 11ffacef01
commit 68f572124a
3 changed files with 107 additions and 100 deletions

View File

@@ -38,16 +38,16 @@ class Config(object):
PLAYER_MOVEMENT_SPEED = 14 PLAYER_MOVEMENT_SPEED = 14
# How many pixels to keep as a minimum margin between the characters and the edge of the screen. # How many pixels to keep as a minimum margin between the characters and the edge of the screen.
LEFT_VIEWPORT_MARGIN = 500 LEFT_VIEWPORT_MARGIN = 700
RIGHT_VIEWPORT_MARGIN = 500 RIGHT_VIEWPORT_MARGIN = 700
BOTTOM_VIEWPORT_MARGIN = 250 BOTTOM_VIEWPORT_MARGIN = 300
TOP_VIEWPORT_MARGIN = 200 TOP_VIEWPORT_MARGIN = 350
# All debug statements and renderings should use this # All debug statements and renderings should use this
DEBUG = True DEBUG = False
#Monster Count to be spawned #Monster Count to be spawned
MONSTER_COUNT = 4 MONSTER_COUNT = 20
class Enums(Enum): class Enums(Enum):

View File

@@ -13,7 +13,7 @@ from typing import Tuple, List
import arcade import arcade
from config import Config from config import Config
from map import Dungeon from map import Dungeon
from mobs import Player, Mob from mobs import Player, Enemy
from projectiles import Temp from projectiles import Temp
@@ -80,10 +80,11 @@ class Game(arcade.Window):
#Set up monsters #Set up monsters
for count in range(Config.MONSTER_COUNT): for count in range(Config.MONSTER_COUNT):
mob = Mob(filename="resources/images/monsters/ghost/ghost1.png", dungeon=self.dungeon) mob = Enemy(filename="resources/images/monsters/ghost/ghost1.png", dungeon=self.dungeon)
mob.center_x, mob.center_y = random.choice(self.dungeon.levelList).center() mob.center_x, mob.center_y = random.choice(self.dungeon.levelList).center()
mob.target = self.player mob.target = self.player
mob.scale = 4 mob.scale = 4
mob.monster_type = 'ghost'
self.enemy_list.append(mob) self.enemy_list.append(mob)
''' '''
mob = Mob(filename="resources/images/monsters/ghost/ghost1.png", dungeon=self.dungeon) mob = Mob(filename="resources/images/monsters/ghost/ghost1.png", dungeon=self.dungeon)
@@ -140,10 +141,10 @@ class Game(arcade.Window):
arcade.draw_rectangle_outline(round(x / Config.TILE_SIZE) * Config.TILE_SIZE, arcade.draw_rectangle_outline(round(x / Config.TILE_SIZE) * Config.TILE_SIZE,
round(y / Config.TILE_SIZE) * Config.TILE_SIZE, round(y / Config.TILE_SIZE) * Config.TILE_SIZE,
Config.TILE_SIZE, Config.TILE_SIZE, arcade.color.RED) Config.TILE_SIZE, Config.TILE_SIZE, arcade.color.RED)
self.player.draw_hit_box() #self.player.draw_hit_box()
arcade.draw_text(str((x, y)), x - 40, y + 50, arcade.color.WHITE, 15, font_name='Arial') #arcade.draw_text(str((x, y)), x - 40, y + 50, arcade.color.WHITE, 15, font_name='Arial')
arcade.draw_text(f"FPS: {self.fps.get_fps():3.0f}", self.view_left + 50, self.view_bottom + 30, #arcade.draw_text(f"FPS: {self.fps.get_fps():3.0f}", self.view_left + 50, self.view_bottom + 30,
arcade.color.WHITE, 16, font_name='Arial') # arcade.color.WHITE, 16, font_name='Arial')
# Draw paths for all mobs # Draw paths for all mobs
for mob in self.active_enemies: for mob in self.active_enemies:
@@ -152,7 +153,7 @@ class Game(arcade.Window):
path = mob.get_path() path = mob.get_path()
t2 = time.time() t2 = time.time()
#print(f'Path acquired in {round(t2 - t1, 4)}s') #print(f'Path acquired in {round(t2 - t1, 4)}s')
self.draw_path(path) #self.draw_path(path)
mob.tick(path) mob.tick(path)
self.fps.tick() self.fps.tick()
@@ -288,7 +289,6 @@ class Game(arcade.Window):
Config.SCREEN_WIDTH + self.view_left, Config.SCREEN_WIDTH + self.view_left,
self.view_bottom, self.view_bottom,
Config.SCREEN_HEIGHT + self.view_bottom) Config.SCREEN_HEIGHT + self.view_bottom)
#Enemy activation and update #Enemy activation and update
for enemy in reversed(self.enemy_list): for enemy in reversed(self.enemy_list):
if ( if (
@@ -300,9 +300,14 @@ class Game(arcade.Window):
if Config.DEBUG: print("Activate Enemy") if Config.DEBUG: print("Activate Enemy")
self.active_enemies.append(enemy) self.active_enemies.append(enemy)
self.enemy_list.remove(enemy) self.enemy_list.remove(enemy)
for enemy in self.active_enemies: try:
enemy.update() for enemy in self.active_enemies:
enemy.update()
path = enemy.get_path()
enemy.tick(path)
except Exception:
import traceback
traceback.print_exc()
# Projectile updates # Projectile updates
self.bullet_list.update() self.bullet_list.update()
for bullet in self.bullet_list: for bullet in self.bullet_list:
@@ -314,6 +319,7 @@ class Game(arcade.Window):
if len(hit_list) > 0: if len(hit_list) > 0:
bullet.remove_from_sprite_lists() bullet.remove_from_sprite_lists()
if len(enemy_hit_list): if len(enemy_hit_list):
self.player.add_kill(enemy_hit_list[0].monster_type)
enemy_hit_list[0].remove_from_sprite_lists() enemy_hit_list[0].remove_from_sprite_lists()

View File

@@ -31,6 +31,90 @@ class Mob(arcade.Sprite):
self.dungeon = dungeon self.dungeon = dungeon
self.target = None self.target = None
class Player(Mob):
"""
Represents a Player.
While this is a instance, there should only be one in the world at any given time.
"""
def __init__(self, *args, **kwargs) -> None:
super(Player, self).__init__(*args, **kwargs)
self.animations = PlayerAnimations(SpritePaths.KNIGHT)
# Used for mapping directions to animations
self.map = {
Enums.IDLE: self.animations.idles,
Enums.UP: self.animations.up,
Enums.DOWN: self.animations.down,
Enums.RIGHT: self.animations.right,
Enums.LEFT: self.animations.left
}
self.refreshIndex = 0
self.prev = Enums.IDLE
self.texture = next(self.map[self.prev])
self.kill_list = []
self.cur_recipe = ['ghost', 'ghost', 'ghost']
def add_kill(self, creature):
# Adds a kill to kill_list. If 3 or more check the recipe then give a power up if it matches.
self.kill_list.append(creature)
if self.cur_recipe == self.kill_list:
print("+++++++++++++++++++++++++++++++++++++++++++++++++++++++")
self.kill_list = []
def update_animation(self, delta_time: float = 1 / 60) -> None:
"""
Updates animations for the Player.
:param delta_time: No idea.
"""
# Increase the refresh index according
self.refreshIndex = (self.refreshIndex + 1) % Config.RUN_UPDATES_PER_FRAME
# Logic to determine what direction we're in.
if self.change_x == 0 and self.change_y == 0:
cur = Enums.IDLE
elif self.change_y > 0: # Up
cur = Enums.UP
elif self.change_y < 0: # Down
cur = Enums.DOWN
elif self.change_x > 0: # Left
cur = Enums.RIGHT
elif self.change_x < 0: # Right
cur = Enums.LEFT
else: # Idle
cur = Enums.IDLE
# If we're in a new direction or the refresh index has reset
if self.prev is not cur or self.refreshIndex == 0:
self.texture = next(self.map[cur])
self.prev = cur
def tick(self):
"""
While Player objects do not have any AI (they are controlled by the user),
the tick function can keep track of statistics that progress over time, like
regenerating health/armor or status effects like poison.
"""
class Enemy(Mob):
"""
Represents an Enemy Mob.
Will take basic offensive actions against Player objects.
"""
def __init__(self, *args, **kwargs) -> None:
super(Enemy, self).__init__(*args, **kwargs)
self.monster_type = ''
def nearestPosition(self) -> Tuple[int, int]: def nearestPosition(self) -> Tuple[int, int]:
""" """
Returns the nearest absolute dungeon tile the Mob is placed on. Returns the nearest absolute dungeon tile the Mob is placed on.
@@ -78,86 +162,3 @@ class Mob(arcade.Sprite):
self.dungeon.grid.cleanup() self.dungeon.grid.cleanup()
return paths return paths
class Player(Mob):
"""
Represents a Player.
While this is a instance, there should only be one in the world at any given time.
"""
def __init__(self, *args, **kwargs) -> None:
super(Player, self).__init__(*args, **kwargs)
self.animations = PlayerAnimations(SpritePaths.KNIGHT)
# Used for mapping directions to animations
self.map = {
Enums.IDLE: self.animations.idles,
Enums.UP: self.animations.up,
Enums.DOWN: self.animations.down,
Enums.RIGHT: self.animations.right,
Enums.LEFT: self.animations.left
}
self.refreshIndex = 0
self.prev = Enums.IDLE
self.texture = next(self.map[self.prev])
def update_animation(self, delta_time: float = 1 / 60) -> None:
"""
Updates animations for the Player.
:param delta_time: No idea.
"""
# Increase the refresh index according
self.refreshIndex = (self.refreshIndex + 1) % Config.RUN_UPDATES_PER_FRAME
# Logic to determine what direction we're in.
if self.change_x == 0 and self.change_y == 0:
cur = Enums.IDLE
elif self.change_y > 0: # Up
cur = Enums.UP
elif self.change_y < 0: # Down
cur = Enums.DOWN
elif self.change_x > 0: # Left
cur = Enums.RIGHT
elif self.change_x < 0: # Right
cur = Enums.LEFT
else: # Idle
cur = Enums.IDLE
# If we're in a new direction or the refresh index has reset
if self.prev is not cur or self.refreshIndex == 0:
self.texture = next(self.map[cur])
self.prev = cur
def tick(self):
"""
While Player objects do not have any AI (they are controlled by the user),
the tick function can keep track of statistics that progress over time, like
regenerating health/armor or status effects like poison.
"""
class Enemy(Mob):
"""
Represents an Enemy Mob.
Will take basic offensive actions against Player objects.
"""
def __init__(self, *args, **kwargs) -> None:
super(Enemy, self).__init__(*args, **kwargs)
def tick(self) -> None:
"""
A on_update function, the Enemy Mob should scan for the player, decide how to path to it, and
decide how to take offensive action.
"""
pass
def path(self) -> None:
"""
Not yet decided how this function should work.
Basically, most pathfinding decisions should be kept within this function.
"""
pass