EXAMEN LE384 Jeu "IL PLEUT DES TONNEAUX"
Transcription
EXAMEN LE384 Jeu "IL PLEUT DES TONNEAUX"
EXAMEN LE384
Jeu "IL PLEUT DES TONNEAUX"
dimx
dimy
P
angle
h = x * tan(angle)
x
Objectif du jeu : un personnage doit survivre dans un environnement hostile.
Principes du jeu :
• Des nuages circulent en haut de l'écran de gauche à droite. L'apparition des nuages à
gauche de l'écran se fera de manière aléatoire (à chaque itération du jeu, le hasard décidera
si un nouveau nuage apparaît ou non).
•
Des tonneaux tombent des nuages puis, arrivés à terre, roulent sur le plan incliné de droite
à gauche. Nous rappelons que pour un point P du plan incliné (avec un angle de valeur
"angle") qui a comme abscisse la valeur x, sa hauteur h vaudra h=x*tan(angle). La
fonction tangente est déclarée sous la forme double tan(double) dans le fichier
math.h.
•
Lorsqu'il apparaît à gauche de l'écran, un nuage contient un et un seul tonneau. Il peut
larguer son tonneau à tout moment (à chaque itération du jeu, le hasard décidera s'il doit ou
non larguer son tonneau). Lorsqu'il arrive à droite de l'écran, il a obligation de le larguer s'il
ne l'a toujours pas fait. Lorsqu'un nuage a largué son tonneau, il doit changer de couleur.
•
Le joueur doit éviter les tonneaux qu'ils soient encore en l'air ou qu'ils roulent sur le plan.
Pour cela, le personnage peut soit se déplacer à gauche ou à droite soit sauter en l'air. Si le
personnage est en l'air, il ne peut pas se déplacer à gauche ou à droite. Il ne reste en l'air
qu'un certain temps (un certain nombre d'itérations du jeu).
Mise en oeuvre : Dans la page suivante, nous avons écrit la fonction principale du jeu. L'objectif de
l'examen sera d'écrire les structures et quelques unes des fonctions nécessaires à son fonctionnement
à partir de l'analyse de la fonction principale proposée (nous vous conseillons aussi de lire toutes les
questions avant de vous lancer) et de vos connaissances acquises durant le projet.
Remarque importante : Vous pouvez définir des procédures ou des fonctions qui ne sont pas
demandées, mais dont vous sentez qu’elles sont nécessaires pour répondre proprement à une
question.
/* programme principal */
int main()
{
char c; int termine=0;
int dimx=500, dimy=400; /* variables liées à la scène */
double angle=10; /* angle du plan incliné en degrés */
TONNEAUX *liste_tonneaux=NULL; /* variables liées aux tonneaux */
int vitesse_tonneau=4, rayon_tonneau=5;
NUAGES *liste_nuages=NULL; /* variables liées aux nuages */
int vitesse_nuage=5, taille_x_nuage=20, taille_y_nuage=10;
PERSONNAGE joueur; /* variables liées au personnage */
int taille_joueur_y=20, taille_joueur_x=10;
int vitesse_joueur_x=5;
int pos_init_x,pos_init_y;
int duree_saut=6; /* duree en nombre d'iterations d'un saut */
int saut=0;
GrInitGraphic("IL PLEUT DES TONNEAUX",0, 0, dimx, dimy, 2);
dessine_scene(dimx, dimy,angle); /* dessin du plan incliné */
/* position initiale du joueur,
au milieu de l'écran et sur le plan incliné */
pos_init_x= dimx/2 - taille_joueur_x/2;
pos_init_y= dimy – (pos_init_x+taille_joueur_x)*tan(angle/180*3.1415) –
taille_joueur_y;
init_joueur(&joueur,pos_init_x,pos_init_y,taille_joueur_x,
taille_joueur_y,vitesse_joueur_x);
dessine_joueur(joueur);/* dessin du joueur à sa position initiale*/
while(!termine)
{
c=GrGetChar();
if (c!=0)
/* Gestion du caractère tapé au clavier */
{
switch (c)
{
case 'a' :
/* aller à gauche */
joueur_bouge(joueur,saut,angle,dimx,dimy,0); break;
case 'z' :
/* à droite */
joueur_bouge(joueur,saut,angle,dimx,dimy,1); break;
case ' ' :
/* saute */
saut=( saut>0 ? saut : duree_saut ); break;
case 'q' :
/* quitter le programme */
termine = 1; break;
}
}
joueur_saute(joueur,saut,rayon_tonneau);
saut=( saut>0 ? saut-1 : 0 );
liste_nuages=nuages_creer_nouveau(liste_nuages,vitesse_nuage,
taille_x_nuage,taille_y_nuage);
liste_tonneaux=tonneaux_bougent(liste_tonneaux,vitesse_tonneau,
angle,dimx,dimy);
liste_nuages=nuages_bougent(liste_nuages,&liste_tonneaux,
vitesse_tonneau,rayon_tonneau,dimx);
dessine_tonneaux(liste_tonneaux);
dessine_nuages(liste_nuages);
dessine_joueur(joueur);
collision=collision_pers(joueur,liste_tonneaux);
if (collision)
{printf(“perdu\n”);termine=1;}
GrSleep(5);
}
libere_all(&liste_tonneaux,&liste_nuages); GrCloseGraphic();
}
QUESTIONS
Vous n'avez pas à gérer l'affichage des éléments du jeu : vous supposerez donc connues les
fonctions suivantes :
– void dessine_scene(int dimx, int dimy, double angle); /* dessine
le plan incliné*/
– void dessine_un_nuage(int x, int y, int x_prec, int y_prec,
int taillex, int tailley, int couleur); /* efface un nuage à la position
précédente, et dessine un nuage à la position courante (x,y) – la couleur sera rouge si la
variable couleur vaut 1 et bleu sinon */
– void dessine_un_tonneau(int x, int y, int x_prec, int y_prec,
int rayon); /* efface un tonneau à la position précédente, et dessine un tonneau à la
position courante (x,y) */
– void dessine_joueur(PERSONNAGE joueur); /* efface le joueur à la position
précédente, et dessine le joueur à la position courante */
I. Gestion du joueur
1. A partir de l'analyse de la fonction principale, écrire la structure de type synonyme
PERSONNAGE.
2. Ecrire la fonction init_joueur qui fixe la position initiale du joueur. Le schéma cidessous illustre les calculs réalisés dans la fonction principale pour fixer cette position aux
coordonnées(pos_init_x,pos_init_y)qui
correspondent
aux
coordonnées
supérieures gauche du joueur.
(pos_init_x,pos_init_y)
taille_joueur_y
taille_joueur_x
dimx/2
3. Ecrire la fonction joueur_bouge qui bougera la position du joueur de
vitesse_joueur_x pixels à droite ou à gauche (en fonction de la valeur de la dernière
variable passée en argument d'entrée), seulement si celui-ci n'est pas en train de sauter
(saut vaut 0 si le joueur n'est pas en train de sauter), sachant que la position en y est
conditionnée par sa position en x et par la pente du plateau incliné (cf. dessin ci-dessus et
celui de la première page).
4. Ecrire la fonction joueur_saute qui fait en sorte que le joueur n'ait plus les pieds à terre
mais à 2*rayon_tonneau au dessus, si celui-ci est en train de sauter.
II. Gestion des tonneaux
5. A partir de l'analyse de la fonction principale, écrire la structure de type synonyme
TONNEAUX, sachant également que les nuages devront être gérés via une liste chaînée.
6. Ecrire la fonction tonneaux_bougent, sachant que si un tonneau est au dessus du plan
incliné (à noter que, lors de la création du tonneau, il est forcément en mode "tombe"), il
tombe à une vitesse donnée (vitesse_tonneau, valeur qui devra être incluse dans un
champ de la structure). Juste avant qu'il ne passe sous le plan incliné, il passe en mode
"roule". Dans ce mode, il roulera sur le plan incliné, de droite à gauche (avec une vitesse
vitesse_tonneau mais selon x à présent). Pour simplifier le traitement, on pourra
ajouter à la structure TONNEAUX, une variable qui indiquera si le tonneau tombe ou roule.
Bien entendu, si un tonneau sort de l'écran, il est supprimé de la liste chaînée.
7. Ecrire une fonction dessine_tonneaux qui dessinera tous les tonneaux en utilisant la
fonction dessine_un_tonneau.
8. Ecrire la fonction collision_pers qui testera s'il y a collision entre un tonneau et le
personnage si c'est le cas la fonction renverra la valeur 1 (ou 0 sinon).
III. Gestion des nuages
Nous vous fournisons la fonction suivante qui renvoie 1 si un nouveau nuage doit apparaître ou 0
sinon (la variable pourcentage définit le nombre de chance/100 de voir un nouveau nuage
apparaître par itération ; elle pourra être fixée à 10) :
int apparition_ou_pas(int pourcentage)
{
int tirage=GrRand(100);
if (tirage<=pourcentage) return 1; else return 0;
}
9. A partir de l'analyse de la fonction principale, écrire la structure de type synonyme NUAGES,
sachant également que les nuages devront être gérées via une liste chaînée.
10. Ecrire la fonction nuages_creer_nouveau qui créera éventuellement un nouveau
nuage à gauche de l'écran et l'ajoutera à la liste chaînée. On ne se préoccupera pas de la
superposition graphique possible des nuages.
11. Ecrire la fonction nuages_bougent qui déplacera tous les nuages. Pour chaque nuage
qui contient encore un tonneau, on testera si celui-ci doit ou non le larguer (on pourra
utiliser la fonction apparition_ou_pas avec un pourcentage faible, par exemple la
valeur 1). On rappelle que, si le nuage arrive tout à droite de l'écran, il a obligation de larger
son tonneau (s'il en "possède" encore) puis est supprimé de la liste. Le largage d'un tonneau
consistera à en créer un nouveau à la position du nuage et à l'ajouter à la liste chaînée.
IV. Organisation du projet
12. Comment organiseriez-vous vos structures et fonctions ? Dans quels fichiers ? Ecrire les
fichiers ".h" correspondant (ainsi que le début du fichier principal ; tout ce qui précédera la
fonction main) et un makefile.