Sujet de projet - FR

publicité
Introduction à la programmation orientée objets avec C# et .net
Projet Space Invaders
Benjamin Perret
28 novembre 2016
Le but de ce projet est de reproduire un des grands classiques du jeu vidéo : Space Invaders ! Space
Invaders est un shoot’em up où le principe est de détruire des vagues d’aliens au moyen d’un canon
en se déplaçant horizontalement sur l’écran. https://youtu.be/437Ld_rKM2s?t=43
Table des matières
1 Travail demandé
1
2 Démarrage
2.1 Comprendre la structure d’un programme animé . . . . . . . . . . . . . . . . . . . . .
2.2 Classe utilitaire Vecteur2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 Suite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2
2
2
3 Cahier des charges fonctionnel
3.1 Éléments fondamentaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Addons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
4
4 Qualité de code
5
5 Éléments de spécification détaillés et
5.1 Gestions des sprites . . . . . . . . .
5.2 Diagramme d’état du jeu . . . . . .
5.3 Test de collision . . . . . . . . . . . .
1
aide
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
6
6
Travail demandé
Éléments de notation : L’évaluation porte sur le travail personnel de l’étudiant et porte sur 2
éléments :
— le code source du logiciel développé,
— le rapport de projet.
Rapport : Le rapport fera au maximum 5 pages. Il devra contenir :
— une description succincte du problème,
— une description de la structure de votre programme permettant de comprendre son fonctionnement,
— une présentation des problèmes soulevés par les tests : analyse de l’origine du problème, de la
solution trouvée ou des idées de solutions (si le problème n’a pas été résolu).
1
Barème :
— Environ 1/2 des points sur les éléments fonctionnels (Section 3)
— Environ 1/4 des points sur la qualité du code (Section 4).
— Environ 1/4 des points sur le rapport : qualité de la rédaction, analyse du sujet, analyse des
problèmes.
Modalité de rendu : Votre dêpot SVN devra contenir les éléments suivants :
— votre projet au format Visual Studio écrit en langage C#,
— un rapport (format pdf).
Le contenu de votre dépôt SVN sera téléchargé à la fin de cette période école (date exacte précisée
par mail) et constituera votre rendu de projet.
Il est fortement recommandé de réaliser un checkout de votre dépôt avant la date limite et sur une
autre machine que celle que vous avez utilisée pendant vos développements afin de vérifier que celui-ci
est complet, que votre projet compile et s’exécute correctement. Tout évènement menant à un retard
de rendu (par exemple dépôt SVN incomplet à la date limite) entrainera une pénalité de 2n−1 points
(avec n le nombre de jours de retard).
Plagiat : La récupération de code chez une tierce personne, qu’il s’agisse d’un étudiant ou d’un site
internet, n’est permise qu’avec citation de la source dans le code et dans le rapport. Le code utilisé
avec citation des sources n’est pas considéré comme le résultat du travail de l’étudiant. Un code utilisé
sans référence à son auteur est un code plagié. Le plagiat est interdit par le règlement intérieur de
l’école (Article 3).
2
2.1
Démarrage
Comprendre la structure d’un programme animé
Téléchargez le mini-projet Visual C# à cette adresse : http://www.esiee.fr/~perretb/E3FI/
SpaceInvaders.zip. Ce projet contient un squelette fonctionnel d’un programme interactif que vous
modifierez et complèterez tout au long du projet.
Avant même d’ouvrir ce projet dans Visual Studio, ajoutez tous les fichiers qu’il contient sur
votre dépôt SVN et réalisez un commit. Pour le moment, le projet comporte trois classes organisées
(grossièrement) selon le schéma MVC :
— GameForm.cs : c’est la classe d’affichage (Vue) : elle représente la fenêtre de jeu.
— Game.cs : c’est elle qui contient les mécanismes fondamentaux du jeu (Contrôleur).
— BalleQuiTombe.cs : c’est un objet de "démonstration" (Modèle), il s’agit d’une balle qui ne
fait que tomber. Elle est capable de calculer l’évolution de sa position en fonction du temps qui
passe. Elle sait également se représenter (dessiner l’image qui la représente).
Questions de compréhension :
— Que faut-il modifier pour que la balle tombe plus lentement ou plus rapidement ?
— Ajoutez la gestion des touches "flèche gauche" et "flèche droite". Lorsque le joueur appuie sur une
des flèches, la balle (si elle existe) doit se déplacer dans la direction indiquée tout en continuant
à tomber.
2.2
Classe utilitaire Vecteur2D
Afin de faciliter la gestion des coordonnées et des déplacements, il est nécessaire de disposer d’un
type permettant de représenter des points et des vecteurs du plan et de réaliser des opérations basiques
(addition, multiplication par un scalaire. . . ). Comme .net ne propose pas de structure pour cela (il y
a la classe Point mais qui est en coordonnées entières) nous allons écrire une classe Vecteur2D.
2
Travail de programmation :
— Créez une classe Vecteur2D avec deux champs x et y de type double.
— Créez un constructeur paramétrique permettant d’initialiser les valeurs de x et de y. Mettez la
valeur par défaut 0 sur les deux paramètres.
— Ajoutez une propriété publique Norme de type double en lecture seule qui retourne la norme du
vecteur.
— Redéfinissez les opérateurs suivants :
— Vecteur2D + Vecteur2D : Addition vectorielle
— Vecteur2D – Vecteur2D : Soustraction vectorielle
— - Vecteur2D : Moins unaire
— Vecteur2D * double : Multiplication par un scalaire à droite
— double * Vecteur2D : Multiplication par un scalaire à gauche
— Vecteur2D / double : Division par un scalaire
2.3
Suite
Vous poursuivez l’implémentation selon le cahier des charges donnés ci-dessous avec 3 parcours
possibles :
1. Vous débutez en programmation orientée objet : vous suivez le guide étape par étape disponible
à cette adresse : http://www.esiee.fr/~perretb/E3FI/GuideEtapeParEtape.pdf.
2. Vous vous sentez à l’aise en programmation orientée objet : vous structurez vous-même votre
logiciel.
3. Vous maitrisez la programmation orientée objet : pour un peu de défi essayez-vous au modèle
Entité-Composant-Système http://www.richardlord.net/blog/what-is-an-entity-framework.
3
3.1
Cahier des charges fonctionnel
Éléments fondamentaux
Interface : elle est composée des éléments suivants (Figure 1) :
— le vaisseau du joueur ;
— une rangée de bunker ;
— les vaisseaux ennemis ;
— les missiles ;
— les vaisseaux, les bunkers et les missiles sont représentés à l’écran par des sprites/bitmap.
— le nombre de vies restantes du joueur.
Figure 1 – Interface du jeu : les éléments rouges ne font pas parti de l’interface.
3
Déplacement du joueur :
— Le vaisseau du joueur se déplace uniquement horizontalement.
— Le vaisseau du joueur ne peut pas sortir de l’écran.
— Le déplacement se fait au moyen des touches flèche gauche et flèche droite.
Bloc d’ennemis :
— Les ennemis sont organisés en un bloc.
— Le bloc est constitué de plusieurs lignes d’ennemis.
— Chaque ligne d’ennemis comprend un ou plusieurs vaisseaux du même type.
— Le bloc arrive par le haut de la fenêtre.
— Le bloc se déplace alternativement de gauche à droite et de droite à gauche.
— Le bloc change de direction dès qu’un des vaisseau du bloc arrive au bord de l’écran.
— Lorsque le bloc change de direction, il se décale vers le bas.
— Lorsque le bloc change de direction, sa vitesse de déplacement augmente.
Missiles :
— Les missiles se déplacent en ligne droite verticale : de haut en bas si tiré par un ennemis et de
bas en haut si c’est un missile du joueur.
— Les missiles des ennemis peuvent entrer en collision avec les bunkers et le vaisseau du joueur
(pas de friendly fire).
— Les missiles du joueur peuvent entrer en collision avec les bunkers et les vaisseaux ennemis.
— Les missiles sont détruits si ils sortent de l’écran.
— Le joueur tire avec la touche espace.
— Les ennemis tirent aléatoirement.
— La fréquence de tire des ennemis augmente lorsqu’ils se rapprochent du joueur.
— Le joueur ne peut tirer qu’un seul missile à la fois : lorsqu’il tire il doit attendre que le missile
soit détruit par une collision ou sorte de l’écran avant de pouvoir tirer à nouveau.
Vie et mort :
— Le joueur, les ennemis et les missiles possèdent chacun un nombre de vies.
— Un élément dont le nombre de vie est inférieur ou égal à zéro est détruit.
Collision missile-vaisseau :
— Un missile est en collision avec un vaisseau si un pixel noir de son sprite est sur un pixel noir
du sprite du vaisseau.
— Lorsqu’un missile touche un vaisseau, les nombres de vies du missile et du vaisseau sont décrémentés de la valeur minimum entre le nombre de vies du missile et du vaisseau.
Collision missile-bunker
— Un missile est en collision avec un bunker si un pixel noir de son sprite est sur un pixel noir du
sprite du vaisseau : un tel pixel est dit en collision.
— Tous les pixels en collision sont retirés du sprite du bunker : ils deviennent transparents et ne
peuvent plus participer à des collisions.
— Le nombre de vie du missile est décrémenté du nombre de pixels en collision.
Victoire
— Le
— Le
— Le
et défaite : La première des conditions suivantes qui survient met fin à la partie :
joueur gagne si il détruit tous les vaisseaux ennemis.
joueur perd si il est détruit.
joueur perd si le bloc d’ennemis atteint la hauteur du joueur.
4
Pause :
— Tant que la partie n’est pas terminée le joueur peut mettre le jeu en pause : pendant la pause
tous les déplacements et donc toute la dynamique du jeu est interrompue.
— En cours de jeu, le joueur passe ne pause avec la touche P.
— Lorsque le jeu est en pause, le joueur peut quitter la pause avec la même touche P.
3.2
Addons
Les addons seront pris en compte uniquement si tous les éléments fondamentaux fonctionnent.
Les addons ne sont pas complètements spécifiés et vous êtes libres de développer autour des thèmes
proposés ou de proposer de nouveaux thèmes.
Bonus
— La destruction d’un vaisseau ennemis a une probabilité de faire apparaitre un bonus.
— Le bonus est représenté par un sprite et de déplace du haut vers le bas.
— Si le vaisseau du joueur entre en collision avec le bonus il le récupère.
— Les bonus peuvent être de différentes natures : invincibilité temporaire, missile indestructible,
missile auto-guidé, tire multiple, vie bonus. . .
Affichage avancé
— Les sprites des différents éléments sont animés.
— Les actions de collisions génèrent des effets visuels (par exemple, explosion).
Son
— Le jeu est accompagné d’une musique en fond sonore.
— Les différentes actions produisent l’émission de sons spécifiques.
Système de niveaux
— Le jeu comporte plusieurs niveaux.
— Les niveaux sont codés dans des fichiers textes éditables.
— Le jeu propose un système de high score.
Multi-joueurs
— Plusieurs joueurs peuvent jouer simultanément sur la même machine.
— Plusieurs joueurs peuvent jouer simultanément en réseau.
4
Qualité de code
Environnement technique
— Le logiciel doit être compilable et exécutable sous la forme d’une solution Visual Studio sur les
machines de TP de l’école.
— Le logiciel doit être intégralement écrit en C#.
Structuration
— Le logiciel doit être structuré en utilisant les techniques de programmation orientée objets.
— Les éléments de langages vus en cours doivent être privilégié dès que cela est pertinent.
— Chaque classe doit correspondre à un composant bien identifié.
— Le rôle de chaque composant doit être clairement identifié.
— Tout ce qui correspond au rôle d’un composant doit être regroupé dans la classe le représentant.
5
Norme de codage
— Le code doit être correctement formaté selon les conventions disponibles à cette adresse : https:
//msdn.microsoft.com/fr-fr/library/ff926074.aspx.
— Une fonction ne doit pas contenir plus de 10 lignes de codes.
— Le copier/coller de code est interdit.
Explications et commentaires
— Tous les identificateurs, à l’exception des variables de boucles, doivent avoir un nom explicite
qui permet de comprendre leur utilité.
— Toutes les méthodes doivent être documentées : rôle de la méthode, description des paramètres,
description de la valeur de retour (voir https://msdn.microsoft.com/en-us/library/z04awywx.
aspx).
Gestion de sources
— Le dépôt sur le gestionnaire de source SVN de l’école ne devra pas contenir de résultats de
compilation (fichiers exécutables, fichiers objets, informations de débogage. . . ).
5
5.1
Éléments de spécification détaillés et aide
Gestions des sprites
Des images de vaisseaux/bunker/missile sont déjà incluses dans le projet SpaceInvaders (Menu
Projet → Propriétés → Ressources → Images). Ces images sont incluses dans l’exécutable généré à
partir de la solution et sont accessibles directement depuis le code :
Bitmap image =SpaceInvaders.Properties.Resources.ship3.
Pour dessiner une image image à la position x, y, utilisez la méthode DrawImage de l’objet
graphics.
5.2
Diagramme d’état du jeu
Le jeu peut être dans 4 états différents : en cours, en pause, gagné, perdu. Le diagramme d’état
indiquant les transitions possibles est le suivant :
5.3
Test de collision
Le test de collision entre 2 objets (missile/bunker ou missile/vaisseau) fait intervenir le calcul de
l’intersection entre deux sprites situés à des positions différentes. Pour des raisons de performances,
le test est effectué en 2 temps. On commence par tester si le rectangle englobant du bunker/vaisseau
intersecte le rectangle englobant du missile. Si ce n’est pas le cas, on sait qu’il n’y a pas de collision
possible, sinon il faut tester plus précisément.
6
Test des rectangles englobants
— les rectangles englobants sont disjoints ; aucune collision possible :
— les rectangles englobant s’intersectent ; on ne peut pas conclure :
Pour tester si deux rectangles s’intersectent, on considère qu’un rectangle est paramétré de la façon
suivante :
Si on dispose de deux rectangles (x1 , y1 , lx1 , ly1 ) et (x2 , y2 , lx2 , ly2 ), les deux rectangles sont disjoints
si
— x2 > x1 + lx1 : le deuxième rectangle est à droite du premier OU
— y2 > y1 + ly1 : le deuxième rectangle est haut dessus du premier OU
— x1 > x2 + lx2 : le premier rectangle est à droite du deuxième OU
— y1 > y2 + ly2 : le premier rectangle est haut dessus du deuxième.
Test pixel à pixel Si les rectangles englobant s’intersectent, il faut tester pixel par pixel si il y a une
intersection. On parcourt l’ensemble des pixels du missile et on calcule la position correspondante sur le
bunker/vaisseau (on connait la position du missile et du bunker/vaisseau par rapport au coin supérieur
gauche de la fenêtre, et on connait les coordonnées du pixel par rapport à la position du missile, on
peut donc en déduire les coordonnées du pixel par rapport à la position du bunker/vaisseau). Si le
pixel de l’image du bunker/vaisseau qui correspond est noir, il y a collision au niveau de ce pixel.
Le changement de repère, lorsque les axes sont alignés, est une opération simple. Imaginons que l’on
dispose de 2 repères. On connait la position du deuxième repère par rapport au premier (Ox , Oy ). On
connait la position d’un point P dans le second repère (Px0 , Py0 ) et on souhaite obtenir les coordonnées
de P dans le premier repère (Px , Py ). On a directement Px = Px0 + Ox et Py = Py0 + Oy .
7
Dans le cas qui nous intéresse il sera nécessaire d’effectuer deux changements de repères consécutifs :
1) du repère missile vers le repère écran, et 2) du repère écran vers le repère vaisseau/bunker.
Gestion des couleurs Les images fournies avec le projet possèdent une couche alpha pour gérer
la transparence. Les pixels noirs de l’image correspondent à la couleur (255,0,0,0) : du noir (0 pour
les 3 composantes rouge, verte et bleue) opaque (255 sur la composante alpha) alors que les pixels
en dehors du bunker/vaisseau/missile sont représentés par la couleur (0,255,255,255) : du blanc (255
pour les 3 composantes rouge, verte et bleue) transparent (0 sur la composante alpha).
8
Téléchargement