<h2>Découvrez le jeu</h2>
<p>
    Space Invaders est un jeu d'arcade créé en 1978 par Tomohiro Nishikado. Dans ce jeu captivant, le joueur prend le contrôle d'un canon laser placé en bas de l'écran et doit défendre la Terre contre des vagues incessantes d'extraterrestres. <br><br>
    Ces envahisseurs se déplacent latéralement et descendent progressivement, menaçant de plus en plus notre planète. Le joueur doit habilement détruire les ennemis en tirant des projectiles tout en esquivant leurs tirs. À mesure que le joueur élimine les extraterrestres, leur vitesse augmente, rendant le défi encore plus intense. <br><br>
    Le jeu se termine si les envahisseurs atteignent le bas de l'écran ou si le joueur perd toutes ses vies. Avec son gameplay addictif et son influence durable, Space Invaders a marqué l'histoire des jeux vidéo et reste une référence incontournable du genre.
</p>
<h3>Téléchargez le code source</h3>
<a href="https://assets.benjamin-bonneton.com/zip/space-invaders-python.zip" target="_blank" rel="noopener noreferrer" class="btn"><span>Téléchargez le code</span></a>
<h3>Faire tourner le jeu</h3>
<p>Si vous souhaitez faire tourner ce jeu sur votre machine, voici plusieurs prérequis à respecter :</p>
<ul>
    <li><b>Version de Python :</b> Certaines versions de Python ne permettent pas de faire tourner le jeu ou entraînent des performances beaucoup plus faibles. Le jeu a été développé et testé sur Python 3.11.7</li>
    <li><b>Version de Pygame :</b> Le jeu a été développé et testé sur la version 2.5.2 de PyGame, cependant il peut également fonctionner sur des versions plus récentes bien qu'elles n'aient pas été testées.</li>
    <li><b>Système d'exploitation :</b> Les tests ont été effectués sous Windows 11, mais le jeu devrait fonctionner sur n'importe quel système d'exploitation tant qu'il prend en charge Python et les modules nécessaires.</li>
    <li><b>Chemin d'Accès aux ressources :</b> Le programme va chercher des ressources situées dans un dossier 'assets'. Il est donc nécessaire de lancer le programme depuis le dossier dans lequel il se trouve, sinon une erreur de chemin d'accès peut se produire. Une erreur se produira si vous exécutez le programme sans extraire les fichiers de l'archive zip.</li>
</ul>
<p>Si ces critères sont remplis, vous pouvez alors lancer le fichier space_invaders.py et commencer à jouer.</p>
<h3>Principaux Changements</h3>
<h4>Nouveautés Générales</h4>
<ul>
    <li>Ajout d'un menu d'accueil permettant de choisir le mode de jeu et le monde de départ.</li>
    <li>Ajout d'un menu de pause accessible avec la touche Échap, offrant des options pour revenir au jeu, retourner au menu d'accueil ou quitter le jeu.</li>
    <li>Ajout d'un mode libre où le joueur affronte des ennemis sans fin et possède tous les pouvoirs des boss.</li>
    <li>Ajout de la possibilité pour le joueur de mourir et d'afficher un écran de mort.</li>
    <li>Ajout de barres de vie pour les boss, les ennemis et le joueur.</li>
    <li>Ajout d'un score affiché en haut à gauche de l'écran en mode libre.</li>
</ul>
<h4>Mode Campagne</h4>
<ul>
    <li>
        Ajout d'un mode campagne composé de 8 niveaux avec 7 ennemis différents et 7 pouvoirs.
        <ul>
            <li><ins>Niveaux 1 à 6 :</ins> Les ennemis apparaissent successivement, suivis d'un boss. Une fois tous les ennemis détruits, le boss apparaît. Vaincre le boss permet d'accéder au niveau suivant.</li>
            <li><ins>Niveaux 7 :</ins> Pas d'ennemis, mais trois mini-boss avec deux pouvoirs chacun.</li>
            <li><ins>Niveau 8 :</ins> Pas d'ennemis non plus, mais un boss final possédant tous les pouvoirs du jeu plus un nouveau pouvoir unique qui arrête le rafraîchissement des images du jeu.</li>
        </ul>
    </li>
    <li>Chaque boss a son propre pouvoir, que le joueur récupère au niveau suivant une fois le boss battu.</li>
    <li>Une transition entre chaque monde affiche les mondes déjà parcourus et présente le nouveau pouvoir obtenu dans une boîte de dialogue.</li>
    <li>Lorsque le boss du niveau 8 est battu, un générique de fin se lance avant de revenir au menu d'accueil.</li>
</ul>
<h4>Musique et Sons</h4>
<ul>
    <li>Ajout de musiques de fond différentes pour chaque affrontement avec les boss.</li>
    <li>Ajout de musiques de fond lors des affrontements avec les ennemis, sur le menu d'accueil, et pour le générique de fin</li>
