Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/src/game/__pycache__
/src/game/modes/__pycache__
/src/game/modules/__pycache__
/src/game/ui/__pycache__
/src/utils/__pycache__
/survival-shooter/src/game/__pycache__
/survival-shooter/src/game/__pycache__
/src/game/systems/__pycache__
/src/game/core/__pycache__
61 changes: 60 additions & 1 deletion plan.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,63 @@
- Sprites du joueur avec rotation
- Sprites des ennemis
- Logo du jeu
- Interface graphique cohérente
- Interface graphique cohérente

8. Système de Modules et Progression
- Modules permanents (achetables) :
* Interface d'achat avec pièces
* Niveaux d'amélioration (1 à 3)
* Sauvegarde des modules débloqués
- Modules temporaires (coffres) :
* Menu de sélection en jeu
* Effets cumulables avec les modules permanents
- Types d'effets :
* Tir rapide (cooldown réduit)
* Bouclier amélioré (cooldown réduit)
* Boost de dégâts
* Boost de vitesse
* Régénération de santé
* Multi-tir (projectiles multiples)
* Attraction de pièces
* Tirs critiques
* Tirs explosifs
* Bouclier réfléchissant
* Ralentissement d'ennemis
* Bonus de pièces
* Tirs perçants

9. Économie et Collectibles
- Système de pièces :
* Drop sur les ennemis tués
* Interface d'affichage
* Sauvegarde entre les sessions
- Coffres :
* Spawn aléatoire
* Sélection de modules temporaires
- Système d'attraction magnétique pour les pièces

10. Personnages et Statistiques
- Système de personnages débloquables :
* Stats différentes (santé, vitesse, dégâts)
* Sprites personnalisés
* Sauvegarde du personnage sélectionné
- Application des statistiques de base aux personnages

11. Modes de Jeu
- Mode Classique (survie continue)
- Mode Survie (vagues progressives avec records)
- Mode Boss Rush (combats de boss consécutifs)
- Sélection de mode via menu dédié
- Records spécifiques pour chaque mode :
* Temps de survie (Classique)
* Vague maximale (Survie)
* Boss vaincus (Boss Rush)

12. Système de Sauvegarde
- Sauvegarde des progrès en JSON :
* High scores pour chaque mode
* Modules débloqués et leur niveau
* Personnages débloqués
* Économie (pièces accumulées)
- Chargement automatique au démarrage
- Sauvegarde automatique à la fermeture
47 changes: 47 additions & 0 deletions prompt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,50 @@ ses réflexes et sa précision.
- Méthodes réutilisables pour les éléments communs
- Meilleure organisation du code UI
- Séparation des responsabilités menu/jeu

## Prompt 14 - Système de Modes de Jeu
- Implémentation de trois modes distincts (Classique, Survie, Boss Rush)
- Menu de sélection de mode avec descriptions visuelles
- Interface adaptée à chaque mode de jeu
- Records spécifiques à chaque mode
- HUD personnalisé selon le mode actif

## Prompt 15 - Boutique de Personnages
- Système de personnages avec statistiques différentes
- Interface de sélection avec aperçu des personnages
- Animation des personnages dans la boutique
- Système de déblocage de personnages avec des pièces
- Affichage des statistiques comparatives

## Prompt 16 - Système d'Économie
- Implémentation du système de pièces
- Drop de pièces à la mort des ennemis
- Animation de collecte des pièces
- Interface d'affichage du solde
- Sauvegarde de l'économie entre les sessions

## Prompt 17 - Modules Permanents
- Boutique de modules améliorables
- Interface d'achat avec description des effets
- Système de niveaux d'amélioration
- Application des effets au joueur

## Prompt 18 - Modules Temporaires et Coffres
- Système de coffres à la mort des ennemis
- Menu de sélection de modules temporaires en jeu
- Cumul des effets temporaires et permanents
- Diversité des bonus temporaires

## Prompt 19 - Boss
- Barre de vie dédiée pour les boss

## Prompt 20 - Interaction avec l'Environnement
- Système de magnétisme pour les pièces

