Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sounds in-game #76

Merged
merged 24 commits into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
5686dd2
feat: add sounds effects for pacman game
jvondermarck Jun 18, 2023
28be314
fix(ghost): segmentation fault of uninitialized variable
jvondermarck Jun 18, 2023
80e297f
feat: add new sounds
jvondermarck Jun 18, 2023
c76a737
feat(audio): implementation of audio class to manage the SLD_Mixer
jvondermarck Jun 18, 2023
0820776
feat(sdl-function): add method to init and load sounds from SDL_Mixer…
jvondermarck Jun 18, 2023
6209b96
feat(pacman): play dot sound when pacman eat a coin
jvondermarck Jun 18, 2023
2569094
feat: change implementation of the ready timer to have a different du…
jvondermarck Jun 18, 2023
8939813
feat(audio): quick changes to add a specific channel to play the dot …
jvondermarck Jun 18, 2023
35f673d
feat(menu): add pacman drill sound
jvondermarck Jun 18, 2023
3c1b04b
feat(game): add power up sound when pacman can eat ghost and siren sound
jvondermarck Jun 18, 2023
71120e7
feat(pause): add pause beat sound
jvondermarck Jun 18, 2023
6fc7d84
refactor(game-window): move setPause method to pause_menu.c file
jvondermarck Jun 18, 2023
b65c531
feat(pause): add pause sound before the pause beat when we pause the …
jvondermarck Jun 18, 2023
0c5bb0f
Merge branch 'main' into feat/74-add-sounds
jvondermarck Jun 18, 2023
cdef3c8
fix: add parameter to startReady function
jvondermarck Jun 18, 2023
e9c599a
feat: add death sound when pacman dies
jvondermarck Jun 18, 2023
e1eda0b
Merge branch 'main' into feat/74-add-sounds
jvondermarck Jun 18, 2023
a60129b
feat(pacman): stop siren when we play the death animation
jvondermarck Jun 18, 2023
41789c2
feat(audio): allocate a specific amount of channels and implement fru…
jvondermarck Jun 18, 2023
b7a4e67
fix(audio): try to reduce latency for the dot sounds when pacman eat …
jvondermarck Jun 18, 2023
b41624d
refactor(audio): update variable name to NO_LOOP to make it more unde…
jvondermarck Jun 19, 2023
522e72b
refactor(audio): change methods to play an audio that either loops or…
jvondermarck Jun 19, 2023
fe4084c
refactor(timer): add setter to set a callback and an initial count du…
jvondermarck Jun 19, 2023
fea26e1
refactor(timer): rename setter to duration rather than initial count
jvondermarck Jun 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/sounds/death.wav
Binary file not shown.
Binary file added assets/sounds/dot_1.wav
Binary file not shown.
Binary file added assets/sounds/dot_2.wav
Binary file not shown.
Binary file added assets/sounds/eat_ghost.wav
Binary file not shown.
Binary file added assets/sounds/eyes.wav
Binary file not shown.
Binary file added assets/sounds/fruit.wav
Binary file not shown.
Binary file added assets/sounds/game_start.wav
Binary file not shown.
Binary file added assets/sounds/pacman_drill.wav
Binary file not shown.
Binary file added assets/sounds/pause.wav
Binary file not shown.
Binary file added assets/sounds/pause_beat.wav
Binary file not shown.
Binary file added assets/sounds/power_up.wav
Binary file not shown.
Binary file added assets/sounds/siren_1.wav
Binary file not shown.
1 change: 1 addition & 0 deletions src/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#define GAME_TITLE "PacMan"

#define GAME_START_DURATION 800
#define READY_DURATION 300

#define CELL_SIZE 25
Expand Down
3 changes: 3 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#include "utilities/sdl_functions.h"
#include "ui/menu_window.h"
#include "models/audio.h"