</ul>
<h4>Graphismes et Effets</h4>
<ul>
    <li>Ajout de fonds différents pour chaque monde.</li>
    <li>Ajout d'une classe Effect pour afficher sur plusieurs frames une image, comme lors de la téléportation d'une entité.</li>
    <li>Ajout d'une sélection du monde dans lequel commencer via le menu d'accueil.</li>
</ul>
<h3>Droits d'Auteurs et Crédits</h3>
<p>
    Pour la création de ma version revisitée de Space Invaders, j'ai utilisé diverses ressources pour enrichir l'expérience de jeu. Les images ont été générées à l'aide de l'intelligence artificielle Midjourney, offrant ainsi un visuel unique et moderne. Les effets sonores proviennent de Pixabay, une plateforme reconnue pour ses ressources audio libres de droits, tandis que les musiques qui accompagnent le jeu sont issues de Soundraw, un service qui permet de créer des morceaux personnalisés et originaux. <br><br>
    Je tiens à préciser que toute modification ou redistribution de mon projet doit impérativement mentionner mon nom dans les crédits pour le code source. Par ailleurs, la revente de ce jeu, sous quelque forme que ce soit, est strictement interdite. Mon objectif est de partager cette création avec la communauté Open Source, tout en respectant les contributions et efforts investis dans ce projet.<br><br>
    En respectant ces conditions, vous contribuez à valoriser le travail collaboratif et à préserver l'esprit de partage qui anime la communauté des développeurs. Merci de votre compréhension et de votre soutien.
</p>
<h3>Structures du projet</h3>
<p> Dans cette section, je vais vous présenter la structure de mon projet Space Invaders revisité, en expliquant le fonctionnement du code et l'utilité des différentes classes et méthodes. Cette documentation vise à vous fournir une compréhension approfondie de l'architecture du jeu, facilitant ainsi toute modification ou contribution future. </p>
<h4>Organisation du Code</h4>
<p> Le projet est structuré principalement autour du fichier <code>space_invaders.py</code>, qui constitue le cœur de la boucle de jeu, et du module <code>space</code>, qui contient les classes et méthodes nécessaires pour le fonctionnement du jeu. Voici un aperçu des principaux composants et de leur rôle : </p>
<ul>
    <li>
        <strong>space_invaders.py</strong> : Le fichier principal qui initialise le jeu, gère les événements et contrôle la boucle principale du jeu.
    </li>
    <li>
        <strong>space.py</strong> : Contient les classes et méthodes pour les différents éléments du jeu (par exemple, Joueur, Ennemi, Tir).
    </li>
</ul>
<h4>Détails des Classes et Méthodes</h4>
<h5>Fichier space_invaders.py</h5>
<p> Le fichier <code>space_invaders.py</code> initialise le jeu, gère les événements et maintient la boucle principale. Voici une explication détaillée de son contenu et de son fonctionnement : </p>
<h5>Initialisation</h5>
<pre>
<code>import sys
sys.dont_write_bytecode = True
import pygame
import space
import sys</code>
</pre>
<p> Ces lignes importent les modules nécessaires et empêchent la création de fichiers bytecode (.pyc). </p>
<h5>Paramètres du jeu</h5>
<pre>
<code>WIDTH = 800
HEIGHT = 600
FPS = 60</code>
</pre>
<p>Définition des paramètres de la fenêtre de jeu.</p>
<h5>Lancement des modules de pygame</h5>
<pre>
<code>pygame.init()
clock = pygame.time.Clock()</code>
</pre>
<p>Initialisation de Pygame et création d'un objet <code>clock</code> pour gérer le temps. </p>
<h5>Création de la fenêtre</h5>
<pre>
<code>screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Invaders")</code>
</pre>
<p>Création de la fenêtre de jeu avec les dimensions spécifiées et définition du titre.</p>
<h5>Instantiation de la classe Jeu</h5>
<pre>
<code>jeu = space.Jeu(screen, WIDTH, HEIGHT, FPS)</code>
</pre>
<p>Création d'une instance de la classe <code>Jeu</code> définie dans <code>space.py</code>. </p>
<h5>Boucle de jeu</h5>
<pre>
<code>while True:
    ...</code>
</pre>
<p> La boucle principale du jeu gère les événements, met à jour l'état du jeu et rend les objets à l'écran. Voici quelques éléments clés de cette boucle : </p>
<h5>Fond de la fenêtre</h5>
<pre>
    <code>if (jeu.scene not in ['transition', 'ending', 'free_death', 'campaign_death']) and (jeu.bg_stop is False):
        jeu.screen.blit(jeu.background(), (0, 0))</code>
</pre>
<p>Affiche le fond de la fenêtre sauf dans certaines scènes spécifiques.</p>
<h5>Gestion des événements</h5>
<pre>
    <code>
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            ...
    </code>
</pre>
<p>Gère les événements de fermeture de la fenêtre, les entrées clavier et souris.</p>
<h5>Mise à jour de la scène</h5>
<pre>
<code>
if jeu.scene == 'home':
    jeu.home()
elif jeu.scene == 'levels':
    jeu.levels()