## Prompt 21 - Système de Notifications
- Interface de notification dans le coin de l'écran
- Animation de fade-in et fade-out pour les notifications
- File d'attente pour gérer plusieurs notifications
- Support des icônes personnalisées
- Adaptable à plusieurs contextes (boutique, combats, etc.)
- Utile pour la gestion des hauts faits (achievements)
11 changes: 10 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,13 @@ survival-shooter
├── README.md
├── plan.txt
├── prompt.txt
└── requirements.txt
└── requirements.txt









4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
numpy==2.2.3
pygame==2.5.2
numpy==2.2.4
pygame==2.6.1
1 change: 1 addition & 0 deletions save_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"coins": 68079, "achievements": {"first_kill": {"unlocked": true, "progress": 0}, "survivor": {"unlocked": false, "progress": 0}, "rich": {"unlocked": true, "progress": 100}, "collector": {"unlocked": false, "progress": 0}, "master": {"unlocked": false, "progress": 0}}}
File renamed without changes.
File renamed without changes.
Binary file added src/assets/achievements/first_kill.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/achievements/rich.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/achievements/survivor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/characters/speeder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/characters/tank.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/chest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/coin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/coin_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes.
Binary file added src/assets/sounds/achievement.wav
Binary file not shown.
Binary file added src/assets/sounds/coin.wav
Binary file not shown.
Binary file added src/assets/sounds/enemy_death.wav
Binary file not shown.
Binary file added src/assets/sounds/hit.wav
Binary file not shown.
Binary file added src/assets/sounds/purchase.wav
Binary file not shown.
1 change: 1 addition & 0 deletions src/assets/sprites/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/sprites/bullet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/sprites/enemy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/sprites/enemy_bullet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/sprites/player.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/data/game_save.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"highscore": 10200, "wave": 1, "score": 0, "records": {"classic": {"best_survival_time": 112}, "survival": {"best_wave": 3}, "boss_rush": {"best_bosses_killed": 0}}, "characters": {"characters": {"default": {"unlocked": true, "selected": false}, "speed": {"unlocked": true, "selected": false}, "tank": {"unlocked": true, "selected": false}, "glass": {"unlocked": true, "selected": true}}}}
File renamed without changes.
File renamed without changes.
Empty file added src/game/core/__init__.py
Empty file.
99 changes: 88 additions & 11 deletions survival-shooter/src/game/enemy.py → src/game/core/enemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
import math
import random
from utils.constants import *
from game.weapon import Bullet
from game.core.weapon import Bullet

class Enemy(pygame.sprite.Sprite):
def __init__(self, health, speed):
super().__init__()
self.max_health = health # Ajout de la santé maximale
self.health = health
self.speed = speed
self.base_speed = speed # Vitesse de base
self.speed = speed # Vitesse actuelle (peut être modifiée par des effets)

# Attributs pour le ralentissement
self.slow_factor = 0 # Facteur de ralentissement (0 = pas de ralentissement, 0.5 = 50% de ralentissement)
self.slow_duration = 0 # Durée du ralentissement en ms
self.is_slowed = False # État de ralentissement

# Configuration de la barre de vie
self.health_bar_height = 5
Expand All @@ -36,6 +42,7 @@ def __init__(self, health, speed):
scaled_points = [(center + (x-center)*0.7, center + (y-center)*0.7) for x, y in points]
pygame.draw.polygon(self.image, ENEMY_COLOR, scaled_points)

self.original_image = self.image.copy() # Garder une copie de l'image originale
self.rect = self.image.get_rect()
self.spawn()

Expand All @@ -56,6 +63,9 @@ def spawn(self):
self.rect.y = random.randint(0, SCREEN_HEIGHT)

def move(self, target_position):
# Mise à jour des effets de ralentissement
self.update_slow_effect()

# Calcul du vecteur de direction vers le joueur
dx = target_position[0] - self.rect.centerx
dy = target_position[1] - self.rect.centery
Expand Down Expand Up @@ -120,6 +130,31 @@ def draw(self, screen):
pygame.draw.rect(screen, (0, 255, 0),
(bar_x, bar_y, bar_width, self.health_bar_height))

def update_slow_effect(self):
"""Met à jour l'effet de ralentissement"""
current_time = pygame.time.get_ticks()

