Jeu vidéo 2D en C++ avec SDL

Un moteur de jeu 2D en C++ avec chargement de niveaux, collisions et ennemis qui avancent à chaque action du joueur.

Année
BUT1, 2024–2025
Type
SAÉ
Domaine
Développement
Période
septembre 2024 – janvier 2025
Stack
C++, SDL, POO
Fenêtre du jeu : une salle vue de dessus, en pixel art, murs de pierre grise autour d’un plancher de bois, sur une grille de 10 × 8 cases. Le long du mur du haut, un coffre fermé, un lit bleu, deux commodes et un escalier ; au centre, un fauteuil et une table ; en bas, un pot, un tapis rouge, une étagère et une porte dans le mur. Le personnage, un petit sprite en tunique claire, est en haut à gauche, sous une pièce d’or ; une chauve-souris vole à droite de la table ; une limace verte est posée sous la table, sur une pièce ; deux autres pièces d’or sont à droite, en haut et en bas.
Niveau chargé, exécutable du dépôt, hors ligne7 écransOuvrir la visite

En bref

Problème
Construire un jeu 2D complet en C++ à partir d’une bibliothèque graphique simplifiée.
Ce que j’ai réalisé
Un moteur objet qui charge ses niveaux depuis des fichiers texte, gère les collisions, deux ennemis en patrouille et des états de victoire ou de défaite.
Résultat
Le jeu est jouable de bout en bout ; les ennemis avancent d’un pas par événement clavier, au plus 8 fois par seconde pour alléger la boucle.
Rôle
Développement complet.
Équipe
Projet individuel
Statut
Terminé

Le jeu, état par état

Captures du jeu tel qu’il est livré dans le dépôt : l’exécutable de la version rendue, lancé hors ligne, dans sa fenêtre de 800 × 640 pixels, agrandie quatre fois sans lissage pour garder le pixel art net. Aucune donnée personnelle n’y figure. Les coordonnées des légendes sont (colonne, ligne), comptées à partir de 0 depuis le coin supérieur gauche de la grille de 10 × 8 cases.

01 sur 04

Niveau chargé

Le niveau vient d’être lu depuis son fichier : le joueur part de la case (2, 2), la chauve-souris de (5, 4) et la limace de (4, 5), posée sur l’une des quatre pièces ; le coffre en (1, 1) est fermé.

Niveau

  • Salle vue de dessus : le personnage en tunique claire est en haut à gauche, sous une pièce d’or placée à côté du coffre fermé ; la chauve-souris est à droite de la table, au centre ; la limace verte est sous la table, posée sur une pièce ; deux autres pièces sont à droite, en haut près des commodes et en bas près de l’étagère., ouvrir la capture complète
    Niveau chargé Le niveau vient d’être lu depuis son fichier : le joueur part de la case (2, 2), la chauve-souris de (5, 4) et la limace de (4, 5), posée sur l’une des quatre pièces ; le coffre en (1, 1) est fermé.

Partie

  • Le personnage est monté d’une case, à côté du coffre, et la pièce qui s’y trouvait n’est plus visible ; la chauve-souris s’est décalée d’une case vers la droite et la limace d’une case vers le bas, ce qui découvre la pièce sous la table ; trois pièces restent au sol., ouvrir la capture complète
    Première pièce ramassée Une flèche vers le haut : le joueur monte en (2, 1) et la pièce de cette case disparaît, il en reste trois ; au même événement clavier, la chauve-souris avance en (6, 4) et la limace en (4, 6).
  • Le personnage est en haut à droite, entre les commodes et l’escalier, là où se trouvait une pièce ; la limace est en haut, à droite du lit ; la chauve-souris est à droite de la table ; deux pièces restent, sous la table et en bas à droite., ouvrir la capture complète
    Deuxième pièce, à droite Huit touches depuis le lancement : le joueur est en (7, 1), entre la commode et l’escalier, et vient de prendre la deuxième pièce ; la limace est remontée en (4, 1), la chauve-souris est revenue en (5, 4) ; deux pièces restent.
  • Le personnage est en bas à droite, à côté de l’étagère ; la chauve-souris est sur le mur de pierre de gauche, à mi-hauteur ; la limace est posée sur la table, au centre ; une seule pièce reste, juste sous la table., ouvrir la capture complète
    Troisième pièce, en bas Treize touches depuis le lancement : le joueur descend en (7, 6) et ramasse la troisième pièce, il n’en reste qu’une, en (4, 5) ; la chauve-souris est sur le mur de gauche, en (0, 4), et la limace sur la table, en (4, 4).