elif jeu.scene in ['campaign_menu', 'free_menu']:
    jeu.ingame_menu()
elif jeu.scene in ['campaign', 'free']:
    ...
elif jeu.scene == 'transition':
    jeu.world_transition()
elif jeu.scene == 'ending':
    jeu.ending()
elif jeu.scene in ['campaign_death', 'free_death']:
    ...
</code>
</pre>
<p> Met à jour et affiche les différentes scènes du jeu en fonction de l'état actuel. </p>
<h5>Rendu et mise à jour de l'écran</h5>
<pre>
<code>pygame.display.update()
clock.tick(FPS)</code>
</pre>
<p>Met à jour l'affichage et contrôle le taux de rafraîchissement du jeu.</p>
<h5>Fichier space.py</h5>
<p> Le fichier <code>space.py</code> contient les classes et méthodes nécessaires pour les différents éléments du jeu. Voici un aperçu des classes principales et de leurs méthodes : </p>
<h5>Classe Jeu</h5>
<ul>
    <li>
        <code>__init__(self, screen, width, height, fps)</code> : Initialise les paramètres du jeu, y compris l'écran, les dimensions et le taux de rafraîchissement.
    </li>
    <li>
        <code>background(self)</code> : Retourne l'image de fond à afficher.
    </li>
    <li>
        <code>home(self)</code> : Gère la scène d'accueil.
    </li>
    <li>
        <code>levels(self)</code> : Gère la scène de sélection des niveaux.
    </li>
    <li>
        <code>ingame_menu(self)</code> : Affiche le menu en cours de jeu.
    </li>
    <li>
        <code>campaign(self, world=None)</code> : Démarre une campagne, avec un niveau spécifique si indiqué.
    </li>
    <li>
        <code>free(self)</code> : Démarre le mode libre.
    </li>
    <li>
        <code>world_campaign(self)</code> : Gère le déroulement des niveaux de la campagne.
    </li>
    <li>
        <code>world_free(self)</code> : Gère le déroulement des niveaux du mode libre.
    </li>
    <li>
        <code>world_transition(self)</code> : Gère les transitions entre les niveaux.
    </li>
    <li>
        <code>ending(self)</code> : Gère la scène de fin de jeu.
    </li>
    <li>
        <code>show_text(self, text, position, size, color=(255, 255, 255))</code> : Affiche du texte à l'écran.
    </li>
    <li>
        <code>interface(self)</code> : Gère l'affichage de l'interface utilisateur.
    </li>
</ul>
<h5>Classe Player</h5>
<ul>
    <li>
        <code>__init__(self, x, y)</code> : Initialise la position du joueur.
    </li>
    <li>
        <code>deplacer(self)</code> : Gère le déplacement du joueur.
    </li>
    <li>
        <code>cooldown(self)</code> : Gère le temps de recharge des pouvoirs du joueur.
    </li>
    <li>
        <code>marquer(self)</code> : Incrémente le score du joueur.
    </li>
</ul>
<h5>Classe Ennemi</h5>
<ul>
    <li>
        <code>__init__(self, x, y, speed, type)</code> : Initialise la position, la vitesse et le type de l'ennemi.
    </li>
    <li>
        <code>avancer(self)</code> : Gère le déplacement de l'ennemi.
    </li>
    <li>
        <code>ability(self)</code> : Active les capacités spéciales de l'ennemi.
    </li>
    <li>
        <code>disparaitre(self)</code> : Gère la disparition de l'ennemi lorsqu'il est détruit.
    </li>
</ul>
<h5>Classe Tir</h5>
<ul>
    <li>
        <code>__init__(self, x, y, speed, direction)</code> : Initialise la position, la vitesse et la direction du projectile.
    </li>
    <li>
        <code>bouger(self)</code> : Met à jour la position du projectile.
    </li>
    <li>
        <code>toucher(self, target)</code> : Vérifie si le projectile touche une cible.
    </li>
    <li>
        <code>toucher_healer(self, pouvoir)</code> : Vérifie si le projectile
    <li>
        <code>toucher_healer(self, pouvoir)</code> : Vérifie si le projectile touche un ennemi de type guérisseur sans être bloqué par son pouvoir.
    </li>
</ul>
<h5>Classe Boss</h5>
<ul>
    <li>
        <code>__init__(self, name, x, y, speed)</code> : Initialise le nom, la position et la vitesse du boss.
    </li>
    <li>
        <code>bouger(self)</code> : Gère le déplacement du boss.
    </li>
    <li>
        <code>tirer(self)</code> : Gère les tirs du boss.
    </li>
    <li>
        <code>ability(self)</code> : Active les capacités spéciales du boss.
    </li>
</ul>
<h5>Classe Effect</h5>
<ul>
    <li>
        <code>__init__(self, x, y, duration)</code> : Initialise la position et la durée de l'effet.
    </li>
    <li>
        <code>afficher(self)</code> : Affiche l'effet à l'écran.
    </li>
</ul>