Jeu de pendu avec sdl, fmod et ttf

Soyez le premier à donner votre avis sur cette source.

Snippet vu 6 312 fois - Téléchargée 17 fois

Contenu du snippet

Voici un petit jeu programmé en C avec les librairies tierces SDL, FMOD et TTF.
La gestion du mot à trouvé se fait à l'aide d'un fichier contenant ici 100 mots. Bien évidemment, il est possible d'en ajouter, mais il faudra changer la valeur d'un des DEFINE dans le code (MAX_POSITION).

La bande son du jeu est une musique libre de droit, téléchargée sur le site http://www.jamendo.com, et les sons dans le jeu sont téléchargés sur le site http://www.findsounds.com (ce sont aussi des sons libre de droit).

Ce jeu est réalisé dans le cadre d'un examen (pour le graduat informatique) et est un bon exemple de l'utilisation de la SDL, ainsi que FMOD et TTF.

Dernière remarque, ce code est compiler avec Dev C++.

Ayant une archive compressé de plus de 1mo (10.4 Mo ici), je ne peux la faire télécharger par le biais de ce site. Cependant, si vous le désirez, vous pouvez télécharger l'archive contenant le code source et l'exécutable ici :

http://mypictures.site.voila.fr/pendu.zip

Source / Exemple :


