diff --git a/.gitignore b/.gitignore index 39666b5..813169c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ checkpoint.db-journal game.db map/infinite/* -temp_audio.mp3 \ No newline at end of file +temp_audio.mp3 +output.prof + +**/*.pyc \ No newline at end of file diff --git a/assets/map/platform/stone_texture.png b/assets/map/platform/stone_texture.png index 579595a..f35817d 100644 Binary files a/assets/map/platform/stone_texture.png and b/assets/map/platform/stone_texture.png differ diff --git a/assets/sound/main_music.mp3 b/assets/sound/main_music.mp3 new file mode 100644 index 0000000..231d0b9 Binary files /dev/null and b/assets/sound/main_music.mp3 differ diff --git a/map/levels/1.json b/map/levels/1.json index 65484ac..e0f1904 100644 --- a/map/levels/1.json +++ b/map/levels/1.json @@ -224,9 +224,9 @@ { "id": "checkpoint1", "x": 2200, - "y": 700, + "y": 600, "width": 50, - "height": 50, + "height": 125, "sprite": "assets/map/checkpoints/checkpoint.png" } ], diff --git a/map/levels/2.json b/map/levels/2.json index 17b1c72..91c06a9 100644 --- a/map/levels/2.json +++ b/map/levels/2.json @@ -1,189 +1,456 @@ { "name": "Level 2", - "width": 2400, - "height": 800, + "width": 10500, + "height": 1500, "background": "assets/map/background/forest_bg.jpg", "gravity": 1.0, "platforms": [ { - "id": "platform1", + "id": "main_ground", "x": -1000, - "y": 520, - "width": 1800, + "y": 800, + "width": 1700, "height": 200, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false + "texture": "assets/map/platform/grass_texture.png" }, { - "id": "platform2", + "id": "platform1_01", "x": 1000, - "y": 600, - "width": 1800, - "height": 200, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false - }, - { - "id": "platform3", - "x": 300, - "y": 570, - "width": 200, - "height": 20, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false - }, - { - "id": "platform4", - "x": 700, - "y": 470, - "width": 150, - "height": 20, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false - }, - { - "id": "platform5", - "x": 900, - "y": 470, - "width": 150, - "height": 20, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false - }, - { - "id": "platform6", - "x": 1200, - "y": 370, + "y": 700, "width": 100, "height": 20, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false + "texture": "assets/map/platform/wood_texture.png", + "is_moving": true, + "movement": { + "type": "circular", + "center": {"x": 1000, "y": 700}, + "radius": 2, + "speed": 0.02, + "clockwise": true + } }, { - "id": "platform7", - "x": 300, - "y": 240, - "width": 260, - "height": 40, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false + "id": "platform1_02", + "x": 1300, + "y": 700, + "width": 200, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": true, + "movement": { + "type": "linear", + "points": [ + {"x": 1300, "y": 700}, + {"x": 1800, "y": 700} + ], + "speed": 3.0, + "wait_time": 1.0 + } }, { - "id": "platform8", - "x": 720, - "y": 220, - "width": 240, - "height": 60, - "texture": "assets/map/platform/grass_texture.png", - "is_moving": false + "id": "platform1_03", + "x": 2100, + "y": 700, + "width": 100, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": true, + "movement": { + "type": "linear", + "points": [ + {"x": 2100, "y": 100}, + {"x": 2100, "y": 700} + ], + "speed": 2.0, + "wait_time": 1.0 + } }, { - "id": "platform9", - "x": 520, + "id": "main_ground_2", + "x": 2300, + "y": 200, + "width": 1000, + "height": 200, + "texture": "assets/map/platform/stone_texture.png" + }, + { + "id": "platform2_01", + "x": 2500, "y": 0, - "width": 240, - "height": 60, - "texture": "assets/map/platform/grass_texture.png", + "width": 100, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", "is_moving": false + }, + { + "id": "platform2_02", + "x": 3400, + "y": 100, + "width": 200, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "platform2_03", + "x": 3600, + "y": 300, + "width": 200, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "main_ground_3", + "x": 3700, + "y": 600, + "width": 1000, + "height": 200, + "texture": "assets/map/platform/stone_texture.png" + }, + { + "id": "platform3_01", + "x": 4800, + "y": 600, + "width": 200, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": true, + "movement": { + "type": "linear", + "points": [ + {"x": 4800, "y": 600}, + {"x": 4800, "y": 1100} + ], + "speed": 2.0, + "wait_time": 1.0 + } + }, + { + "id": "platform3_02", + "x": 5100, + "y": 1200, + "width": 500, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "main_ground_4", + "x": 5700, + "y": 1200, + "width": 900, + "height": 200, + "texture": "assets/map/platform/stone_texture.png" + }, + { + "id": "platform4_01", + "x": 5900, + "y": 1000, + "width": 100, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "platform4_02", + "x": 6000, + "y": 900, + "width": 100, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "platform4_03", + "x": 6700, + "y": 1300, + "width": 200, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": true, + "movement": { + "type": "linear", + "points": [ + {"x": 6700, "y": 1300}, + {"x": 7300, "y": 1300} + ], + "speed": 3.0, + "wait_time": 1.0 + } + }, + { + "id": "platform4_04", + "x": 7600, + "y": 1150, + "width": 200, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "main_ground_5", + "x": 7900, + "y": 1200, + "width": 700, + "height": 200, + "texture": "assets/map/platform/stone_texture.png" + }, + { + "id": "platform5_01", + "x": 8900, + "y": 1200, + "width": 300, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": false + }, + { + "id": "platform5_02", + "x": 9500, + "y": 1200, + "width": 100, + "height": 20, + "texture": "assets/map/platform/wood_texture.png", + "is_moving": true, + "movement": { + "type": "circular", + "center": {"x": 9500, "y": 1200}, + "radius": 2, + "speed": 0.02, + "clockwise": true + } + }, + { + "id": "main_ground_6", + "x": 9800, + "y": 1300, + "width": 700, + "height": 200, + "texture": "assets/map/platform/stone_texture.png" } ], + "enemies": [ { - "id": "enemy1", - "type": "turret", - "x": 260, - "y": 100, - "health": 1, - "damage": 1, - "sprite_sheet": "assets/map/enemy/turret.gif", - "size": [ - 50, - 100 - ], - "behavior": "stationary", - "attack_interval": 2.0, - "attack_range": 300 - }, - { - "id": "enemy2", + "id": "enemy1_01", "type": "walker", - "x": 770, - "y": 140, + "x": 300, + "y": 700, "health": 1, "damage": 1, - "sprite_sheet": "assets/map/enemy/walker_enemy.png", - "size": [ - 50, - 100 - ], "behavior": "patrol", "patrol_points": [ - { - "x": 670, - "y": 140 - }, - { - "x": 870, - "y": 140 - } + {"x": 300, "y": 700}, + {"x": 600, "y": 700} ], - "speed": 1.5 + "speed": 1.5, + "sprite_sheet": "assets/map/enemy/walker_enemy.png", + "size": [50,50] }, { - "id": "enemy3", + "id": "enemy2_01", "type": "flyer", - "x": 420, - "y": 520, + "x": 1600, + "y": 600, "health": 1, "damage": 1, - "sprite_sheet": "assets/map/enemy/flying_enemy.png", - "size": [ - 50, - 100 - ], "behavior": "chase", "detection_radius": 200, - "speed": 2.0 - } - ], - "checkpoints": [ + "speed": 2.0, + "sprite_sheet": "assets/map/enemy/flying_enemy.png", + "size": [50,50] + }, { - "id": "checkpoint1", - "x": 1080, + "id": "enemy1_02", + "type": "turret", + "x": 2900, + "y": 75, + "health": 1, + "damage": 1, + "behavior": "stationary", + "attack_interval": 2.0, + "attack_range": 300, + "sprite_sheet": "assets/map/enemy/turret.gif", + "size": [50,100] + }, + { + "id": "enemy2_02", + "type": "flyer", + "x": 3700, + "y": 200, + "health": 1, + "damage": 1, + "behavior": "chase", + "detection_radius": 200, + "speed": 2.0, + "sprite_sheet": "assets/map/enemy/flying_enemy.png", + "size": [50,50] + }, + { + "id": "enemy1_03", + "type": "walker", + "x": 3800, "y": 450, - "width": 50, - "height": 50, - "sprite": "assets/map/checkpoints/checkpoint_uncheck.png" - } - ], - "exits": [ + "health": 1, + "damage": 1, + "behavior": "patrol", + "patrol_points": [ + {"x": 3800, "y": 450}, + {"x": 4100, "y": 450} + ], + "speed": 1.5, + "sprite_sheet": "assets/map/enemy/walker_enemy.png", + "size": [50,50] + }, { - "x": 2225, - "y": 500, - "width": 50, - "height": 80, - "next_level": "map/levels/1.json", - "sprite": "assets/map/exit/Zeldo.png" + "id": "enemy2_03", + "type": "walker", + "x": 4200, + "y": 450, + "health": 1, + "damage": 1, + "behavior": "patrol", + "patrol_points": [ + {"x": 4200, "y": 450}, + {"x": 4600, "y": 450} + ], + "speed": 1.5, + "sprite_sheet": "assets/map/enemy/walker_enemy.png", + "size": [50,50] + }, + { + "id": "enemy1_04", + "type": "flyer", + "x": 6100, + "y": 800, + "health": 1, + "damage": 1, + "behavior": "chase", + "detection_radius": 200, + "speed": 2.0, + "sprite_sheet": "assets/map/enemy/flying_enemy.png", + "size": [50,50] + }, + { + "id": "enemy2_04", + "type": "turret", + "x": 6300, + "y": 1050, + "health": 1, + "damage": 1, + "behavior": "stationary", + "attack_interval": 2.0, + "attack_range": 300, + "sprite_sheet": "assets/map/enemy/turret.gif", + "size": [50,100] + }, + { + "id": "enemy1_05", + "type": "turret", + "x": 8300, + "y": 1050, + "health": 1, + "damage": 1, + "behavior": "stationary", + "attack_interval": 2.0, + "attack_range": 300, + "sprite_sheet": "assets/map/enemy/turret.gif", + "size": [50,100] + }, + { + "id": "enemy1_06", + "type": "flyer", + "x": 9800, + "y": 1100, + "health": 1, + "damage": 1, + "behavior": "chase", + "detection_radius": 200, + "speed": 2.0, + "sprite_sheet": "assets/map/enemy/flying_enemy.png", + "size": [50,50] + }, + { + "id": "enemy2_06", + "type": "walker", + "x": 9900, + "y": 1200, + "health": 1, + "damage": 1, + "behavior": "patrol", + "patrol_points": [ + {"x": 9900, "y": 1200}, + {"x": 10200, "y": 1200} + ], + "speed": 1.5, + "sprite_sheet": "assets/map/enemy/walker_enemy.png", + "size": [50,50] } ], + "collectibles": [ { - "id": "jump", + "id": "coin1", + "type": "coin", + "x": 2500, + "y": -100, + "sprite": "assets/map/collectibles/Sanic_Coin.png" + }, + { + "id": "coin2", + "type": "coin", + "x": 4600, + "y": 800, + "sprite": "assets/map/collectibles/Sanic_Coin.png" + }, + { + "id": "coin3", + "type": "coin", + "x": 6000, + "y": 800, + "sprite": "assets/map/collectibles/Sanic_Coin.png" + }, + { + "id": "jump1", "type": "jump", - "x": 1500, - "y": 400, + "x": 6500, + "y": 1000, "sprite": "assets/map/collectibles/jump.png" }, { - "id": "speed", + "id": "speed1", "type": "speed", - "x": 1000, - "y": 400, + "x": 8000, + "y": 1000, "sprite": "assets/map/collectibles/speed.png" } ], + + "checkpoints": [ + { + "id": "checkpoint1", + "x": 5300, + "y": 1075, + "width": 50, + "height": 125, + "sprite": "assets/map/checkpoints/checkpoint.png" + } + ], + "spawn_point": { - "x": 50.0, - "y": 350.0 - } + "x": 50, + "y": 650 + }, + + "exits": [ + { + "x": 10450, + "y": 1000, + "width": 50, + "height": 80, + "next_level": "Level 2", + "sprite": "assets/map/exit/Zeldo.png" + } + ] } \ No newline at end of file diff --git a/profiler.py b/profiler.py new file mode 100644 index 0000000..1d04425 --- /dev/null +++ b/profiler.py @@ -0,0 +1,9 @@ +import cProfile +from src.handler import handler + + +def main(): + handler() + + +cProfile.run("main()", "output.prof") diff --git a/src/Database/CheckpointDB.py b/src/Database/CheckpointDB.py index 0c8a317..dce97bc 100644 --- a/src/Database/CheckpointDB.py +++ b/src/Database/CheckpointDB.py @@ -81,3 +81,18 @@ class CheckpointDB: self.conn.commit() except Exception as e: print(f"Error clearing checkpoint database: {e}") + + def reset_level(self, map_name): + """ + Reset the checkpoint for a specific map + + Args: + map_name: Map name to reset + """ + try: + self.cursor.execute( + "DELETE FROM checkpoints WHERE map_name = ?", (map_name,) + ) + self.conn.commit() + except Exception as e: + print(f"Error resetting checkpoint for {map_name}: {e}") diff --git a/src/Entity/Exit.py b/src/Entity/Exit.py index cdbcd48..2463ceb 100644 --- a/src/Entity/Exit.py +++ b/src/Entity/Exit.py @@ -1,4 +1,5 @@ import pygame +import os from src.Entity.Entity import Entity from moviepy import VideoFileClip import moviepy as mp @@ -75,9 +76,16 @@ class Exit(Entity): # Extract audio from the video audio = mp.AudioFileClip(video_path) audio.write_audiofile("temp_audio.mp3") - pygame.mixer.init() - pygame.mixer.music.load("temp_audio.mp3") - pygame.mixer.music.play() + + # Pause the main music without stopping it + main_music_pos = ( + pygame.mixer.music.get_pos() / 1000 if pygame.mixer.get_init() else 0 + ) + pygame.mixer.music.pause() + + # Load and play the audio on a separate channel + temp_sound = pygame.mixer.Sound("temp_audio.mp3") + sound_channel = temp_sound.play() for frame in clip.iter_frames(fps=24, dtype="uint8"): frame_surface = pygame.surfarray.make_surface(frame.swapaxes(0, 1)) @@ -85,11 +93,22 @@ class Exit(Entity): pygame.display.flip() clock.tick(24) - clip.close() - pygame.mixer.music.stop() - pygame.mixer.quit() + # Check if the sound channel is still playing + if sound_channel and not sound_channel.get_busy(): + break - # Create and post a return to menu event + clip.close() + + # Play the main music again from the last position + pygame.mixer.music.unpause() + + # Remove the temporary audio file + try: + os.remove("temp_audio.mp3") + except Exception as e: + print(f"Error removing temporary audio file: {e}") + + # Return to the menu return_event = pygame.event.Event( pygame.USEREVENT, {"action": "return_to_menu"} ) diff --git a/src/Entity/JumpBoost.py b/src/Entity/JumpBoost.py index 1bfb23b..ac90f7d 100644 --- a/src/Entity/JumpBoost.py +++ b/src/Entity/JumpBoost.py @@ -15,8 +15,8 @@ class JumpBoost(Entity): self.collected = False # Jump boost properties - self.boost_factor = 1.5 # 50% increase in jump power - self.boost_duration = 3 # Duration in seconds + self.boost_factor = 1.5 + self.boost_duration = 10 # Create initial surface self.surf = pygame.Surface(size, pygame.SRCALPHA) diff --git a/src/Entity/Player.py b/src/Entity/Player.py index c2ba263..49e5a68 100644 --- a/src/Entity/Player.py +++ b/src/Entity/Player.py @@ -83,7 +83,9 @@ class Player(Entity): self.attack_start_time = 0 self.attack_cooldown = 2000 - # Initialize mixer + self.facing_right = True + + # Initilize mixer pygame.mixer.init() def load_images(self): @@ -209,23 +211,46 @@ class Player(Entity): def update_animation(self): current_time = pygame.time.get_ticks() + current_image = None + # Priority: Dashing > Jumping > Moving > Static - if self.dashing and self.dash_frames: + if self.dashing and self.dash_frames and len(self.dash_frames) > 0: if current_time - self.last_update > self.animation_speed * 1000: self.current_frame = (self.current_frame + 1) % len(self.dash_frames) - self.surf = self.dash_frames[self.current_frame] self.last_update = current_time - elif self.jumping and self.jump_frames: - self.surf = self.jump_frames[0] # Use jump frame - elif self.moving and self.animation_frames: + + if 0 <= self.current_frame < len(self.dash_frames): + current_image = self.dash_frames[self.current_frame] + + elif self.jumping and self.jump_frames and len(self.jump_frames) > 0: + if 0 < len(self.jump_frames): + current_image = self.jump_frames[0] + + elif self.moving and self.animation_frames and len(self.animation_frames) > 0: if current_time - self.last_update > self.animation_speed * 1000: self.current_frame = (self.current_frame + 1) % len( self.animation_frames ) - self.surf = self.animation_frames[self.current_frame] self.last_update = current_time + + if 0 <= self.current_frame < len(self.animation_frames): + current_image = self.animation_frames[self.current_frame] + elif self.static_image: - self.surf = self.static_image + current_image = self.static_image + + # If no animation is found, use the static imagef available + if not current_image: + if self.static_image: + current_image = self.static_image + else: + return + + # Appliquer le retournement selon la direction + if not self.facing_right: + self.surf = pygame.transform.flip(current_image, True, False) + else: + self.surf = current_image def dash(self, acc): current_time = pygame.time.get_ticks() @@ -259,7 +284,7 @@ class Player(Entity): if self.has_joystick and self.joystick: try: - # Joystick gauche pour mouvement + # Left joystick for movement if self.joystick.get_numaxes() > 0: joystick_x = self.joystick.get_axis(0) if abs(joystick_x) > 0.2: @@ -268,7 +293,7 @@ class Player(Entity): elif joystick_x > 0: move_right = True - # Boutons pour sauter/dasher + # Button for jumping and dashing if self.joystick.get_numbuttons() > self.jump_button: if self.joystick.get_button(self.jump_button): jump = True @@ -277,7 +302,7 @@ class Player(Entity): if self.joystick.get_button(self.dash_button): dash_key = True except pygame.error: - pass # Ignorer les erreurs de manette + pass if move_left: # Check if X is > 0 to prevent player from going off screen @@ -405,6 +430,11 @@ class Player(Entity): if fall_distance > 500: self.death() + if self.vel.x > 0: + self.facing_right = True + elif self.vel.x < 0: + self.facing_right = False + def take_damage(self, amount=1): """Reduce life number if not invulnerable""" if not self.invulnerable: @@ -413,7 +443,7 @@ class Player(Entity): if self.lives <= 0: self.death() else: - # Période d'invulnérabilité temporaire + # Temporarily make the player invulnerable self.invulnerable = True self.invulnerable_timer = 0 @@ -432,7 +462,7 @@ class Player(Entity): for i in range(self.max_lives): if i < self.lives: - # Vie active: afficher l'icône normale + # Active life: display the icon surface.blit( self.life_icon, ( @@ -441,9 +471,9 @@ class Player(Entity): ), ) else: - # Vie perdue: afficher l'icône grisée + # Life lost: display a grayscale version of the icon grayscale_icon = self.life_icon.copy() - # Appliquer un filtre gris + # Apply grayscale effect for x in range(grayscale_icon.get_width()): for y in range(grayscale_icon.get_height()): color = grayscale_icon.get_at((x, y)) diff --git a/src/Entity/SpeedBoost.py b/src/Entity/SpeedBoost.py index bbc4714..c171426 100644 --- a/src/Entity/SpeedBoost.py +++ b/src/Entity/SpeedBoost.py @@ -16,7 +16,7 @@ class SpeedBoost(Entity): # Speed boost properties self.boost_factor = 2 - self.boost_duration = 3 + self.boost_duration = 10 # Create initial surface self.surf = pygame.Surface(size, pygame.SRCALPHA) @@ -76,16 +76,16 @@ class SpeedBoost(Entity): Args: player: The player object to apply the boost to - game_ressources: Game resources object containing player speed + game_resources: Game resources object containing player speed """ if not self.collected: self.collected = True # Store original movement speed - original_ACC = game_ressources.ACC + original_ACC = game_resources.ACC # Apply boost effect - game_ressources.ACC *= self.boost_factor + game_resources.ACC *= self.boost_factor # Set visual feedback player.speed_boost_active = True diff --git a/src/Map/parser.py b/src/Map/parser.py index 697d479..9bda5c6 100644 --- a/src/Map/parser.py +++ b/src/Map/parser.py @@ -124,9 +124,7 @@ class MapParser: self.platforms.add(platform) self.all_sprites.add(platform) - # Create collectibles (requires Collectible class implementation) - # In MapParser.create_map_objects() - # In MapParser.create_map_objects() + # Create collectibles if "collectibles" in map_data: for collectible_data in map_data["collectibles"]: if collectible_data["type"] == "coin": @@ -158,11 +156,12 @@ class MapParser: # Create background image if "background" in map_data: + map_width = map_data.get("width", self.game_resources.WIDTH) + map_height = map_data.get("height", self.game_resources.HEIGHT) + if os.path.isfile(map_data["background"]): background = pygame.image.load(map_data["background"]).convert_alpha() - background = pygame.transform.scale( - background, (self.game_resources.WIDTH, self.game_resources.HEIGHT) - ) + background = pygame.transform.scale(background, (map_width, map_height)) self.background = background else: print(f"Background image not found: {map_data['background']}") diff --git a/src/constant.py b/src/constant.py index 06a2c70..38c5ed9 100644 --- a/src/constant.py +++ b/src/constant.py @@ -16,6 +16,12 @@ class GameResources: self.life_icon_width = 50 self.fullscreen = False + try: + icon = pygame.image.load("assets/player/Sanic Head.png") + pygame.display.set_icon(icon) + except Exception as e: + print(f"Erreur lors du chargement de l'icône: {e}") + # Ressources self.platforms = pygame.sprite.Group() self.all_sprites = pygame.sprite.Group() diff --git a/src/game.py b/src/game.py index 4f4989b..183afad 100644 --- a/src/game.py +++ b/src/game.py @@ -27,6 +27,9 @@ def initialize_game(game_resources, map_file="map/levels/1.json"): Returns: tuple: (player, platform, platforms_group, all_sprites, background, checkpoints, exits) """ + checkpointDB = CheckpointDB() + checkpointDB.reset_level(map_file) + checkpointDB.close() parser = MapParser(game_resources) map_objects = parser.load_map(map_file) diff --git a/src/handler.py b/src/handler.py index cb24cbb..f1a5e11 100644 --- a/src/handler.py +++ b/src/handler.py @@ -74,6 +74,13 @@ def initialize_game_resources(): game_resources.WIDTH, game_resources.HEIGHT, game_resources.font, leaderboard_db ) + try: + pygame.mixer.music.load("assets/sound/main_music.mp3") + pygame.mixer.music.set_volume(0.2) + pygame.mixer.music.play(-1) + except Exception as e: + print(f"Error loading main music: {e}") + return ( game_resources, displaysurface, @@ -458,9 +465,7 @@ def draw_playing_state( checkpoint.activate() # Handle exit collisions - result = handle_exits( - P1, exits, game_resources, level_file, speedrun_timer, collectibles - ) + result = handle_exits(P1, exits, game_resources, level_file, speedrun_timer) # Handle collectibles collectibles_hit = pygame.sprite.spritecollide(P1, collectibles, False) @@ -487,9 +492,7 @@ def draw_playing_state( return result -def handle_exits( - P1, exits, game_resources, level_file, speedrun_timer=None, collectibles=[] -): +def handle_exits(P1, exits, game_resources, level_file, speedrun_timer=None): """Handle collisions with level exits""" exits_hit = pygame.sprite.spritecollide(P1, exits, False) if exits else [] for exit in exits_hit: diff --git a/temp_audio.mp3 b/temp_audio.mp3 deleted file mode 100644 index 6577b36..0000000 Binary files a/temp_audio.mp3 and /dev/null differ