Monsters on screen move randomly when not active.

This commit is contained in:
Cameron Smart
2020-04-24 01:36:44 -07:00
parent 8fc41803f4
commit dd45c32283
4 changed files with 88 additions and 55 deletions

View File

@@ -37,6 +37,8 @@ class Config(object):
# Movement speed of player, in pixels per frame # Movement speed of player, in pixels per frame
PLAYER_MOVEMENT_SPEED = 14 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. # How many pixels to keep as a minimum margin between the characters and the edge of the screen.
LEFT_VIEWPORT_MARGIN = 700 LEFT_VIEWPORT_MARGIN = 700
RIGHT_VIEWPORT_MARGIN = 700 RIGHT_VIEWPORT_MARGIN = 700
@@ -47,7 +49,7 @@ class Config(object):
DEBUG = False DEBUG = False
# Monster Count to be spawned # Monster Count to be spawned
MONSTER_COUNT = 6 MONSTER_COUNT = 8
class Enums(Enum): class Enums(Enum):

View File

@@ -57,7 +57,6 @@ class Game(arcade.Window):
# Used to keep track of our scrolling # Used to keep track of our scrolling
self.view_bottom = self.view_left = 0 self.view_bottom = self.view_left = 0
self.Recipe = [] self.Recipe = []
self.enemies_in_range = []
arcade.set_background_color(arcade.color.BLACK) arcade.set_background_color(arcade.color.BLACK)
@@ -80,12 +79,11 @@ class Game(arcade.Window):
level = random.choice(self.dungeon.levelList) level = random.choice(self.dungeon.levelList)
self.player.center_x, self.player.center_y = level.center() self.player.center_x, self.player.center_y = level.center()
self.player.cur_recipe = self.Recipe.active 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 # Set up monsters
self.Mobs = MobHandler() self.Mobs = MobHandler()
self.enemy_list = self.Mobs.setup(Config.MONSTER_COUNT, Config.MONSTER_COUNT, self.player, self.dungeon) 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 # Setup viewport
self.view_bottom = self.player.center_x - (0.5 * Config.SCREEN_WIDTH) + 300 self.view_bottom = self.player.center_x - (0.5 * Config.SCREEN_WIDTH) + 300
@@ -103,9 +101,8 @@ class Game(arcade.Window):
# Draw our sprites # Draw our sprites
self.dungeon.render() self.dungeon.render()
self.player.draw()
self.Mobs.render() self.Mobs.render()
self.active_enemies.draw() #self.active_enemies.draw()
self.bullet_list.draw() self.bullet_list.draw()
self.Recipe.render() self.Recipe.render()
@@ -237,7 +234,7 @@ class Game(arcade.Window):
# Collision Checks # Collision Checks
hit_list = arcade.check_for_collision_with_list(bullet, self.dungeon.getWalls()) 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 it did, get rid of the bullet
if len(hit_list) > 0: if len(hit_list) > 0:
bullet.remove_from_sprite_lists() bullet.remove_from_sprite_lists()

View File

@@ -10,7 +10,7 @@ import json
from pprint import pprint from pprint import pprint
import arcade import arcade
import numpy as np import random
from itertools import chain from itertools import chain
from config import Config 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) 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 Returns a random spot in the level.
:param times_rotated: :return: A tuple containing the X and Y coordinates
:return:
""" """
m = np.array(self.level)
for i in range(0, times_rotated % 4): return int((self.x + random.randint(1,9)/10) * Config.LEVEL_SIZE), int((self.y + random.randint(1,9)/10) * Config.LEVEL_SIZE)
m = np.rot90(m)
self.level = m.tolist()

View File