Fin de partie

  • Un large bandeau vert portant « BRAVO !!! » en lettres noires couvre le haut de la salle ; sous lui, la chauve-souris est sur la table, le personnage juste en dessous, à la place de la dernière pièce, et la limace une case plus bas ; il n’y a plus aucune pièce au sol., ouvrir la capture complète
    Bravo : les quatre pièces Dix-sept touches depuis le lancement : le joueur prend la dernière pièce en (4, 5) et un bandeau « BRAVO !!! » est dessiné par-dessus la scène ; l’image reste une seconde, puis le programme se ferme de lui-même.
  • Un large bandeau rouge portant « GAME OVER » en lettres noires couvre le haut de la salle et cache le personnage ; la limace dépasse juste sous le bandeau, sur le fauteuil, et la chauve-souris est à droite ; les quatre pièces sont encore au sol., ouvrir la capture complète
    Game over : touché par la limace Sept touches depuis le lancement : bloqué par le fauteuil en (4, 3), le joueur reste en (4, 2) pendant que la limace remonte la colonne 4 jusqu’à lui ; le bandeau « GAME OVER » est dessiné par-dessus l’image précédente, où le joueur est caché, et le programme se ferme une seconde plus tard.

Options

  • Même salle qu’au départ, les quatre pièces au sol ; le personnage, toujours en haut à gauche, porte maintenant une tunique bleue ; la chauve-souris et la limace ont chacune avancé d’une case., ouvrir la capture complète
    Changement de skin La touche Espace change la ligne de skin du joueur : tunique bleue au lieu de la tunique claire ; l’appui compte comme un événement clavier, les ennemis avancent d’un pas, en (6, 4) et (4, 6).

01 sur 01

Niveau chargé

Sommaire7 sections

Contexte

L’enseignant fournissait, pour ce projet de première année, une version simplifiée de la bibliothèque SDL. L’objectif était de livrer un jeu 2D jouable.

Le problème

Le moteur fourni lisait le clavier et cadençait l’affichage. Il fallait écrire au-dessus le modèle du jeu et sa logique : niveaux, collisions, ennemis et conditions de fin.

Démarche et décisions

J’ai modélisé le jeu en objets, au-dessus des classes Moteur et Image fournies. Une seule classe Personnage sert au joueur et aux deux ennemis : elle porte leur position et leur affichage. Un Niveau regroupe des Objet, et chaque objet retrouve dans une Tuile du Dictionnaire sa place dans la planche d’images et sa propriété. Les attributs de ces classes sont privés. Objet et Tuile les exposent par des accesseurs. Les niveaux sont décrits dans des fichiers texte, une ligne Nom x y par objet, que le programme lit et analyse au chargement. Une recherche dichotomique retrouve chaque tuile dans le dictionnaire. Les déplacements et la collecte des pièces passent par la boucle d’événements clavier. Les ennemis y avancent aussi, d’un pas par événement, et réagissent aux bords de la fenêtre. La partie est gagnée quand toutes les pièces sont ramassées, et perdue au contact d’un ennemi.

Pour que le calcul des ennemis ne sature pas la boucle, je limite leur mise à jour à 8 par seconde. Sans événement clavier, ils restent immobiles. L’affichage est conditionné à ce qui est visible.

Cette boucle est reproduite dans le navigateur (fig. 1), sur un plateau simplifié jouable au clavier.

joueur ennemi bonus sortie

Prêt. Déplacez le joueur avec les flèches.

  1. Entrées. Les flèches du clavier déplacent le joueur d’une case, si elle n’est pas un mur.
  2. Mise à jour. Dans le jeu, chaque événement clavier fait aussi avancer les ennemis d’un pas, au plus huit fois par seconde ; ils font demi-tour au bord de la fenêtre. Sur ce plateau simplifié, Espace les fait avancer d’un pas et Lancer les anime seuls.
  3. Rendu, puis fin. La scène est redessinée à chaque image. Le jeu est gagné quand toutes les pièces sont ramassées, ce plateau quand le joueur atteint le coffre ; toucher un ennemi fait perdre.
Fig. 1 — La boucle de jeu sur un plateau simplifié, dans le navigateur : le joueur avance d’une case par appui, l’ennemi d’un pas avec Espace, ou huit fois par seconde avec Lancer. Ce plateau se gagne au coffre et se perd au contact de l’ennemi.

Résultat

Le jeu a été évalué dans le cadre de la SAÉ, un projet de cours noté.

Ce que j’ai appris

J’ai pratiqué la programmation objet en C++ (classes, encapsulation). Charger les niveaux depuis des fichiers texte demandait de lire et d’analyser des données externes. J’ai codé la détection de collisions et les règles de jeu.

Limites et suite

Le plafond de 8 mises à jour par seconde des ennemis a été choisi par commodité. Je reprendrais la boucle avec un pas de temps fixe, indépendant de l’affichage, pour que le jeu se comporte de la même façon sur toutes les machines.

Compétences BUT mobilisées

Compétences du référentiel BUT Informatique démontrées dans ce projet : niveau, ce que le projet montre et preuve.
CompétenceNiveauCe que le projet montre, et preuve
RéaliserRéaliser un développement d’applicationNiveau 1Développer une application à partir d’une conception objet.Preuve : Cinq classes C++ écrites pour le jeu (Personnage, Niveau, Objet, Tuile, Dictionnaire), attributs privés et accesseurs, au-dessus des classes Moteur et Image fournies.
OptimiserOptimiser des applicationsNiveau 1Analyser et améliorer le comportement d’un programme.Preuve : Affichage conditionnel et mise à jour des ennemis limitée à 8 par seconde.