mirror of
https://github.com/BreizhHardware/project_sanic.git
synced 2026-01-18 16:47:25 +01:00
5
.gitignore
vendored
5
.gitignore
vendored
@@ -12,4 +12,7 @@ checkpoint.db-journal
|
||||
game.db
|
||||
map/infinite/*
|
||||
|
||||
temp_audio.mp3
|
||||
temp_audio.mp3
|
||||
output.prof
|
||||
|
||||
**/*.pyc
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 51 KiB |
BIN
assets/sound/main_music.mp3
Normal file
BIN
assets/sound/main_music.mp3
Normal file
Binary file not shown.
@@ -224,9 +224,9 @@
|
||||
{
|
||||
"id": "checkpoint1",
|
||||
"x": 2200,
|
||||
"y": 700,
|
||||
"y": 600,
|
||||
"width": 50,
|
||||
"height": 50,
|
||||
"height": 125,
|
||||
"sprite": "assets/map/checkpoints/checkpoint.png"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
9
profiler.py
Normal file
9
profiler.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import cProfile
|
||||
from src.handler import handler
|
||||
|
||||
|
||||
def main():
|
||||
handler()
|
||||
|
||||
|
||||
cProfile.run("main()", "output.prof")
|
||||
@@ -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}")
|
||||
|
||||
@@ -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"}
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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']}")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
BIN
temp_audio.mp3
BIN
temp_audio.mp3
Binary file not shown.
Reference in New Issue
Block a user