mirror of
https://github.com/BreizhHardware/project_sanic.git
synced 2026-01-18 16:47:25 +01:00
Feat(Gamepad Support) - Implement joystick initialization and controls for player movement, jumping, and dashing; enhance input handling for both keyboard and joystick
This commit is contained in:
252
main.py
252
main.py
@@ -54,121 +54,155 @@ def main():
|
||||
clear_checkpoint_database()
|
||||
projectiles = pygame.sprite.Group()
|
||||
|
||||
pygame.joystick.quit()
|
||||
pygame.joystick.init()
|
||||
joysticks = []
|
||||
|
||||
try:
|
||||
for i in range(pygame.joystick.get_count()):
|
||||
joystick = pygame.joystick.Joystick(i)
|
||||
joystick.init()
|
||||
joysticks.append(joystick)
|
||||
print(f"Manette détectée: {joystick.get_name()}")
|
||||
print(f"Nombre de boutons: {joystick.get_numbuttons()}")
|
||||
print(f"Nombre d'axes: {joystick.get_numaxes()}")
|
||||
except pygame.error:
|
||||
print("Erreur lors de l'initialisation des manettes")
|
||||
|
||||
# Main game loop
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == QUIT:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif event.type == KEYDOWN:
|
||||
if event.key == K_ESCAPE:
|
||||
if current_state in [PLAYING, INFINITE]:
|
||||
current_state = MENU
|
||||
else:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif event.key == K_F11:
|
||||
fullscreen = not fullscreen
|
||||
if fullscreen:
|
||||
# Store current window size before going fullscreen
|
||||
ORIGINAL_WIDTH, ORIGINAL_HEIGHT = displaysurface.get_size()
|
||||
displaysurface = pygame.display.set_mode(
|
||||
(0, 0), pygame.FULLSCREEN
|
||||
)
|
||||
else:
|
||||
# Return to windowed mode with previous size
|
||||
displaysurface = pygame.display.set_mode(
|
||||
(ORIGINAL_WIDTH, ORIGINAL_HEIGHT), pygame.RESIZABLE
|
||||
)
|
||||
elif (
|
||||
event.type == VIDEORESIZE
|
||||
): # Fixed indentation - moved out of K_F11 condition
|
||||
if not fullscreen:
|
||||
displaysurface = pygame.display.set_mode(
|
||||
(event.w, event.h), pygame.RESIZABLE
|
||||
)
|
||||
# Update window dimensions
|
||||
ORIGINAL_WIDTH, ORIGINAL_HEIGHT = event.w, event.h
|
||||
elif event.type == USEREVENT:
|
||||
if event.action == "player_death":
|
||||
db = CheckpointDB()
|
||||
checkpoint_pos = db.get_checkpoint(level_file)
|
||||
running = True
|
||||
while running:
|
||||
try:
|
||||
events = []
|
||||
try:
|
||||
events = pygame.event.get()
|
||||
except Exception as e:
|
||||
print(f"Erreur lors de la récupération des événements: {e}")
|
||||
pygame.joystick.quit()
|
||||
pygame.joystick.init()
|
||||
continue
|
||||
|
||||
if checkpoint_pos:
|
||||
# Respawn player at checkpoint
|
||||
P1, platforms, all_sprites, background, checkpoints = (
|
||||
reset_game_with_checkpoint(level_file, game_resources)
|
||||
for event in events:
|
||||
if event.type == QUIT:
|
||||
running = False
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif event.type == KEYDOWN:
|
||||
if event.key == K_ESCAPE:
|
||||
if current_state in [PLAYING, INFINITE]:
|
||||
current_state = MENU
|
||||
else:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif event.key == K_F11:
|
||||
fullscreen = not fullscreen
|
||||
if fullscreen:
|
||||
# Store current window size before going fullscreen
|
||||
ORIGINAL_WIDTH, ORIGINAL_HEIGHT = displaysurface.get_size()
|
||||
displaysurface = pygame.display.set_mode(
|
||||
(0, 0), pygame.FULLSCREEN
|
||||
)
|
||||
else:
|
||||
# Return to windowed mode with previous size
|
||||
displaysurface = pygame.display.set_mode(
|
||||
(ORIGINAL_WIDTH, ORIGINAL_HEIGHT), pygame.RESIZABLE
|
||||
)
|
||||
elif (
|
||||
event.type == VIDEORESIZE
|
||||
): # Fixed indentation - moved out of K_F11 condition
|
||||
if not fullscreen:
|
||||
displaysurface = pygame.display.set_mode(
|
||||
(event.w, event.h), pygame.RESIZABLE
|
||||
)
|
||||
projectiles.empty()
|
||||
else:
|
||||
# No checkpoint found, return to menu
|
||||
current_state = MENU
|
||||
if event.dict.get("action") == "create_projectile":
|
||||
projectile = event.dict.get("projectile")
|
||||
projectiles.add(projectile)
|
||||
# Update window dimensions
|
||||
ORIGINAL_WIDTH, ORIGINAL_HEIGHT = event.w, event.h
|
||||
elif event.type == USEREVENT:
|
||||
if event.action == "player_death":
|
||||
db = CheckpointDB()
|
||||
checkpoint_pos = db.get_checkpoint(level_file)
|
||||
|
||||
# Handle menu events
|
||||
if current_state == MENU:
|
||||
if current_menu == "main":
|
||||
action = main_menu.handle_event(event)
|
||||
if action == "level_select":
|
||||
level_select_menu = LevelSelectMenu(game_resources)
|
||||
if checkpoint_pos:
|
||||
# Respawn player at checkpoint
|
||||
P1, platforms, all_sprites, background, checkpoints = (
|
||||
reset_game_with_checkpoint(level_file, game_resources)
|
||||
)
|
||||
projectiles.empty()
|
||||
else:
|
||||
# No checkpoint found, return to menu
|
||||
current_state = MENU
|
||||
if event.dict.get("action") == "create_projectile":
|
||||
projectile = event.dict.get("projectile")
|
||||
projectiles.add(projectile)
|
||||
|
||||
# Handle menu events
|
||||
if current_state == MENU:
|
||||
if current_menu == "main":
|
||||
action = main_menu.handle_event(event)
|
||||
if action == "level_select":
|
||||
level_select_menu = LevelSelectMenu(game_resources)
|
||||
current_menu = "level_select"
|
||||
elif action == "infinite":
|
||||
current_state = INFINITE
|
||||
elif action == "leaderboard":
|
||||
current_state = LEADERBOARD
|
||||
elif action == "quit":
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif current_menu == "level_select":
|
||||
action = level_select_menu.handle_event(event)
|
||||
if action == "back_to_main":
|
||||
current_menu = "main"
|
||||
elif (
|
||||
isinstance(action, dict)
|
||||
and action.get("action") == "select_level"
|
||||
):
|
||||
level_file = action.get("level_file")
|
||||
print(level_file)
|
||||
(
|
||||
P1,
|
||||
PT1,
|
||||
platforms,
|
||||
all_sprites,
|
||||
background,
|
||||
checkpoints,
|
||||
exits,
|
||||
) = initialize_game(game_resources, level_file)
|
||||
projectiles.empty()
|
||||
current_state = PLAYING
|
||||
elif action == "open_editor":
|
||||
editor_select_menu = LevelEditorSelectionMenu(
|
||||
game_resources
|
||||
)
|
||||
current_state = "editor_select"
|
||||
|
||||
# Handle leaderboard events
|
||||
elif current_state == LEADERBOARD:
|
||||
action = leaderboard.handle_event(event)
|
||||
if action == "menu":
|
||||
current_state = MENU
|
||||
|
||||
elif current_state == "editor_select":
|
||||
action = editor_select_menu.handle_event(event)
|
||||
if action == "back_to_levels":
|
||||
current_state = MENU
|
||||
current_menu = "level_select"
|
||||
elif action == "infinite":
|
||||
current_state = INFINITE
|
||||
elif action == "leaderboard":
|
||||
current_state = LEADERBOARD
|
||||
elif action == "quit":
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
elif current_menu == "level_select":
|
||||
action = level_select_menu.handle_event(event)
|
||||
if action == "back_to_main":
|
||||
current_menu = "main"
|
||||
elif (
|
||||
isinstance(action, dict)
|
||||
and action.get("action") == "select_level"
|
||||
):
|
||||
level_file = action.get("level_file")
|
||||
print(level_file)
|
||||
(
|
||||
P1,
|
||||
PT1,
|
||||
platforms,
|
||||
all_sprites,
|
||||
background,
|
||||
checkpoints,
|
||||
exits,
|
||||
) = initialize_game(game_resources, level_file)
|
||||
projectiles.empty()
|
||||
current_state = PLAYING
|
||||
elif action == "open_editor":
|
||||
editor_select_menu = LevelEditorSelectionMenu(game_resources)
|
||||
elif isinstance(action, dict):
|
||||
if action["action"] == "edit_level":
|
||||
level_editor = LevelEditor(
|
||||
game_resources, action["level_file"]
|
||||
)
|
||||
current_state = "level_editor"
|
||||
elif action["action"] == "new_level":
|
||||
level_editor = LevelEditor(game_resources)
|
||||
current_state = "level_editor"
|
||||
|
||||
elif current_state == "level_editor":
|
||||
result = level_editor.handle_event(event)
|
||||
if result == "back_to_levels":
|
||||
current_state = "editor_select"
|
||||
|
||||
# Handle leaderboard events
|
||||
elif current_state == LEADERBOARD:
|
||||
action = leaderboard.handle_event(event)
|
||||
if action == "menu":
|
||||
current_state = MENU
|
||||
|
||||
elif current_state == "editor_select":
|
||||
action = editor_select_menu.handle_event(event)
|
||||
if action == "back_to_levels":
|
||||
current_state = MENU
|
||||
current_menu = "level_select"
|
||||
elif isinstance(action, dict):
|
||||
if action["action"] == "edit_level":
|
||||
level_editor = LevelEditor(game_resources, action["level_file"])
|
||||
current_state = "level_editor"
|
||||
elif action["action"] == "new_level":
|
||||
level_editor = LevelEditor(game_resources)
|
||||
current_state = "level_editor"
|
||||
|
||||
elif current_state == "level_editor":
|
||||
result = level_editor.handle_event(event)
|
||||
if result == "back_to_levels":
|
||||
current_state = "editor_select"
|
||||
except Exception as e:
|
||||
print(f"Erreur lors du traitement de l'événement: {e}")
|
||||
continue
|
||||
|
||||
# Clear screen
|
||||
displaysurface.fill((0, 0, 0))
|
||||
|
||||
@@ -11,6 +11,20 @@ class Player(Entity):
|
||||
# Game ressources
|
||||
self.game_resources = game_resources
|
||||
|
||||
self.has_joystick = False
|
||||
self.joystick = None
|
||||
|
||||
self.jump_button = 0
|
||||
self.dash_button = 1
|
||||
|
||||
try:
|
||||
if pygame.joystick.get_count() > 0:
|
||||
self.joystick = pygame.joystick.Joystick(0)
|
||||
self.joystick.init()
|
||||
self.has_joystick = True
|
||||
except pygame.error:
|
||||
self.has_joystick = False
|
||||
|
||||
# Animation variables
|
||||
self.animation_frames = []
|
||||
self.jump_frames = []
|
||||
@@ -171,18 +185,46 @@ class Player(Entity):
|
||||
# Reset flags
|
||||
self.moving = False
|
||||
|
||||
# Keyboard controls
|
||||
pressed_keys = pygame.key.get_pressed()
|
||||
if pressed_keys[K_q]:
|
||||
move_left = pressed_keys[K_q]
|
||||
move_right = pressed_keys[K_d]
|
||||
jump = pressed_keys[K_SPACE]
|
||||
dash_key = pressed_keys[K_a]
|
||||
|
||||
if self.has_joystick and self.joystick:
|
||||
try:
|
||||
# Joystick gauche pour mouvement
|
||||
if self.joystick.get_numaxes() > 0:
|
||||
joystick_x = self.joystick.get_axis(0)
|
||||
if abs(joystick_x) > 0.2:
|
||||
if joystick_x < 0:
|
||||
move_left = True
|
||||
elif joystick_x > 0:
|
||||
move_right = True
|
||||
|
||||
# Boutons pour sauter/dasher
|
||||
if self.joystick.get_numbuttons() > self.jump_button:
|
||||
if self.joystick.get_button(self.jump_button):
|
||||
jump = True
|
||||
|
||||
if self.joystick.get_numbuttons() > self.dash_button:
|
||||
if self.joystick.get_button(self.dash_button):
|
||||
dash_key = True
|
||||
except pygame.error:
|
||||
pass # Ignorer les erreurs de manette
|
||||
|
||||
if move_left:
|
||||
# Check if X is > 0 to prevent player from going off screen
|
||||
if self.pos.x > 0:
|
||||
self.acc.x = -self.game_resources.ACC
|
||||
self.moving = True
|
||||
if pressed_keys[K_a]:
|
||||
if dash_key:
|
||||
self.dash(-self.game_resources.ACC)
|
||||
if pressed_keys[K_d]:
|
||||
if move_right:
|
||||
self.acc.x = self.game_resources.ACC
|
||||
self.moving = True
|
||||
if pressed_keys[K_a]:
|
||||
if dash_key:
|
||||
self.dash(self.game_resources.ACC)
|
||||
|
||||
# Also consider the player moving if they have significant horizontal velocity
|
||||
@@ -190,7 +232,7 @@ class Player(Entity):
|
||||
self.moving = True
|
||||
|
||||
# Jumping logic
|
||||
if pressed_keys[K_SPACE] and not self.jumping:
|
||||
if jump and not self.jumping:
|
||||
self.vel.y = -30
|
||||
self.jumping = True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user