int main(void)
{
initSDL();
initSDL_Mixer();

initAudio();
loadMedia();

startMenu();
Expand Down
124 changes: 124 additions & 0 deletions src/models/audio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//
// Created by Julien on 18/06/2023.
//

#include "audio.h"

Mix_Chunk *audioDeath = NULL;
Mix_Chunk *audioDotOne = NULL;
Mix_Chunk *audioDotTwo = NULL;
Mix_Chunk *audioEatGhost = NULL;
Mix_Chunk *audioEyes = NULL;
Mix_Chunk *audioFruit = NULL;
Mix_Chunk *audioGameStart = NULL;
Mix_Chunk *audioPacmanDrill = NULL;
Mix_Chunk *audioPause = NULL;
Mix_Chunk *audioPauseBeat = NULL;
Mix_Chunk *audioPowerUp = NULL;
Mix_Chunk *audioSirenOne = NULL;

bool isPowerUpPlaying = false;
bool isSirenPlaying = false;

void initAudio()
{
Mix_AllocateChannels(MAX_CHANNELS);

loadSound(&audioDeath, AUDIO_DEATH);
loadSound(&audioDotOne, AUDIO_DOT_1);
loadSound(&audioDotTwo, AUDIO_DOT_2);
loadSound(&audioEatGhost, AUDIO_EAT_GHOST);
loadSound(&audioEyes, AUDIO_EYES);
loadSound(&audioFruit, AUDIO_FRUIT);
loadSound(&audioGameStart, AUDIO_GAME_START);
loadSound(&audioPacmanDrill, AUDIO_PACMAN_DRILL);
loadSound(&audioPause, AUDIO_PAUSE);
loadSound(&audioPauseBeat, AUDIO_PAUSE_BEAT);
loadSound(&audioPowerUp, AUDIO_POWER_UP);
loadSound(&audioSirenOne, AUDIO_SIREN_1);
}

void playDotSound()
{
if (getEatenDotsCount() % 2 == 0) {
stopAudio(CHANNEL_DOT_2);
playAudioWithChannel(audioDotOne, CHANNEL_DOT);
}
else {
stopAudio(CHANNEL_DOT);
playAudioWithChannel(audioDotTwo, CHANNEL_DOT_2);
}
}

void stopSirenOrPowerUpSound()
{
stopAudio(CHANNEL_SIREN);
stopAudio(CHANNEL_POWER_UP);
isSirenPlaying = false;
isPowerUpPlaying = false;
}

void playSirenOrPowerUpSound()
{
if((pacmanDeathAnimationDelayTimer.isRunning || pacmanDeathAnimationTimer.isRunning)
|| nextRoundAnimationTimer.isRunning || readyTimer.isRunning || gameOverTimer.isRunning) {
stopSirenOrPowerUpSound();
return;
}

if (isGhostEatable()) {
if (!isPowerUpPlaying) {
playAudioWithChannelLoop(audioPowerUp, CHANNEL_POWER_UP);
isPowerUpPlaying = true;
}
if (isSirenPlaying) {
stopAudio(CHANNEL_SIREN);
isSirenPlaying = false;
}
} else {
if (!isSirenPlaying) {
playAudioWithChannelLoop(audioSirenOne, CHANNEL_SIREN);
isSirenPlaying = true;
}
if (isPowerUpPlaying) {
stopAudio(CHANNEL_POWER_UP);
isPowerUpPlaying = false;
}
}
}

void playAudioWithChannel(Mix_Chunk *sound, int channel)
{
Mix_PlayChannel(channel, sound, NO_LOOP);
}

void playAudioWithChannelLoop(Mix_Chunk *sound, int channel)
{
Mix_PlayChannel(channel, sound, LOOP_INFINITE);
}

void volumeAudio(Mix_Chunk *sound, int volume)
{
if(volume > 0 && volume <= MIX_MAX_VOLUME)
Mix_VolumeChunk(sound, volume);
}

void stopAudio(int channel) {
Mix_HaltChannel(channel);
}

void freeAudios()
{
freeSound(audioDotOne);
freeSound(audioDotTwo);
freeSound(audioGameStart);
freeSound(audioPacmanDrill);
freeSound(audioPause);
freeSound(audioPauseBeat);
freeSound(audioPowerUp);
freeSound(audioSirenOne);
freeSound(audioDeath);
freeSound(audioEatGhost);
freeSound(audioEyes);
freeSound(audioFruit);
}
66 changes: 66 additions & 0 deletions src/models/audio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// Created by Julien on 18/06/2023.
//

#ifndef PACMAN_AUDIO_H
#define PACMAN_AUDIO_H

#include <SDL_mixer.h>
#include "../utilities/sdl_functions.h"
#include "game.h"

#define AUDIO_DEATH "../assets/sounds/death.wav"
#define AUDIO_DOT_1 "../assets/sounds/dot_1.wav"
#define AUDIO_DOT_2 "../assets/sounds/dot_2.wav"
#define AUDIO_EAT_GHOST "../assets/sounds/eat_ghost.wav"
#define AUDIO_EYES "../assets/sounds/eyes.wav"
#define AUDIO_FRUIT "../assets/sounds/fruit.wav"
#define AUDIO_GAME_START "../assets/sounds/game_start.wav"
#define AUDIO_PACMAN_DRILL "../assets/sounds/pacman_drill.wav"
#define AUDIO_PAUSE "../assets/sounds/pause.wav"
#define AUDIO_PAUSE_BEAT "../assets/sounds/pause_beat.wav"
#define AUDIO_POWER_UP "../assets/sounds/power_up.wav"
#define AUDIO_SIREN_1 "../assets/sounds/siren_1.wav"

#define CHANNEL_DEFAULT (-1)
#define MAX_CHANNELS 13
#define CHANNEL_PACMAN_DRILL 1
#define CHANNEL_GAME_START 2
#define CHANNEL_DOT 3
#define CHANNEL_SIREN 4
#define CHANNEL_POWER_UP 5
#define CHANNEL_PAUSE_BEAT 6
#define CHANNEL_PAUSE 7
#define CHANNEL_EAT_GHOST 8
#define CHANNEL_EYES 9
#define CHANNEL_FRUIT 10
#define CHANNEL_DEATH 11
#define CHANNEL_DOT_2 12

#define NO_LOOP 0
#define LOOP_INFINITE (-1)

extern Mix_Chunk *audioDeath;
extern Mix_Chunk *audioDotOne;
extern Mix_Chunk *audioDotTwo;
extern Mix_Chunk *audioEatGhost;
extern Mix_Chunk *audioEyes;
extern Mix_Chunk *audioFruit;
extern Mix_Chunk *audioGameStart;
extern Mix_Chunk *audioPacmanDrill;
extern Mix_Chunk *audioPause;
extern Mix_Chunk *audioPauseBeat;
extern Mix_Chunk *audioPowerUp;
extern Mix_Chunk *audioSirenOne;

void initAudio();
void playAudioWithChannelLoop(Mix_Chunk *sound, int channel);
void playAudioWithChannel(Mix_Chunk *sound, int channel);
void volumeAudio(Mix_Chunk *sound, int volume);
void playDotSound();
void playSirenOrPowerUpSound();
void stopSirenOrPowerUpSound();
void stopAudio(int channel);
void freeAudios();

#endif //PACMAN_AUDIO_H
2 changes: 2 additions & 0 deletions src/models/fruit.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ int getFruitLevel() {

void handleFruitCollision() {
stopTimer(&fruitTimer);

playAudioWithChannel(audioFruit, CHANNEL_FRUIT);
incrementScore(fruitPoints[fruitLevel]);

resetTimer(&fruitScoreAnimationTimer);
Expand Down
4 changes: 2 additions & 2 deletions src/models/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ void nextRound(){
void startNextRoundAnimation()
{
isGamePause = true;
nextRoundAnimationTimer.callback = &endNextRoundAnimation;
setTimerCallback(&nextRoundAnimationTimer, endNextRoundAnimation);
resetTimer(&nextRoundAnimationTimer);
startTimer(&nextRoundAnimationTimer);
}
Expand All @@ -107,7 +107,7 @@ void endNextRoundAnimation()
spawnPacman();
refillCoins();
resetEatenDotsCount();
startReady();
startReady(READY_DURATION);
}

int getEatenDotsCount() {
Expand Down
1 change: 1 addition & 0 deletions src/models/ghost.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void initGhostList()
ghostList[i].gridPosition.x = 0;
ghostList[i].gridPosition.y = 0;
ghostList[i].ghostElement = i + '0';
ghostList[i].direction = DIRECTION_RIGHT;

// Sprites :
ghostList[i].rects = malloc(sizeof(SDL_Rect) * DIRECTION_COUNT);
Expand Down
26 changes: 13 additions & 13 deletions src/models/pacman.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ struct Position onPacmanGridMove(struct Position *pacmanUiPos)
case RIGHT_TELEPORTER:
return teleportPacman(LEFT_TELEPORTER);
case SMALL_COIN:
playDotSound();
incrementScore(10);
setMazeElementAt(pacmanGridPos, EMPTY);
handleCoinCollision();
Expand Down Expand Up @@ -260,14 +261,8 @@ void endEatGhostAnimation() {

void handleGhostCollision(MazeElement ghostElement)
{
if (isGhostEatable())
{
pacmanEatGhost(ghostElement);
}
else
{
killPacman();
}
if (isGhostEatable()) pacmanEatGhost(ghostElement);
else killPacman();
}

void killPacman()
Expand All @@ -284,9 +279,11 @@ void pacmanEatGhost(MazeElement ghostElement)
setMazeElementAt(pacmanGridPos, PACMAN);
ghostEaten++;

playAudioWithChannel(audioEatGhost, CHANNEL_EAT_GHOST);

incrementScore(getEatenGhostScore(ghostEaten));

eatGhostAnimationTimer.callback = endEatGhostAnimation;
setTimerCallback(&eatGhostAnimationTimer, endEatGhostAnimation);

resetTimer(&eatGhostAnimationTimer);
startTimer(&eatGhostAnimationTimer);
Expand All @@ -297,8 +294,11 @@ void pacmanEatGhost(MazeElement ghostElement)

void startPacmanDeathAnimation() {

pacmanDeathAnimationDelayTimer.callback = endPacmanDeathDelay;
pacmanDeathAnimationTimer.callback = endPacmanDeathAnimation;
setTimerCallback(&pacmanDeathAnimationDelayTimer, endPacmanDeathDelay);
setTimerCallback(&pacmanDeathAnimationTimer, endPacmanDeathAnimation);

stopSirenOrPowerUpSound();
playAudioWithChannel(audioDeath, CHANNEL_DEATH);

isGamePause = true;

Expand Down Expand Up @@ -328,7 +328,7 @@ void afterPacmanDeath() {

if (getLives() <= 0)
{
gameOverTimer.callback = afterGameOverAnimation;
setTimerCallback(&gameOverTimer, afterGameOverAnimation);
resetTimer(&gameOverTimer);
startTimer(&gameOverTimer);
return;
Expand All @@ -337,7 +337,7 @@ void afterPacmanDeath() {
resetFruit();
spawnPacman();
spawnGhosts();
startReady();
startReady(READY_DURATION);

}

Expand Down
1 change: 1 addition & 0 deletions src/models/pacman.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "models/ghost.h"
#include "../ui/game_window.h"
#include "models/fruit.h"
#include "models/audio.h"

extern struct Position pacmanUIPos;

Expand Down
10 changes: 10 additions & 0 deletions src/models/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ void updateTimers()
}
}

void setDuration(struct Timer *timer, int duration)
{
timer->initialCount = duration;
}

void setTimerCallback(struct Timer *timer, TimerCallback callback)
{
timer->callback = callback;
}

void clearTimers()
{
for (int i = 0; i < timerCount; i++)
Expand Down
4 changes: 4 additions & 0 deletions src/models/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ void stopTimer(struct Timer *timer);

void resetTimer(struct Timer *timer);

void setDuration(struct Timer *timer, int duration);

void setTimerCallback(struct Timer *timer, TimerCallback callback);

void updateTimers();

void clearTimers();
Expand Down
Loading