if self.slow_duration > 0 and current_time >= self.slow_duration:
# L'effet de ralentissement est terminé
self.is_slowed = False
self.slow_factor = 0
self.slow_duration = 0
self.speed = self.base_speed
# Restaurer l'apparence normale
self.image = self.original_image.copy()
elif self.slow_factor > 0:
# L'effet de ralentissement est actif
if not self.is_slowed:
self.is_slowed = True
# Appliquer le ralentissement
self.speed = self.base_speed * (1 - self.slow_factor)
# Modifier l'apparence pour indiquer le ralentissement
slowed_image = self.original_image.copy()
blue_overlay = pygame.Surface(slowed_image.get_size(), pygame.SRCALPHA)
blue_overlay.fill((0, 0, 255, 100)) # Teinte bleue pour indiquer le ralentissement
slowed_image.blit(blue_overlay, (0, 0), special_flags=pygame.BLEND_RGBA_ADD)
self.image = slowed_image

class ShootingEnemy(Enemy):
def __init__(self, health, speed):
super().__init__(health, speed)
Expand All @@ -146,20 +181,62 @@ def __init__(self, health, speed):
scaled_points = [(center + (x-center)*0.7, center + (y-center)*0.7) for x, y in points]
pygame.draw.polygon(self.image, SHOOTER_ENEMY_COLOR, scaled_points)

self.original_image = self.image.copy() # Garder une copie de l'image originale

def update(self, player_pos):
super().move(player_pos)
current_time = pygame.time.get_ticks()
if current_time - self.last_shot >= self.shoot_cooldown:

# Ajuster le cooldown de tir en fonction du ralentissement
effective_cooldown = self.shoot_cooldown
if self.is_slowed:
# Un ennemi ralenti tire moins souvent
effective_cooldown = self.shoot_cooldown * (1 + self.slow_factor)

if current_time - self.last_shot >= effective_cooldown:
self.shoot(player_pos)

def shoot(self, player_pos):
dx = player_pos[0] - self.rect.centerx
dy = player_pos[1] - self.rect.centery
distance = math.sqrt(dx**2 + dy**2)
if distance != 0:
direction = (dx/distance, dy/distance)
bullet = Bullet(self.rect.centerx, self.rect.centery, direction, is_enemy=True)
self.bullets.add(bullet)
if hasattr(self, 'game') and self.game.enemy_shoot_sound and not self.game.sound_muted:
self.game.enemy_shoot_sound.play()
self.last_shot = pygame.time.get_ticks()
# Calculer l'angle au lieu du vecteur de direction
angle = math.atan2(dy, dx)
bullet = Bullet(self.rect.centerx, self.rect.centery, angle, ENEMY_BULLET_DAMAGE, is_enemy=True)
self.bullets.add(bullet)
if hasattr(self, 'game') and self.game.enemy_shoot_sound and not self.game.sound_muted:
self.game.enemy_shoot_sound.play()
self.last_shot = pygame.time.get_ticks()

def check_bullet_shield_collision(self, player):
"""Vérifie les collisions entre les balles ennemies et le bouclier du joueur"""
# Si le joueur n'a pas de bouclier actif, pas besoin de vérifier
if not player.shield_active:
return False

# Vérifier chaque balle
for bullet in self.bullets:
# Calculer la distance entre la balle et le centre du joueur
dx = bullet.rect.centerx - player.rect.centerx
dy = bullet.rect.centery - player.rect.centery
distance = math.sqrt(dx * dx + dy * dy)

# Si la balle est à l'intérieur du rayon du bouclier
shield_radius = PLAYER_SIZE + 10 # Même valeur que dans player.draw
if distance < shield_radius:
# Déterminer si la balle rebondit ou est détruite
if hasattr(player, 'reflect_chance') and random.random() < player.reflect_chance:
# La balle rebondit vers l'ennemi
bullet.direction_x *= -1
bullet.direction_y *= -1

# Jouer un son si disponible
if hasattr(self, 'game') and hasattr(self.game, 'hit_sound') and self.game.hit_sound and not self.game.sound_muted:
self.game.hit_sound.play()

return True
else:
# La balle est simplement détruite
bullet.kill()
return True

return False
Loading