/********************************************************************
  Fichier : main.c
  Auteur : Haimet Stéphane
  Crée le 19/11/08 à 18h05
  modifié le 30/11/08 à 19h29
  
  Description : Réalisation d'un jeu de pendu en 2D 
  utilisant les librairies tierces SDL pour la gestion de la 2D, 
  FMOD (pour la gestion du son) et la TTF pour la gestion 
  du texte, on a donc aussi la présence de plusieurs DLL dans
  le répertoire où ce fichier se trouve.

                                                                                                                                        • /
#include <stdlib.h> #include <stdio.h> #include <string.h> //Contient des fonctions pour les chaines #include <SDL/SDL.h> //Contient les fonctions de la SDL #include <FMOD/fmod.h> //Contient les fonctions de sonorité (FMOD) #include <SDL/SDL_ttf.h> //Contient les fonctions pour la gestion du texte //On crée des defines #define MIN_POSITION 1 //Utilisé pour le random (selection d'un mot dans le dictionnaire #define MAX_POSITION 100 //Nombre maxi de mot dans le dictionnaire //PROTOTYPES DES FONCTIONS void creerMotSecret(char *mot); void choixDeLAcceuil(SDL_Surface *ecran); int jouer(SDL_Surface *ecran); char recupererLettre(FSOUND_SAMPLE *erreur); void afficherEcranJeu(SDL_Surface *ecran,SDL_Surface *fondJeu, int longueur, char *motSecret, int coupFoireux, int *emplacementTrouve); int verificationLettreEntree(char *motSecret,int *emplacementTrouve,int longueurMotSecret, char lettreEntree, char *lettreTapee); int verificationVictoire(int longueurMotSecret, int *emplacementTrouve); void afficherVictoire(SDL_Surface *ecran, char *motSecret, int longueur); void afficherDefaite(SDL_Surface *ecran, char *motSecret, int longueur); /******************************************************************** FONCTION main
                                                                                                                                        • /
int main(int argc, char *argv[]) { //Déclaration des variables SDL SDL_Surface *ecran = NULL; //Déclaration de la surface //Jouer de la musique à l'accueil FSOUND_STREAM *musique = NULL; //pointeur vers une musique (qui sera lu en streaming) FSOUND_Init(44100,32,0) ; //Initialisation de FMOD (son) musique = FSOUND_Stream_Open("musique.mp3", FSOUND_LOOP_NORMAL, 0, 0); //On met la musique en varialbe FSOUND_Stream_SetLoopCount(musique, -1); FSOUND_Stream_Play(FSOUND_FREE, musique); //On jour la musique en streaming FSOUND_SetVolume(0, 80); //On baisse le volume pour le canal 0 (canal utilisé par la musique) //Initialisation de la SDL SDL_Init(SDL_INIT_VIDEO); //On crée notre icone SDL_WM_SetIcon(SDL_LoadBMP("icone.bmp"), NULL); //Initialisation de la librairie TTF TTF_Init(); //Initialisation de l'écran( écran de résolution 640*480...) ecran = SDL_SetVideoMode(640,480,32,SDL_HWSURFACE | SDL_DOUBLEBUF); //On donne un nom à notre fenetre SDL_WM_SetCaption("'Pendons nous dans les bois' v1.0 by Haimet.S", NULL); //On fait appele à la fonction qui accueil le choix que l'on fait choixDeLAcceuil(ecran); //Fermeture de TTF TTF_Quit(); //Fermeture de la SDL SDL_Quit(); //Fermeture de la musique de fond, et de FMOD FSOUND_Stream_Close(musique); FSOUND_Close() ; return EXIT_SUCCESS; /*Exit_success est une constante contenu dans stdlib qui annonce le bon déroulement du programme */ } /******************************************************************** FONCTION creerMotSecret
                                                                                                                                        • /
void creerMotSecret(char *mot) { //Déclaration de nos variables locales FILE *dictionnaire = NULL; int i = 0, positionMot = 0; //Ouverture du fichier en lecture seule dictionnaire = fopen("dictionnaire.dat","r"); //On prend un nombre aléatoire savoir la position du mot du dictionnaire que l'on veut //(nombre entre min_position et max_position) srand(time(NULL)); //Initialisation positionMot = (rand() % (MAX_POSITION - MIN_POSITION + 1)) + MIN_POSITION; //On chosit le mot du dico qui est à la position "positionMot" for(i = 0; i<positionMot; i++) { fgets(mot,1000,dictionnaire); } //Fermeture du fichier fclose(dictionnaire); return; //Fonction "void" donc on ne retourne rien } /******************************************************************** FONCTION CHOIX DE L'ACCUEIL
                                                                                                                                        • /
void choixDeLAcceuil(SDL_Surface *ecran) { //Variables locales int continuer = 1; int quitterJeu = 0; //Création de nos surfaces SDL_Surface *fondAccueil = NULL; SDL_Rect positionFondAccueil; //Contient la positin du fond //création de notre son FSOUND_SAMPLE *cri = NULL ; cri = FSOUND_Sample_Load(FSOUND_FREE, "cri.wav",0,0,0) ; //On initialise nos surfaces (sauf l'écran qui est déjà initialisé) et leurs fonds fondAccueil = SDL_LoadBMP("accueil.bmp"); positionFondAccueil.x = 0; positionFondAccueil.y = 0; //On colle le fond d'accueil sur l'écrand et on l'affiche (blit + flip) après avoir effacé l'écran SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format,0,0,0)); SDL_BlitSurface(fondAccueil,NULL,ecran,&positionFondAccueil); SDL_Flip(ecran); SDL_Event event; //On déclare une variable de type SDL_Event //Tant que continuer vaut 1, on passe dans cette boucle while (continuer) { SDL_WaitEvent(&event); //Ici on attend un événement switch(event.type) { case SDL_QUIT : //Si l'événement est de type Quitter, on sors de la boucle en mettant continuer à 0 continuer = 0; break; case SDL_KEYDOWN : //Si l'événement est un clique sur une touche switch(event.key.keysym.sym){ //Cette variable contient la touche sur laquelle on a cliqué case SDLK_RETURN : //Si on a cliqué sur la touche ENTER, on joue le son et on peut jouer FSOUND_PlaySound(FSOUND_FREE,cri) ; quitterJeu = jouer(ecran); //Si on nous renvoie 0, on quitte le programme if(quitterJeu == 1) { continuer = 0; } break; default : continuer = 1; break; } //fin du switch pour la récupération de la touche appuyée } } //Fermeture des surfaces SDL_FreeSurface(fondAccueil); //Fermeture du son FSOUND_Sample_Free(cri); } /******************************************************************** FONCTION JOUER
                                                                                                                                        • /
int jouer(SDL_Surface *ecran) { //Variable locale int coupFoireux = 0; char motSecret[50] = "", lettreTapee[30] = ""; int longueurMotSecret = 0; char lettreEntree = 0; int gagne = 0, perdu = 0; int emplacementTrouve[50]; int i = 0, trouve = 0; //Création de sons FSOUND_SAMPLE *erreur = NULL ; FSOUND_SAMPLE *sonGagne = NULL ; FSOUND_SAMPLE *sonPerdu = NULL ; erreur = FSOUND_Sample_Load(FSOUND_FREE, "erreur.wav",0,0,0) ; sonGagne = FSOUND_Sample_Load(FSOUND_FREE, "gagne.wav",0,0,0) ; sonPerdu = FSOUND_Sample_Load(FSOUND_FREE, "perdu.wav",0,0,0) ; //On initialise nos surfaces (sauf l'écran qui est déjà initialisé) et leurs positionnement SDL_Surface *fondJeu = NULL; SDL_Rect posFondJeu; //On donne une image à fondJeu et une position fondJeu = SDL_LoadBMP("fondJeu.bmp"); posFondJeu.x = 0; posFondJeu.y = 0; //On colle le fond d'accueil sur l'écrand et on l'affiche (blit + flip) après avoir effacé l'écran SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format,0,0,0)); SDL_BlitSurface(fondJeu,NULL,ecran,&posFondJeu); SDL_Flip(ecran); //appel de la fonction de création d'un mot, et récupération de la longueur du mot creerMotSecret(motSecret); longueurMotSecret = strlen(motSecret)-1; //On ne compte pas le \n de la chaine //Mise à zéro du tableau contenant les emplacement des lettres trouvée for(i = 0; i<50; i++) { emplacementTrouve[i] == 0; } //Tant qu'on a pas gagné et qu'on a pas perdu, on fait le code suivant while(gagne == 0 && perdu == 0) { //Fonction affichant les emplacement vide du mot secret afficherEcranJeu(ecran,fondJeu,longueurMotSecret, motSecret, coupFoireux, emplacementTrouve); //On récupère une lettre entrée lettreEntree = recupererLettre(erreur); //Si on a taper sur quitter (et donc renvoyé 0) on renvoie 0 if(lettreEntree == 0) { //Fermeture des sons FSOUND_Sample_Free(erreur); return(1); } else { //On va voir si la lettre renvoyée est la bonne trouve = verificationLettreEntree(motSecret,emplacementTrouve,longueurMotSecret, lettreEntree, lettreTapee); } //Si on a pas trouvé de lettre, on incrémente la variable coupFoireux if (trouve == 0) { coupFoireux ++; //Si on a 8 coups foireux, on affiche le fin de jeu if(coupFoireux == 8) { perdu = 1; break; } } //Si on a trouve, on regarde si on a gagne else if(trouve == 1) { gagne = verificationVictoire(longueurMotSecret, emplacementTrouve); } else { FSOUND_PlaySound(FSOUND_FREE,erreur); } } if(gagne == 1) { afficherVictoire(ecran, motSecret, longueurMotSecret); FSOUND_PlaySound(FSOUND_FREE,sonGagne); } else if(perdu == 1) { afficherDefaite(ecran, motSecret, longueurMotSecret); FSOUND_PlaySound(FSOUND_FREE,sonPerdu); } //On arrete le temps pour que le son de victoire ou défaite ait le temps de se jouer SDL_Delay(2000); //Fermeture des sons FSOUND_Sample_Free(erreur); FSOUND_Sample_Free(sonGagne); FSOUND_Sample_Free(sonPerdu); return(0); } /******************************************************************** FONCTION RECUPERE LETTRE
                                                                                                                                        • /
char recupererLettre(FSOUND_SAMPLE *erreur) { //Déclaration des variables locales int continuer = 1; SDL_Event event2; while (continuer) { SDL_WaitEvent(&event2); switch(event2.type) { //Si on quitte, on retourne 0 qui fait en sorte que le programme se termine en libérant toute la mémoire allouée case SDL_QUIT: return(0); break; case SDL_KEYDOWN : /*On récupère la touche sur laquelle on a appuyé et on renvoie la lettre correspondante Attention la SDL gère les claviers QWERTY, donc on fait en sorte de travailler avec un clavier AZERTY*/ switch(event2.key.keysym.sym) { case SDLK_q : return('A'); break; case SDLK_b : return('B'); break; case SDLK_c : return('C'); break; case SDLK_d : return('D'); break; case SDLK_e : return('E'); break; case SDLK_f : return('F'); break; case SDLK_g : return('G'); break; case SDLK_h : return('H'); break; case SDLK_i : return('I'); break; case SDLK_j : return('J'); break; case SDLK_k : return('K'); break; case SDLK_l : return('L'); break; case SDLK_SEMICOLON : return('M'); break; case SDLK_n : return('N'); break; case SDLK_o : return('O'); break; case SDLK_p : return('P'); break; case SDLK_a : return('Q'); break; case SDLK_r : return('R'); break; case SDLK_s : return('S'); break; case SDLK_t : return('T'); break; case SDLK_u : return('U'); break; case SDLK_v : return('V'); break; case SDLK_z : return('W'); break; case SDLK_x : return('X'); break; case SDLK_y : return('Y'); break; case SDLK_w : return('Z'); break; //Par défaut, on ne récupère rien mais on joue un son d'erreur default : FSOUND_PlaySound(FSOUND_FREE,erreur) ; continuer = 1; } } } } /******************************************************************** FONCTION AFFICHAGE EMPLACEMENT VIDE DU MOT SECRET
                                                                                                                                        • /
void afficherEcranJeu(SDL_Surface *ecran, SDL_Surface *fondJeu, int longueur, char *motSecret, int coupFoireux, int *emplacementTrouve) { //Création de nos variable locales SDL_Surface *texte = NULL, *pendu = NULL; SDL_Color rouge = {255, 0, 0}; SDL_Rect position; TTF_Font *police = NULL; char motVide[50] = ""; int i = 0; //Création de la police police = TTF_OpenFont("bloody.ttf", 30); //On défini le texte qu'on va afficher for(i = 0; i<longueur; i++) { if(emplacementTrouve[i] == 1) { motVide[i] = motSecret[i]; } else { motVide[i] = '-'; } } //On donne une valeur à texte texte = TTF_RenderText_Blended(police, motVide, rouge); SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); position.x = 0; position.y = 0; SDL_BlitSurface(fondJeu, NULL, ecran, &position); /* Blit du fond */ position.x = 400; position.y = 280; SDL_BlitSurface(texte, NULL, ecran, &position); /* Blit du texte par-dessus */ //Si on a un au moins un coup foireux, on affiche le pendu if(coupFoireux>0) { position.x = 0; position.y = 0; switch(coupFoireux) { case 1 : pendu = SDL_LoadBMP("1.bmp"); break; case 2 : pendu = SDL_LoadBMP("2.bmp"); break; case 3 : pendu = SDL_LoadBMP("3.bmp"); break; case 4 : pendu = SDL_LoadBMP("4.bmp"); break; case 5 : pendu = SDL_LoadBMP("5.bmp"); break; case 6 : pendu = SDL_LoadBMP("6.bmp"); break; case 7 : pendu = SDL_LoadBMP("7.bmp"); break; } SDL_BlitSurface(pendu, NULL, ecran, &position); } SDL_Flip(ecran); //On ferme la police et la surface texte TTF_CloseFont(police); SDL_FreeSurface(texte); } /******************************************************************** FONCTION VERIFICATION LETTRE ENTREE
                                                                                                                                        • /
int verificationLettreEntree(char *motSecret,int *emplacementTrouve,int longueurMotSecret, char lettreEntree, char *lettreTapee) { int i = 0, trouve = 0, dejaTapee = 0, longueur = 0; //Calcul du nombre de lettre que l'on a dans lettreTape longueur = strlen(lettreTapee); //On passe le tableau de char en revue voir si on a déjà tapé la lettre entree for(i = 0; i<longueur; i++) { //Si on a déjà la lettre, on donne la valeur 1 à dejaTapee if(lettreTapee[i] == lettreEntree) { dejaTapee = 1; } } //Si la lettre n'est pas encore tapée : if(dejaTapee == 0) { //On enregistre la lettre tapee lettreTapee[i] = lettreEntree; //On regarde une par un les lettres du mot secret for(i = 0; i<longueurMotSecret; i++) { //Si la lettre entree a été trouvé à la lettre 2 par exemple, on note 1 dans // le tableau d'emplacement trouvé à l'indice 2 if(lettreEntree == motSecret[i]) { emplacementTrouve[i] = 1; trouve = 1; } } return(trouve); } //Si la lettre est déjà tapée, on renvoie 2 else { return(2); } } /******************************************************************** FONCTION VERIFICATION VICTOIRE
                                                                                                                                        • /
int verificationVictoire(int longueurMotSecret, int *emplacementTrouve) { int victoire = 1, i = 0; for(i = 0; i<longueurMotSecret; i++) { //Si un des éléments du tableau vaut 0, on renvoie victoire = 0 if(emplacementTrouve[i] != 1) { victoire = 0; } } return(victoire); } /******************************************************************** FONCTION AFFICHAGE VICTOIRE
                                                                                                                                        • /
void afficherVictoire(SDL_Surface *ecran, char *motSecret, int longueur) { //Déclaration des variables SDL_Surface *fondVictoire = NULL, *texteVictoire = NULL, *dessin = NULL; SDL_Rect position; TTF_Font *police = NULL; int i = 0; char mot[50] = ""; SDL_Color rouge = {255, 0, 0}; //On reforme le mot secret, car on à \n à la fin for(i = 0; i<longueur; i++) { mot[i] = motSecret[i]; } police = TTF_OpenFont("bloody.ttf", 30); //création de la police texteVictoire = TTF_RenderText_Blended(police, mot, rouge); //Création du texte //Affichage SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); //On efface l'écran fondVictoire = SDL_LoadBMP("gagne.bmp"); position.x = 0; position.y = 0; SDL_BlitSurface(fondVictoire,NULL,ecran,&position); dessin = SDL_LoadBMP("pasPendu.bmp"); position.x = 0; position.y = 0; SDL_BlitSurface(dessin, NULL, ecran, &position); position.x = 400; position.y = 280; SDL_BlitSurface(texteVictoire,NULL,ecran,&position); SDL_Flip(ecran); //On libère la mémoire SDL_FreeSurface(fondVictoire); SDL_FreeSurface(texteVictoire); SDL_FreeSurface(dessin); TTF_CloseFont(police); return; } /******************************************************************** FONCTION AFFICHAGE DEFAITE
                                                                                                                                        • /
void afficherDefaite(SDL_Surface *ecran, char *motSecret, int longueur) { //Déclaration des variables SDL_Surface *fondDefaite = NULL, *texteDefaite = NULL, *pendu = NULL; SDL_Rect position; TTF_Font *police = NULL; int i = 0; char mot[50] = ""; SDL_Color rouge = {255, 0, 0}; //On reforme le mot secret, car on à \n à la fin for(i = 0; i<longueur; i++) { mot[i] = motSecret[i]; } police = TTF_OpenFont("bloody.ttf", 30); //création de la police texteDefaite = TTF_RenderText_Blended(police, mot, rouge); //Création du texte //Affichage SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 0, 0, 0)); //On efface l'écran fondDefaite = SDL_LoadBMP("perdu.bmp"); position.x = 0; position.y = 0; SDL_BlitSurface(fondDefaite,NULL,ecran,&position); pendu = SDL_LoadBMP("8.bmp"); position.x = 0; position.y = 0; SDL_BlitSurface(pendu,NULL,ecran,&position); position.x = 400; position.y = 280; SDL_BlitSurface(texteDefaite,NULL,ecran,&position); SDL_Flip(ecran); //On libère la mémoire SDL_FreeSurface(fondDefaite); SDL_FreeSurface(texteDefaite); SDL_FreeSurface(pendu); TTF_CloseFont(police); return; }

Conclusion :


Enjoy

A voir également

Ajouter un commentaire

Commentaires

Messages postés
31
Date d'inscription
mardi 3 juillet 2007
Statut
Membre
Dernière intervention
4 mai 2009

Salut, je n'ai fait que survoler ton code, pas le lire attentivement et j'ai été rapidement impressionné par la longueur de ta source, tout ça dans un seul fichier, c'est peut-être beaucoup, je pense que tu aurait du séparer prototypes et définitions et placer touts ces élément dans des fichiers en les regroupant par thèmes.
D'autres part si pour changer la liste de mots, on doit modifier le code source cela ne donne pas quelque chose de très souple, je t'encourage à stocker MAX_POSITION dans un fichier(dans un autre fichier ou par exemple dans la première ligne du dico)
Messages postés
215
Date d'inscription
dimanche 20 février 2005
Statut
Membre
Dernière intervention
10 mars 2014

Slt bad_dark_spirit.
Rien qu'en mettant ton pseudo jsui fatigué :p
Bon j'ai quelques remarques:
- ton code est super lisible et très bien commenté, ca c'est es deux plus de ta source
- tes variables et fonctions sont bien nommées aussi (dans le prototype des fonction le nom des variables n'est pas nécessaire, le type suffit)

Quelques remarques sinon :
- dans ta fonction creerMotSecret, cette fonction pourrait retourner le mot, plutot que de prendre en paramètre de sortie.
- tu fais une lecture dna sle fichier mais si le fichier dictionnaire est court et ne contient pas assez d'éléments qu'est-ce qu'il se passe?

- dans ChoixDeLAccueil et dans d'autre, pourquoi "continuer" n'est pas un booléen? plutôt que de mettre un entier a 1 ou 0.
- ton default continuer=1 ne sert a rien caril est déjà a 1
# quitterJeu = jouer(ecran)
# if (quitterJeu == 1)

remplace par
# continuer = jouer(ecran)
avec jouer() qui retourne un booléen.

- dans jouer(), cette fonction pourrait retourner un boolée,
- perdu et gagne devraient aussi etre des booléen
- la variable emplacement trouvé devrait être un tableau dynamique d'entier, tableau du nombre de cas

- dans recupererLettre ton SQL_QUIT ne devrait pas retourner 0 mais null
- ta boucle devrait etre while (1), car tu ne peux jamais quitter la boucle hormis par un return donc ta variable continuer est inutile

- enfin dans verification, au lieu de
# victoire = 0
utilise return false;

En gros tu pourrais privilégier des booléen, eviter des tableaux contenant trop de cases (emplacementTrouve qui devrait avoir le meme nombre de cases que le mot).
Voila ce que je peux dire de beau sur cette source, mais en tout cas continue comme ca
++
Messages postés
21
Date d'inscription
vendredi 7 décembre 2012
Statut
Membre
Dernière intervention
3 janvier 2009

salut
merci pour le code j'avais bien besoin d'un comme ceci

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.