Big Tuto SDL 2 : Rabidja v. 3.0
Chapitre 14 : Monte le son !
Tutoriel présenté par : Jérémie F. Bellanger (Jay81)
Ecriture : 2 novembre 2014
Dernière mise à jour : 11 novembre 2015
Prologue
Dans Rabidja... Personne ne vous entendra crier ! ![]()
Oui, c'est clair, y'a pas de son !
![]()
On va donc remédier à cela dès maintenant en rajoutant une jolie musique (de ma composition - on critique pas !
) et des effets sonores aussi appelés sounds Fx (ou effects). Mais si, vous savez ces petits bip, bip, blip, etc. ! ![]()
Allez, on est parti !
Nouveaux fichiers à ajouter au projet
Avant de commencer, il va nous falloir ajouter ces nouveaux fichiers à notre projet. Vous pourrez les télécharger dans l'archive ci-dessus. Là, copiez les dossier music et sounds dans votre projet. Bien sûr, si vous en avez, vous pouvez aussi utiliser vos propres fichiers (sachant que les miens sont sous copyright et restent utilisables uniquement dans le cadre de ce tuto - n'allez pas les vendre avec votre jeu
).
Passons maintenant au code ! Youpi ! ![]()
Le code
On va commencer par retourner dans notre fichier defs.h pour rajouter une petite enum qui nous permettra de choisir plus facilement le sound Fx à jouer. ![]()
Fichier : defs.h : Rajouter :
|
//Une enum pour la gestion des sons.
enum
{
BUMPER,
DESTROY,
JUMP,
STAR
};
|
Voilà, nous allons maintenant initialiser notre musique et nos sounds Fx dans la fonction loadGame() en faisant appel à loadSong() et loadSound() que nous allons écrire ensuite :
Fichier : init.c : Remplacer la fonction précédente par :
|
void loadGame(void)
{
//On charge les données pour la map
initMaps();
//On charge la feuille de sprites du monstre
initMonsterSprites();
//On charge la feuille de sprites (spritesheet) de notre héros
initPlayerSprites();
//On commence au premier niveau
SetValeurDuNiveau(1);
changeLevel();
/* On initialise les variables du jeu */
setNombreDeVies(3);
setNombreDetoiles(0);
/* On charge le HUD */
initHUD();
//On charge la musique
loadSong("music/Caviator.mp3");
/* On charge les sounds Fx */
loadSound();
}
|
Et le cleanup() classique avec cleanUpMusic() et freeSound(). ![]()
Fichier : init.c : Modifier :
|
void cleanup()
{
//Nettoie les sprites de la map
cleanMaps();
/* Libère le sprite du héros */
cleanPlayer();
/* Libère le sprite des monstres */
cleanMonsters();
//Libère le HUD
cleanHUD();
/* Ferme la prise en charge du joystick */
closeJoystick();
/* On libère la musique */
cleanUpMusic();
//On libère les sons
freeSound();
//On quitte SDL_Mixer 2 et on décharge la mémoire
Mix_CloseAudio();
Mix_Quit();
.....
|
On passe maintenant au son ! ![]()
On va, en effet, créer un nouveau fichier sounds.c dans lequel nous allons écrire toutes nos fonctions relatives à la musique et aux effets sonores.
Rassurez-vous, là encore, elles sont simples. ![]()
Fichier : sounds.c : Créer le fichier et y copier :
|
#include "prototypes.h"
//Sounds Fx
Mix_Chunk *bumper_sound, *destroy_sound, *jump_sound, *star_sound;
//Musique
Mix_Music *musique;
void loadSong(char filename[200])
{
/* On libère la chanson précédente s'il y en a une */
if (musique != NULL)
{
Mix_HaltMusic();
Mix_FreeMusic(musique);
}
/* On charge la nouvelle chanson */
musique = Mix_LoadMUS(filename);
if (musique == NULL)
{
fprintf(stderr, "Can't read the music \n");
exit(1);
}
/* On active la répétition de la musique à l'infini */
if (Mix_PlayMusic(musique, -1) == -1)
{
printf("Mix_PlayMusic: %s\n", Mix_GetError());
}
}
void cleanUpMusic(void)
{
/* On libère la musique */
if (musique != NULL)
Mix_FreeMusic(musique);
}
void loadSound(void)
{
bumper_sound = Mix_LoadWAV("sounds/bumper.wav");
if (bumper_sound == NULL)
{
fprintf(stderr, "Can't read the bumper sound FX \n");
exit(1);
}
destroy_sound = Mix_LoadWAV("sounds/destroy.wav");
if (destroy_sound == NULL)
{
fprintf(stderr, "Can't read the destroy sound FX \n");
exit(1);
}
jump_sound = Mix_LoadWAV("sounds/jump.wav");
if (jump_sound == NULL)
{
fprintf(stderr, "Can't read the jump sound FX \n");
exit(1);
}
star_sound = Mix_LoadWAV("sounds/star.wav");
if (star_sound == NULL)
{
fprintf(stderr, "Can't read the star sound FX \n");
exit(1);
}
}
void freeSound(void)
{
Mix_FreeChunk(bumper_sound);
Mix_FreeChunk(destroy_sound);
Mix_FreeChunk(jump_sound);
Mix_FreeChunk(star_sound);
}
void playSoundFx(int type)
{
switch (type)
{
case BUMPER:
Mix_PlayChannel(-1, bumper_sound, 0);
break;
case DESTROY:
Mix_PlayChannel(-1, destroy_sound, 0);
break;
case JUMP:
Mix_PlayChannel(-1, jump_sound, 0);
break;
case STAR:
Mix_PlayChannel(-1, star_sound, 0);
break;
}
}
|
On voit donc qu'on crée d'abord des variables pour contenir nos sounds Fx et notre musique.
La fonction loadSong() charge la musique qu'on lui indique et la joue (tout en vérifiant s'il n'y en avait pas déjà une en cours avant).
cleanUpMusic() la décharge, au contraire.
Même principe pour les sounds Fx, sauf que, contrairement à la musique, on ne va pas les jouer en boucle (sinon, bonjour la caca-phonie !
). On crée donc une fonction playSoundFx() à qui on enverra une de nos enums pour jouer le bon sound Fx quand il faudra!
Bon, là, on n'en a que 4 mais rien ne vous empêche d'en rajouter autant que vous voudrez ! ![]()
Voilà, maintenant que notre gestion du son est en place, il ne nous reste plus qu'à faire appel à playSoundFx() quand on en a besoin! Et on va commencer dans le fichier monster.c en rajoutant le son DESTROY à la mort de celui-ci :
Fichier : monster.c : Modifier updateMonsters() - vers la fin de la fonction :
|
else if (collide(getPlayer(), &monster[i]) == 2)
{
//On met le timer à 1 pour tuer le monstre intantanément
monster[i].timerMort = 1;
playSoundFx(DESTROY);
}
|
Idem pour le joueur, dans le fichier player.c et dans les fonctions killPlayer() et playerHurts()
:
Fichier : player.c : Modifier killPlayer() et playerHurts() :
|
void killPlayer(void)
{
//On met le timer à 1 pour tuer le joueur intantanément
player.timerMort = 1;
//On joue le son
playSoundFx(DESTROY);
}
void playerHurts(GameObject *monster)
{
//Si le timer d'invincibilité est à 0
//on perd un coeur
if (player.invincibleTimer == 0)
{
player.life--;
player.invincibleTimer = 80;
//On joue le son
playSoundFx(DESTROY);
monster->timerMort = 1;
player.dirY = -JUMP_HEIGHT;
}
}
|
Voilà, on passe ensuite dans la fonction updatePlayer(), pour rajouter le sound Fx du saut, à la fois pour le saut normal et le double jump :
Fichier : player.c : Modifier updatePlayer() :
|
//Et voici la fonction de saut très simple :
//Si on appuie sur la touche saut et qu'on est sur le sol, alors on attribue une valeur
//négative au vecteur Y
//parce que sauter veut dire se rapprocher du haut de l'écran et donc de y=0.
if (input->jump == 1)
{
if (player.onGround == 1)
{
player.dirY = -JUMP_HEIGHT;
player.onGround = 0;
player.jump = 1;
playSoundFx(JUMP);
}
/* Si on est en saut 1, on peut faire un deuxième bond et on remet jump1 à 0 */
else if (player.jump == 1)
{
player.dirY = -JUMP_HEIGHT;
player.jump = 0;
playSoundFx(JUMP);
}
input->jump = 0;
}
|
Eh voilà, c'est tout pour nos sounds Fx maintenant !![]()
On utilisera les autres dans la suite de ce tuto, rassurez-vous ! ![]()
Plus qu'à mettre à jour notre catalogue de prototypes :
Fichier : prototypes.h : Remplacez par :
|
#ifndef PROTOTYPES
#define PROTOTYPES
#include "structs.h"
/* Catalogue des prototypes des fonctions utilisées.
On le complétera au fur et à mesure. */
extern void centerScrollingOnPlayer(void);
extern void changeLevel(void);
extern int checkFall(GameObject monster);
extern void cleanHUD(void);
extern void cleanMaps(void);
extern void cleanMonsters(void);
extern void cleanPlayer(void);
extern void cleanup(void);
extern void cleanUpMusic(void);
extern void closeFont(void);
extern void closeJoystick(void);
extern int collide(GameObject *player, GameObject *monster);
extern void delay(unsigned int frameLimit);
extern void drawGame(void);
extern void drawHud(void);
extern void drawImage(SDL_Texture *, int, int);
extern void drawMap(int);
extern void drawMonster(GameObject *entity);
extern void drawPlayer(void);
extern void drawString(char *text, int x, int y, int r, int g, int b, int a);
extern void drawTile(SDL_Texture *image, int destx, int desty, int srcx, int srcy);
extern void freeSound(void);
extern void gestionInputs(Input *input);
extern SDL_Texture *getBackground(void);
extern int getBeginX(void);
extern int getBeginY(void);
extern void getInput(Input *input);
extern void getJoystick(Input *input);
extern int getLevel(void);
extern int getLife(void);
extern int getMaxX(void);
extern int getMaxY(void);
extern GameObject *getMonster(int nombre);
extern int getMonsterNumber(void);
extern int getNombreDetoiles(void);
extern int getNombreDeVies(void);
extern GameObject *getPlayer(void);
extern int getPlayerDirection(void);
extern int getPlayerx(void);
extern int getPlayery(void);
extern SDL_Renderer *getrenderer(void);
extern int getStartX(void);
extern int getStartY(void);
extern SDL_Texture *getTileSetA(void);
extern SDL_Texture *getTileSetB(void);
extern int getTileValue(int y, int x);
extern void init(char *);
extern void initHUD(void);
extern void initMaps(void);
extern void initializeNewMonster(int x, int y);
extern void initMonsterSprites(void);
extern void initPlayerSprites(void);
extern void initializePlayer(int newLevel);
extern void killPlayer(void);
extern void loadFont(char *, int);
extern void loadGame(void);
extern SDL_Texture *loadImage(char *name);
extern void loadMap(char *name);
extern void loadSong(char filename[200]);
extern void loadSound(void);
extern void mapCollision(GameObject *entity);
extern void monsterCollisionToMap(GameObject *entity);
extern void openJoystick(void);
extern void playerHurts(GameObject *monster);
extern void playSoundFx(int type);
extern void resetMonsters(void);
extern void setNombreDeVies(int valeur);
extern void setNombreDetoiles(int valeur);
extern void setStartX(int valeur);
extern void setStartY(int valeur);
extern void SetValeurDuNiveau(int valeur);
extern void updateMonsters();
extern void updatePlayer(Input *input);
#endif
|
Voilà, on compile et on lance le programme !
Et ?! Y'a du son !!
Hourra !
On va pouvoir entendre crier notre lapin ! ![]()
Bon, allez, je vous laisse sur un petit screenshot qui vous en dit long sur la musique de folie qui passe en arrière-plan, et je vous dis à bientôt ! ![]()

@ bientôt pour le chapitre 15 ! ![]()
Jay

English
Français 
