diff --git a/Constants/Game.py b/Constants/Game.py index 9ee235b..d6a99e4 100644 --- a/Constants/Game.py +++ b/Constants/Game.py @@ -43,3 +43,6 @@ # How close the player needs to be for the enemy to track it. # starts to break above 15 ENEMY_AWARENESS = 40 + +# How often in should a star be ran +PATHING_RATE = 1.0 \ No newline at end of file diff --git a/Core/Character.py b/Core/Character.py index 1d31f89..8590aeb 100644 --- a/Core/Character.py +++ b/Core/Character.py @@ -1,7 +1,5 @@ import arcade -import math -from Constants.Physics import PLAYER_MOVEMENT_SPEED from Constants.Game import ( SPRITE_SCALING_PLAYER, DOWN_FACING, @@ -11,13 +9,11 @@ SPRITE_SIZE) from Constants.Animation import WALK_CYCLE_LENGTH, IDLE_CYCLE_LENGTH -# from Core.Projectiles.Projectile_Manager import angle - class Character(arcade.Sprite): """ Player Sprite""" - def __init__(self, position): + def __init__(self, main_path=''): # Set up parent class super().__init__() @@ -40,17 +36,11 @@ def __init__(self, position): # --- Load Textures --- - self.main_path = '' + self.main_path = main_path # Set the initial texture self.texture = None - grid_x = 20 - grid_y = 25 - self.center_x = SPRITE_SIZE * grid_x + SPRITE_SIZE / 2 - self.center_y = SPRITE_SIZE * grid_y + SPRITE_SIZE / 2 - - self.position = position def load_textures(self): # Load textures for idle standing diff --git a/Core/Enemy.py b/Core/Enemy.py index b06cdb4..39e36bc 100644 --- a/Core/Enemy.py +++ b/Core/Enemy.py @@ -1,41 +1,45 @@ -from typing import List, Union - -import arcade import random +import arcade from arcade import SpriteList +from typing import List, Union -from Constants.Game import SPRITE_SIZE, SPRITE_SCALING_PLAYER, ENEMY_AWARENESS +from Constants.Game import ENEMY_AWARENESS, PATHING_RATE, SPRITE_SIZE from Constants.Physics import PLAYER_MOVEMENT_SPEED +from Core.Character import Character - -class Enemy(arcade.Sprite): +class Enemy(Character): def __init__(self, barrier_list, game_resources): - super().__init__( - "Graphics/Character_animation/monsters_idle/skeleton1/v1/skeleton_v1_1.png", - SPRITE_SCALING_PLAYER, - ) + super().__init__() + self.randomize_enemy_sprite() + self.load_textures() self.game_resources = game_resources self.speed = PLAYER_MOVEMENT_SPEED - self.path = [ - self.game_resources.player_sprite.center_x, - self.game_resources.player_sprite.center_y, - ] + self.path = [] self.obstacles = self.game_resources.wall_list self.barrier_list = barrier_list - self.light = game_resources.game_instance.scene_renderer.light_renderer.create_point_light( + self.light = game_resources.scene_renderer.light_renderer.create_point_light( (-1000, -1000), (1.5, 0.5, 0.25), 196 ) - self.barrier_list = barrier_list + + def randomize_enemy_sprite(self): + sprites = [ + "Graphics/Character_animation/monsters_idle/vampire/v2/vampire_v2", + "Graphics/Character_animation/monsters_idle/skull/v2/skull_v2", + "Graphics/Character_animation/monsters_idle/skeleton2/v2/skeleton2_v2", + "Graphics/Character_animation/monsters_idle/skeleton1/v2/skeleton_v2", + ] + choice = random.choice(sprites) + self.main_path = choice def draw(self): if self.path: arcade.draw_line_strip(self.path, arcade.color.BLUE, 2) def on_death(self): - self.game_resources.game_instance.scene_renderer.light_renderer.destroy_light(self.light) + self.game_resources.scene_renderer.light_renderer.destroy_light(self.light) def calculate_astar(self): @@ -74,6 +78,10 @@ def update_position(self): physics_engine.apply_impulse(self, impulse_force) self.light.position = (self.center_x, self.center_y) + def on_update(self, delta_time): + self.update_position() + self.update_animation(delta_time) + class EnemyManager: enemy_list: Union[SpriteList, List[Enemy]] @@ -81,6 +89,8 @@ class EnemyManager: def __init__(self, game_resources): self.game_resources = game_resources self.enemy_list = arcade.SpriteList() + self.next_to_path = 0 + self.time_elapsed = 0 def spawn_enemy(self, barrier_list, position): # Enemy @@ -94,9 +104,25 @@ def spawn_enemy(self, barrier_list, position): return enemy + def spawn_random_enemy(self): + radius = self.game_resources.player_sprite.player_health.max_light_radius + player_pos = self.game_resources.player_sprite.position + + rand_x = random.randint(int(player_pos[0]-radius), int(player_pos[0]+radius)) + rand_y = random.randint(int(player_pos[1] - radius), int(player_pos[1] + radius)) + enemy = self.spawn_enemy(self.make_barrier_list(), (player_pos[0]+100, player_pos[1]+100)) + self.game_resources.projectile_manager.add_enemy(enemy) + #for floor in self.game_resources.floor_list: + # if floor.position[0] < rand_x + 100 and floor.position[0] > rand_x - 100 and floor.position[1] < rand_x + 100 and floor.position[1] > rand_x - 100: + # self.spawn_enemy(self.make_barrier_list(), floor.position) + + def spawn_continual_enemies(self): + if len(self.enemy_list) < 5: + self.spawn_random_enemy() + def make_barrier_list(self): grid_size = SPRITE_SIZE - + print() playing_field_left_boundary = self.game_resources.player_sprite.position[0] - ( ENEMY_AWARENESS * SPRITE_SIZE ) @@ -129,8 +155,18 @@ def setup(self): def on_update(self, delta_time): + # move enemies for enemy in self.enemy_list: position = self.game_resources.player_sprite.position if arcade.get_distance(position[0], position[1], enemy.position[0], enemy.position[1]) < 500: - enemy.calculate_astar() - enemy.update_position() + enemy.on_update(delta_time) + + # path the next enemy in line + if self.time_elapsed >= PATHING_RATE: + if self.next_to_path < len(self.enemy_list): + self.enemy_list[self.next_to_path].calculate_astar() + self.next_to_path += 1 + else: + self.next_to_path = 0 + + self.time_elapsed += delta_time \ No newline at end of file diff --git a/Core/GameInstance.py b/Core/GameInstance.py index 6333b19..5d8aba6 100644 --- a/Core/GameInstance.py +++ b/Core/GameInstance.py @@ -1,15 +1,5 @@ - -import arcade -import math import arcade -from Constants.Game import SCREEN_WIDTH, SCREEN_HEIGHT -from Core.GameResources import GameResources -import ctypes -import platform -import subprocess - -from Constants.Physics import PLAYER_MOVEMENT_SPEED from Constants.Game import SCREEN_WIDTH, SCREEN_HEIGHT from Core.GameResources import GameResources @@ -34,40 +24,7 @@ def __init__(self, window): # This configures the post processing stack and default lighting self.scene_renderer = RendererFactory.create_renderer(window) - # Core game resources - self.game_resources = GameResources(self) - self.object_manager = ObjectManager(self.game_resources, self) - - self.screensize = 1920,1080 - - # Fullscreen information get based on OS - if platform.system() == 'Linux': - print("This game expects linux users to be using a 1080p, 16:9 monitor. Other aspect ratios or resolutions on linux may cause issues.") - """ - cmd = ['xrandr'] - cmd2 = ['grep', '*'] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE) - p2 = subprocess.Popen(cmd2, stdin=p.stdout, stdout=subprocess.PIPE) - p.stdout.close() - resolution_string, junk = p2.communicate() - resolution = resolution_string.split()[0] - width, height = resolution.split('x') - self.screensize[0] = width - self.screensize[1] = height - """ - self.screensize = (1920, 1080) - elif platform.system() == 'Windows': - user32 = ctypes.windll.user32 - self.screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1) - - # Physics engine - self.physics_engine = setup_physics_engine(self.game_resources) - - self.horizontal_key_list = [] - self.verticle_key_list = [] - - - + self.screensize = arcade.get_display_size() # bind rendering callbacks self.scene_renderer.draw_primary_callback = self.on_draw_scene @@ -86,21 +43,11 @@ def __init__(self, window): ) # dim the ambient lighting to make the player's light more vibrant - self.scene_renderer.light_renderer.ambient_light = (0.2, 0.2, 0.2) + self.scene_renderer.light_renderer.ambient_light = (0.1, 0.1, 0.1) #self.scene_renderer.light_renderer.ambient_light = (0.01, 0.01, 0.01) # Core game resources - self.game_resources = GameResources(self) - self.object_manager = ObjectManager(self.game_resources, self) - - # Physics engine - self.physics_engine = setup_physics_engine(self.game_resources) - - # create light sources - self.light_list = [] - - - + self.game_resources = GameResources(self.scene_renderer) # torch particle system self.torch_particle_system = TorchSystem(window.ctx) @@ -120,17 +67,15 @@ def __init__(self, window): for light in self.game_resources.light_list: radius = radius_by_type.get(light.properties["type"]) - self.light_list.append( - self.scene_renderer.light_renderer.create_point_light( - (light.center_x, light.center_y), # Position - ( - 2.5, - 1.25, - 0.5, - ), # Color, 0 = black, 1 = white, 0.5 = grey, order is RGB This can go over 1.0 because of HDR - radius, - ) # Radius - ) + self.scene_renderer.light_renderer.create_point_light( + (light.center_x, light.center_y), # Position + ( + 2.5, + 1.25, + 0.5, + ), # Color, 0 = black, 1 = white, 0.5 = grey, order is RGB This can go over 1.0 because of HDR + radius, + ) # Radius if light.properties["type"] == "torch": self.torch_particle_system.add_torch((light.center_x, light.center_y)) @@ -194,22 +139,4 @@ def on_draw_after_post(self): def on_update(self, delta_time): """ Movement and game logic """ - - x_force = self.game_resources.player_sprite.x_force - y_force = self.game_resources.player_sprite.y_force - self.game_resources.player_sprite.on_update(delta_time) - self.game_resources.projectile_manager.projectile_physics.apply_impulse(self.game_resources.player_sprite, (x_force, y_force)) - - # Move the player with the physics engine - # self.physics_engine.update() - - self.game_resources.enemy_manager.on_update(delta_time) - - # move projectiles - self.game_resources.projectile_manager.on_update(delta_time) - - - # update animations - self.game_resources.player_sprite.update_animation(delta_time) - self.game_resources.object_manager.on_update(delta_time) self.game_resources.on_update(delta_time) diff --git a/Core/GameResources.py b/Core/GameResources.py index 44ae514..b4cec43 100644 --- a/Core/GameResources.py +++ b/Core/GameResources.py @@ -9,11 +9,12 @@ from Core.Enemy import EnemyManager from Constants.Game import ( SPRITE_SCALING_TILES, + SPRITE_SCALING_PLAYER, SPRITE_SIZE, SCREEN_WIDTH, SCREEN_HEIGHT, LERP_MARGIN, - CAMERA_SPEED + CAMERA_SPEED, ) from Core.ArcadeUtils import convert_from_tiled_coordinates from Core.LevelGenerator.generate_game_level import generate_game_level @@ -27,9 +28,9 @@ class GameResources: Load arcade resources """ - def __init__(self, game_instance): + def __init__(self, scene_renderer): - self.game_instance = game_instance + self.scene_renderer = scene_renderer # Create the sprite lists self.sprite_list = arcade.SpriteList(use_spatial_hash=True) self.player_list = arcade.SpriteList() @@ -59,14 +60,7 @@ def __init__(self, game_instance): self.dead = False - # Static map for testing - # generated_map = generate_tiled_compatible_level(70, 70) - # place_room(Rect(1, 1, 5, 5), generated_map) - # place_room(Rect(10, 1, 10, 10), generated_map) - # place_room(Rect(1, 10, 8, 8), generated_map) - # place_tunnel(Rect(6, 3, 5, 1), generated_map) - # place_tunnel(Rect(3, 6, 1, 5), generated_map) - + ''' fake_walls_layer = TileLayer( id_=1, name="Walls", @@ -109,7 +103,7 @@ def __init__(self, game_instance): self.warps_list = arcade.tilemap._process_object_layer( my_map, fake_warps_layer, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True ) - + self.doors_enabled = False if "Doors" in generated_map: @@ -124,42 +118,62 @@ def __init__(self, game_instance): self.doors_list = arcade.tilemap._process_object_layer( my_map, fake_doors_layer, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True ) + self.wall_list = arcade.tilemap._process_tile_layer( - my_map, fake_walls_layer, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True + my_map, self.wall_list, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True ) self.light_list = arcade.tilemap._process_tile_layer( - my_map, fake_lighting_layer, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True + my_map, self.light_list, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True ) self.floor_list = arcade.tilemap._process_tile_layer( - my_map, fake_floor_layer, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True + my_map, self.floor_list, scaling=SPRITE_SCALING_TILES, use_spatial_hash=True ) - # Uncomment if you want to actually load the level from the Tiled map. - # self.wall_list = arcade.tilemap.process_layer( - # my_map, "Walls", SPRITE_SCALING_TILES - # ) - # self.floor_list = arcade.tilemap.process_layer( - # my_map, "Floor", SPRITE_SCALING_TILES - # ) - # self.light_list = arcade.tilemap.process_layer( - # my_map, "Lighting", SPRITE_SCALING_TILES - # ) - self.start_location = generated_map["start_location"][0].location # Create player sprite - self.player_sprite = PlayerCharacter(convert_from_tiled_coordinates(my_map, generated_map["start_location"][0].location), self, game_instance.scene_renderer) + #self.player_sprite = PlayerCharacter(convert_from_tiled_coordinates(my_map, generated_map["start_location"][0].location), self, self.scene_renderer) + + self.player_sprite = PlayerCharacter( + (5,5), self, + self.scene_renderer) # Set player location i = random.randint(0, len(self.floor_list)) start_pos = self.floor_list[i].position + # Add to player sprite list + self.player_list.append(self.player_sprite) + ''' + # Read in the tiled map + map_name = "Graphics/test_map.tmx" + my_map = arcade.tilemap.read_tmx(map_name) + self.wall_list = arcade.tilemap.process_layer( + my_map, "Walls", SPRITE_SCALING_TILES + ) + self.floor_list = arcade.tilemap.process_layer( + my_map, "Floor", SPRITE_SCALING_TILES + ) + self.light_list = arcade.tilemap.process_layer( + my_map, "Lighting", SPRITE_SCALING_TILES + ) + + # Create player sprite + self.player_sprite = PlayerCharacter( + (5, 5), self, + self.scene_renderer) + + # Set player location + grid_x = 10 + grid_y = 5 + self.player_sprite.center_x = SPRITE_SIZE * grid_x + SPRITE_SIZE / 2 + self.player_sprite.center_y = SPRITE_SIZE * grid_y + SPRITE_SIZE / 2 # Add to player sprite list self.player_list.append(self.player_sprite) # Game managers - self.object_manager = ObjectManager(self, game_instance) + self.object_manager = ObjectManager(self, scene_renderer) self.enemy_manager = EnemyManager(self) self.enemy_manager.setup() self.projectile_manager = ProjectileManager(self) @@ -176,15 +190,33 @@ def on_draw(self): self.wall_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) self.floor_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) self.light_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) + ''' self.warps_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) if self.doors_enabled: self.doors_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) + ''' self.bullet_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) self.player_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) self.object_manager.object_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) self.enemy_manager.enemy_list.draw(filter=(arcade.gl.NEAREST, arcade.gl.NEAREST)) def on_update(self, delta_time): + + x_force = self.player_sprite.x_force + y_force = self.player_sprite.y_force + self.player_sprite.on_update(delta_time) + self.enemy_manager.on_update(delta_time) + + self.projectile_manager.projectile_physics.apply_impulse(self.player_sprite, + (x_force, y_force)) + + # move projectiles + self.projectile_manager.on_update(delta_time) + + # update animations + self.player_sprite.update_animation(delta_time) + self.object_manager.on_update(delta_time) + if self.shake_remain > 0: self.shake_x = random.randrange(-self.shake_strength,self.shake_strength) self.shake_y = random.randrange(-self.shake_strength,self.shake_strength) diff --git a/Core/ObjectManager.py b/Core/ObjectManager.py index 62671a2..c2f842a 100644 --- a/Core/ObjectManager.py +++ b/Core/ObjectManager.py @@ -5,27 +5,26 @@ class ObjectManager: """ Creates objects in the dungeon. """ - def __init__(self, game_resources, game_instance): + def __init__(self, game_resources, scene_renderer): self.object_list = arcade.SpriteList() self.game_resources = game_resources - self.game_instance = game_instance - - - #for floor in + self.scene_renderer = scene_renderer def flask(self, x, y): obj = Item((x, y), 'Graphics/items/flasks/flasks_1', 'flask') self.object_list.append(obj) + return obj def candle_drop(self, x, y): obj = Item((x, y), 'Graphics/items/torch/candle_drop','candle_drop') self.object_list.append(obj) + return obj def candle(self, x, y): obj = Item((x, y), 'Graphics/items/torch/candlestick_1', 'candle') self.object_list.append(obj) self.game_resources.torch_particle_system.add_candle((x,y)) - self.game_instance.scene_renderer.light_renderer.create_point_light( + self.scene_renderer.light_renderer.create_point_light( (x,y), # Position ( 2.5, @@ -45,7 +44,8 @@ def on_update(self, delta_time): class Item(Character): def __init__(self, position, main_path, kind): - super().__init__(position) + super().__init__() + self.position = position self.main_path = main_path self.load_textures() self.kind = kind \ No newline at end of file diff --git a/Core/PlayerCharacter.py b/Core/PlayerCharacter.py index 77ad702..62ad428 100644 --- a/Core/PlayerCharacter.py +++ b/Core/PlayerCharacter.py @@ -23,7 +23,8 @@ class PlayerCharacter(Character): def __init__(self, position, game_resources, scene_renderer): # Set up parent class - super().__init__(position) + super().__init__() + self.position = position self.game_resources = game_resources self.main_path = "Graphics/Character_animation/Acolyte/player_animation_down_idle" self.load_textures() @@ -37,7 +38,7 @@ def __init__(self, position, game_resources, scene_renderer): self.y_force = 0 self.speed = 40 - self.candles = 0 + self.candles = 5 self.walk_textures = [] walk_path = 'Graphics/Character_animation/Acolyte/player_animation_down_walk' diff --git a/Core/Projectile_Manager.py b/Core/Projectile_Manager.py index ea8248f..3573a00 100644 --- a/Core/Projectile_Manager.py +++ b/Core/Projectile_Manager.py @@ -49,12 +49,13 @@ def __init__(self, game_resources): max_vertical_velocity=1200, body_type=arcade.PymunkPhysicsEngine.DYNAMIC ) - + ''' self.projectile_physics.add_sprite_list( self.game_resources.warps_list, collision_type="warp", body_type=arcade.PymunkPhysicsEngine.STATIC, ) + ''' self.explosion_sounds = [ SoundPool("Sounds/explosion.wav", 5, 0.2), @@ -195,17 +196,19 @@ def enemy_bullet_handler(_arbiter, _space, _data): enemy_sprite.remove_from_sprite_lists() will_drop = random.randint(0, 10) + obj = '' if will_drop > 6: - self.game_resources.object_manager.flask(enemy_sprite.center_x, enemy_sprite.center_y) + obj = self.game_resources.object_manager.flask(enemy_sprite.center_x, enemy_sprite.center_y) elif will_drop > 3: - self.game_resources.object_manager.candle_drop(enemy_sprite.center_x, enemy_sprite.center_y) - self.game_resources.object_manager.object_list - self.projectile_physics.add_sprite_list( - self.game_resources.object_manager.object_list, + obj = self.game_resources.object_manager.candle_drop(enemy_sprite.center_x, enemy_sprite.center_y) + + if obj != '': + self.projectile_physics.add_sprite( + obj, collision_type="object", body_type=arcade.PymunkPhysicsEngine.STATIC, - ) + ) enemy_sprite.on_death() if bullet_sprite: @@ -229,12 +232,14 @@ def enemy_bullet_handler(_arbiter, _space, _data): handler = self.projectile_physics.space.add_collision_handler(bullet_physics_id, enemy_physics_id) handler.begin = enemy_bullet_handler + ''' self.projectile_physics.add_sprite_list( self.game_resources.doors_list, collision_type="door", friction=1.0, body_type=arcade.PymunkPhysicsEngine.STATIC, ) + ''' def door_player_handler(_arbiter, _space, _data): door_sprite, player_sprite = self.projectile_physics.get_sprites_from_arbiter(_arbiter)