diff --git a/triple-dungeon/config.py b/triple-dungeon/config.py index ddf7fc0..07f0986 100644 --- a/triple-dungeon/config.py +++ b/triple-dungeon/config.py @@ -37,6 +37,8 @@ class Config(object): # Movement speed of player, in pixels per frame PLAYER_MOVEMENT_SPEED = 14 + MONSTER_MOVEMENT_SPEED = 11 + # How many pixels to keep as a minimum margin between the characters and the edge of the screen. LEFT_VIEWPORT_MARGIN = 700 RIGHT_VIEWPORT_MARGIN = 700 @@ -47,7 +49,7 @@ class Config(object): DEBUG = False # Monster Count to be spawned - MONSTER_COUNT = 6 + MONSTER_COUNT = 8 class Enums(Enum): diff --git a/triple-dungeon/main.py b/triple-dungeon/main.py index ba717f5..e7d8375 100644 --- a/triple-dungeon/main.py +++ b/triple-dungeon/main.py @@ -57,7 +57,6 @@ class Game(arcade.Window): # Used to keep track of our scrolling self.view_bottom = self.view_left = 0 self.Recipe = [] - self.enemies_in_range = [] arcade.set_background_color(arcade.color.BLACK) @@ -80,12 +79,11 @@ class Game(arcade.Window): level = random.choice(self.dungeon.levelList) self.player.center_x, self.player.center_y = level.center() self.player.cur_recipe = self.Recipe.active - self.player.monster_collisions = arcade.PhysicsEngineSimple(self.player, self.dungeon.getWalls()) + self.player.collisions = arcade.PhysicsEngineSimple(self.player, self.dungeon.getWalls()) # Set up monsters self.Mobs = MobHandler() self.enemy_list = self.Mobs.setup(Config.MONSTER_COUNT, Config.MONSTER_COUNT, self.player, self.dungeon) - self.active_enemies = self.Mobs.active_enemies # Setup viewport self.view_bottom = self.player.center_x - (0.5 * Config.SCREEN_WIDTH) + 300 @@ -103,9 +101,8 @@ class Game(arcade.Window): # Draw our sprites self.dungeon.render() - self.player.draw() self.Mobs.render() - self.active_enemies.draw() + #self.active_enemies.draw() self.bullet_list.draw() self.Recipe.render() @@ -237,7 +234,7 @@ class Game(arcade.Window): # Collision Checks hit_list = arcade.check_for_collision_with_list(bullet, self.dungeon.getWalls()) - enemy_hit_list = arcade.check_for_collision_with_list(bullet, self.active_enemies) + enemy_hit_list = arcade.check_for_collision_with_list(bullet, self.enemy_list) # If it did, get rid of the bullet if len(hit_list) > 0: bullet.remove_from_sprite_lists() diff --git a/triple-dungeon/map.py b/triple-dungeon/map.py index 32f254e..3666364 100644 --- a/triple-dungeon/map.py +++ b/triple-dungeon/map.py @@ -10,7 +10,7 @@ import json from pprint import pprint import arcade -import numpy as np +import random from itertools import chain from config import Config @@ -177,13 +177,10 @@ class Level: """ return int((self.x + 0.5) * Config.LEVEL_SIZE), int((self.y + 0.5) * Config.LEVEL_SIZE) - def rotate_level(self, times_rotated): + def random(self) -> tuple: """ - Rotates the - :param times_rotated: - :return: + Returns a random spot in the level. + :return: A tuple containing the X and Y coordinates """ - m = np.array(self.level) - for i in range(0, times_rotated % 4): - m = np.rot90(m) - self.level = m.tolist() + + return int((self.x + random.randint(1,9)/10) * Config.LEVEL_SIZE), int((self.y + random.randint(1,9)/10) * Config.LEVEL_SIZE) diff --git a/triple-dungeon/mobs.py b/triple-dungeon/mobs.py index b15e071..66895a2 100644 --- a/triple-dungeon/mobs.py +++ b/triple-dungeon/mobs.py @@ -13,64 +13,89 @@ from config import Config, Enums, SpritePaths from map import Dungeon from sprites import PlayerAnimations -class MobHandler(arcade.SpriteList): +class MobHandler: def __init__(self): super().__init__() self.enemy_list = [] - self.active_enemies = [] + self.avoid_list = [] self.dungeon = None self.player = None def setup(self, ghost, frogs, player, dungeon) -> list: self.enemy_list = arcade.SpriteList() - self.active_enemies = arcade.SpriteList() self.dungeon = dungeon self.player = player + self.avoid_list = arcade.SpriteList() + self.avoid_list.append(self.player) + for d in dungeon.getWalls(): + self.avoid_list.append(d) for count in range(ghost): mob = Enemy(filename="resources/images/monsters/ghost/ghost1.png", dungeon=self.dungeon) - mob.center_x, mob.center_y = random.choice(self.dungeon.levelList).center() + level = random.choice(self.dungeon.levelList) + mob.center_x, mob.center_y = level.random() mob.target = self.player mob.scale = 4 mob.monster_type = 'ghost' - mob.monster_collisions = arcade.PhysicsEngineSimple(mob, self.active_enemies) + mob.collisions = arcade.PhysicsEngineSimple(mob, self.avoid_list) + mob.level = level self.enemy_list.append(mob) + self.avoid_list.append(mob) for count in range(frogs): mob = Enemy(filename="resources/images/monsters/frog/frog1.png", dungeon=self.dungeon) - mob.center_x, mob.center_y = random.choice(self.dungeon.levelList).center() + level = random.choice(self.dungeon.levelList) + mob.center_x, mob.center_y = level.random() mob.target = self.player mob.scale = 4 mob.monster_type = 'frog' - mob.monster_collisions = arcade.PhysicsEngineSimple(mob, self.active_enemies) + mob.collisions = arcade.PhysicsEngineSimple(mob, self.avoid_list) + mob.level = level self.enemy_list.append(mob) + self.avoid_list.append(mob) return self.enemy_list - def render(self) -> None: + def render(self) -> None: + self.player.draw() self.enemy_list.draw() def update(self) -> None: #update player - self.player.monster_collisions.update() + self.player.collisions.update() self.player.update_animation() # Enemy activation and update for enemy in reversed(self.enemy_list): # TODO replace with distance checking distance = self.get_distance(enemy) + enemy.collisions.update() if (distance < 300): - self.active_enemies.append(enemy) - self.enemy_list.remove(enemy) - enemy.active = True - try: - for enemy in self.active_enemies: - enemy.monster_collisions.update() - path = enemy.get_path() - enemy.tick(path) - except Exception: - import traceback - traceback.print_exc() + enemy.speed = Config.MONSTER_MOVEMENT_SPEED + try: + path = enemy.get_path(enemy.target.position) + enemy.tick(path) + except Exception: + import traceback + traceback.print_exc() + else: + left, right, bottom, top = arcade.get_viewport() + if ( + enemy.bottom > bottom and + enemy.top < bottom + Config.SCREEN_HEIGHT and + enemy.right < left + Config.SCREEN_WIDTH and + enemy.left > left + ): + enemy.speed = 5 + ran = random.randint(0,1000) + if ran > 950: + print(ran) + try: + path = enemy.get_path(enemy.level.random()) + enemy.tick(path) + except Exception: + import traceback + traceback.print_exc() def get_distance(self, enemy) -> int: start_x = enemy.center_x @@ -80,6 +105,20 @@ class MobHandler(arcade.SpriteList): distance = math.sqrt(math.pow(start_x - end_x, 2) + math.pow(start_y - end_y, 2)) return distance + @staticmethod + def draw_path(path: List[Tuple[int, int]]) -> None: + """ + Draws a line between positions in a list of tuple, also known as the path. + :param path: A list of tuple positions defining a path that can be traversed. + """ + + if len(path) > 2: + path = map(lambda point: ((point[0]) * Config.TILE_SIZE, (point[1]) * Config.TILE_SIZE), path) + path = list(path) + #print(path) + for pos1, pos2 in zip(path, path[1:]): + arcade.draw_line(*pos1, *pos2, color=arcade.color.RED) + class Mob(arcade.Sprite): """ @@ -97,10 +136,10 @@ class Mob(arcade.Sprite): self.up_textures = [] self.down_textures = [] self.cur_texture = 0 - self.monster_collisions = None + self.collisions = None self.dungeon = dungeon self.target = None - self.collisions = None + self.level = None class Player(Mob): @@ -127,6 +166,7 @@ class Player(Mob): self.texture = next(self.map[self.prev]) self.kill_list = [] self.cur_recipe = None + self.speed = 14 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. @@ -176,8 +216,6 @@ class Player(Mob): """ - - class Enemy(Mob): """ Represents an Enemy Mob. @@ -187,7 +225,6 @@ class Enemy(Mob): def __init__(self, *args, **kwargs) -> None: super(Enemy, self).__init__(*args, **kwargs) self.monster_type = '' - self.active = False def nearestPosition(self) -> Tuple[int, int]: """ @@ -202,25 +239,26 @@ class Enemy(Mob): """ A on_update function, the Mob should decide it's next actions here. """ - - curpos, nextpos = self.nearestPosition(), path[1] + near_pos = self.nearestPosition() + + curpos, nextpos = near_pos, path[1] # print(curpos, nextpos) if nextpos[0] > curpos[0]: - self.change_x = Config.PLAYER_MOVEMENT_SPEED - 3 + self.change_x = self.speed elif nextpos[0] < curpos[0]: - self.change_x = -Config.PLAYER_MOVEMENT_SPEED + 3 + self.change_x = -self.speed else: self.change_x = 0 if nextpos[1] > curpos[1]: - self.change_y = Config.PLAYER_MOVEMENT_SPEED - 3 + self.change_y = self.speed elif nextpos[1] < curpos[1]: - self.change_y = -Config.PLAYER_MOVEMENT_SPEED + 3 + self.change_y = -self.speed else: self.change_y = 0 - # print(self.change_x, self.change_y) + def get_path(self, end: Tuple[int, int] = None) -> List[Tuple[int, int]]: """ @@ -229,10 +267,9 @@ class Enemy(Mob): :param end: A the endpoint tuple. Must be a valid position within the matrix. :return: """ - if end is None: - end = self.target.position - start, end = self.nearestPosition(), (round(end[0] / Config.TILE_SIZE), round(end[1] / Config.TILE_SIZE)) - start, end = self.dungeon.grid.node(*start), self.dungeon.grid.node(*end) - paths, runs = self.dungeon.finder.find_path(start, end, self.dungeon.grid) - self.dungeon.grid.cleanup() - return paths + + start, end = self.nearestPosition(), (round(end[0] / Config.TILE_SIZE), round(end[1] / Config.TILE_SIZE)) + start, end = self.dungeon.grid.node(*start), self.dungeon.grid.node(*end) + paths, runs = self.dungeon.finder.find_path(start, end, self.dungeon.grid) + self.dungeon.grid.cleanup() + return paths \ No newline at end of file