@@ -13,60 +13,85 @@ from config import Config, Enums, SpritePaths
from map import Dungeon from map import Dungeon
from sprites import PlayerAnimations from sprites import PlayerAnimations
class MobHandler(arcade.SpriteList): class MobHandler:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.enemy_list = [] self.enemy_list = []
self.active_enemies = [] self.avoid_list = []
self.dungeon = None self.dungeon = None
self.player = None self.player = None
def setup(self, ghost, frogs, player, dungeon) -> list: def setup(self, ghost, frogs, player, dungeon) -> list:
self.enemy_list = arcade.SpriteList() self.enemy_list = arcade.SpriteList()
self.active_enemies = arcade.SpriteList()
self.dungeon = dungeon self.dungeon = dungeon
self.player = player 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): for count in range(ghost):
mob = Enemy(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() level = random.choice(self.dungeon.levelList)
mob.center_x, mob.center_y = level.random()
mob.target = self.player mob.target = self.player
mob.scale = 4 mob.scale = 4
mob.monster_type = 'ghost' 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.enemy_list.append(mob)
self.avoid_list.append(mob)
for count in range(frogs): for count in range(frogs):
mob = Enemy(filename="resources/images/monsters/frog/frog1.png", dungeon=self.dungeon) 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.target = self.player
mob.scale = 4 mob.scale = 4
mob.monster_type = 'frog' 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.enemy_list.append(mob)
self.avoid_list.append(mob)
return self.enemy_list return self.enemy_list
def render(self) -> None: def render(self) -> None:
self.player.draw()
self.enemy_list.draw() self.enemy_list.draw()
def update(self) -> None: def update(self) -> None:
#update player #update player
self.player.monster_collisions.update() self.player.collisions.update()
self.player.update_animation() self.player.update_animation()
# Enemy activation and update # Enemy activation and update
for enemy in reversed(self.enemy_list): for enemy in reversed(self.enemy_list):
# TODO replace with distance checking # TODO replace with distance checking
distance = self.get_distance(enemy) distance = self.get_distance(enemy)
enemy.collisions.update()
if (distance < 300): if (distance < 300):
self.active_enemies.append(enemy) enemy.speed = Config.MONSTER_MOVEMENT_SPEED
self.enemy_list.remove(enemy)
enemy.active = True
try: try:
for enemy in self.active_enemies: path = enemy.get_path(enemy.target.position)
enemy.monster_collisions.update() enemy.tick(path)
path = enemy.get_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) enemy.tick(path)
except Exception: except Exception:
import traceback import traceback
@@ -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)) distance = math.sqrt(math.pow(start_x - end_x, 2) + math.pow(start_y - end_y, 2))
return distance 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): class Mob(arcade.Sprite):
""" """
@@ -97,10 +136,10 @@ class Mob(arcade.Sprite):
self.up_textures = [] self.up_textures = []
self.down_textures = [] self.down_textures = []
self.cur_texture = 0 self.cur_texture = 0
self.monster_collisions = None self.collisions = None
self.dungeon = dungeon self.dungeon = dungeon
self.target = None self.target = None
self.collisions = None self.level = None
class Player(Mob): class Player(Mob):
@@ -127,6 +166,7 @@ class Player(Mob):
self.texture = next(self.map[self.prev]) self.texture = next(self.map[self.prev])
self.kill_list = [] self.kill_list = []
self.cur_recipe = None self.cur_recipe = None
self.speed = 14
def add_kill(self, creature): 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. # 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): class Enemy(Mob):
""" """
Represents an Enemy Mob. Represents an Enemy Mob.
@@ -187,7 +225,6 @@ class Enemy(Mob):
def __init__(self, *args, **kwargs) -> None: def __init__(self, *args, **kwargs) -> None:
super(Enemy, self).__init__(*args, **kwargs) super(Enemy, self).__init__(*args, **kwargs)
self.monster_type = '' self.monster_type = ''
self.active = False
def nearestPosition(self) -> Tuple[int, int]: 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. A on_update function, the Mob should decide it's next actions here.
""" """
near_pos = self.nearestPosition()
curpos, nextpos = self.nearestPosition(), path[1] curpos, nextpos = near_pos, path[1]
# print(curpos, nextpos) # print(curpos, nextpos)
if nextpos[0] > curpos[0]: if nextpos[0] > curpos[0]:
self.change_x = Config.PLAYER_MOVEMENT_SPEED - 3 self.change_x = self.speed
elif nextpos[0] < curpos[0]: elif nextpos[0] < curpos[0]:
self.change_x = -Config.PLAYER_MOVEMENT_SPEED + 3 self.change_x = -self.speed
else: else:
self.change_x = 0 self.change_x = 0
if nextpos[1] > curpos[1]: if nextpos[1] > curpos[1]:
self.change_y = Config.PLAYER_MOVEMENT_SPEED - 3 self.change_y = self.speed
elif nextpos[1] < curpos[1]: elif nextpos[1] < curpos[1]:
self.change_y = -Config.PLAYER_MOVEMENT_SPEED + 3 self.change_y = -self.speed
else: else:
self.change_y = 0 self.change_y = 0
# print(self.change_x, self.change_y)
def get_path(self, end: Tuple[int, int] = None) -> List[Tuple[int, int]]: def get_path(self, end: Tuple[int, int] = None) -> List[Tuple[int, int]]:
""" """
@@ -229,8 +267,7 @@ class Enemy(Mob):
:param end: A the endpoint tuple. Must be a valid position within the matrix. :param end: A the endpoint tuple. Must be a valid position within the matrix.
:return: :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.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) start, end = self.dungeon.grid.node(*start), self.dungeon.grid.node(*end)
paths, runs = self.dungeon.finder.find_path(start, end, self.dungeon.grid) paths, runs = self.dungeon.finder.find_path(start, end, self.dungeon.grid)