Merge branch 'master' of gitlab.iut-clermont.uca.fr:/maribemont/projet-tut

merge-requests/1/merge
Mathis RIBEMONT 4 years ago
commit 1c28d17eb3

@ -2059,7 +2059,7 @@ ENABLE_PREPROCESSING = YES
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = NO MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and # the macro expansion is limited to the macros specified with the PREDEFINED and
@ -2067,7 +2067,7 @@ MACRO_EXPANSION = NO
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES, the include files in the # If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found. # INCLUDE_PATH will be searched if a #include is found.

@ -6,6 +6,9 @@
#include "engine/TextureHandler.h" #include "engine/TextureHandler.h"
#include "model/Game.h" #include "model/Game.h"
#include "view/GameDrawer.h" #include "view/GameDrawer.h"
#include "engine/ArrayUtils.h"
#include "model/arrayCoord.h"
#include "debug/printer.h"
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
@ -27,7 +30,7 @@ int main(int argc, char* argv[])
goto Quit; goto Quit;
} }
renderer = SDL_CreateRenderer(window,-1,0); renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);
if(!renderer) if(!renderer)
{ {
fprintf(stderr, "Erreur : %s", SDL_GetError()); fprintf(stderr, "Erreur : %s", SDL_GetError());
@ -35,19 +38,22 @@ int main(int argc, char* argv[])
} }
InputProcessor inputProcessor = {.selectedCase = {.x=-1, .y=-1}}; InputProcessor inputProcessor = {.selectedCase = {.x=-1, .y=-1}};
struct array_Coord interactiveCases = array_Coord_Create();
int wBoardRect=99*3, hBoardRect=99*3; int wBoardRect=99*3, hBoardRect=99*3;
SDL_Rect boardRect = {.x=windowSize.w/2 - wBoardRect/2, .y=windowSize.h/2 - hBoardRect/2, .w=wBoardRect, .h=99*3}; SDL_Rect boardRect = {.x=windowSize.w/2 - wBoardRect/2, .y=windowSize.h/2 - hBoardRect/2, .w=wBoardRect, .h=99*3};
const char* pseudos[] = {"Azerty","Bépo"}; const char* pseudos[] = {"Azerty","Bépo"};
Game game = newGame(2, pseudos); Game game = newGame(3, pseudos);
TextureHandler textureHandler = newTextureHandler(renderer); TextureHandler textureHandler = newTextureHandler(renderer);
bool quit = false; bool quit = false;
while(!quit) while(!quit)
{ {
// Event handling // Event handling
InputElement inputElement; InputElement inputElement;
while (InputType_None != (inputElement = proccessInput(&inputProcessor, &boardRect)).type) { while (InputType_None != (inputElement = proccessInput(&inputProcessor, &boardRect)).type) {
switch (inputElement.type) switch (inputElement.type)
{ {
case InputType_ActivateUI: case InputType_ActivateUI:
@ -66,22 +72,40 @@ int main(int argc, char* argv[])
break; break;
case InputType_MoveGame: case InputType_MoveGame:
fprintf(stderr, "Move on board\n"); fprintf(stderr, "Move on board\n");
fprintf(stderr, "From (%d; %d)\n", inputElement.data.move.start.x, inputElement.data.move.start.y);
fprintf(stderr, "To (%d; %d)\n", inputElement.data.move.end.x, inputElement.data.move.end.y);
moveOnBoard(inputElement.data.move.start, inputElement.data.move.end, &game); moveOnBoard(inputElement.data.move.start, inputElement.data.move.end, &game);
break; break;
case InputType_ClickGame: case InputType_ClickGame:
fprintf(stderr, "Clic on board (%d; %d)\n", inputElement.data.coord.x, inputElement.data.coord.y); fprintf(stderr, "Clic on board (%d; %d)\n", inputElement.data.coord.x, inputElement.data.coord.y);
fflush(stderr); fprintf(stderr, "\tSelected case : (%d; %d)\n", inputProcessor.selectedCase.x, inputProcessor.selectedCase.y);
if(!array_Coord_Contains(&interactiveCases, inputElement.data.coord, *coordEqual)) {
fprintf(stderr, "\tselected case reset\n");
inputProcessor.selectedCase = newCoord(-1,-1);
}
if (clickOnBoard(inputElement.data.coord, &game)) { if (clickOnBoard(inputElement.data.coord, &game)) {
fprintf(stderr, "\tselected case reset\n");
inputProcessor.selectedCase = newCoord(-1,-1); inputProcessor.selectedCase = newCoord(-1,-1);
} }
break; break;
case InputType_None: case InputType_None:
default: default:
break; break;
} }
array_Coord_Free(&interactiveCases);
interactiveCases = getInteractiveCases(&game, inputProcessor.selectedCase);
fprintf(stderr, "Interactive cases : {");
array_Coord_Foreach(&interactiveCases, *printCoord);
fprintf(stderr, "}\n");
} }
fflush(stderr);
// Drawing // Drawing
drawGame(renderer, &windowSize, &boardRect, &game, &textureHandler); drawGame(renderer, &windowSize, &boardRect, &game, &textureHandler);
@ -95,6 +119,7 @@ int main(int argc, char* argv[])
Quit: Quit:
freeTextureHandler(&textureHandler); freeTextureHandler(&textureHandler);
array_Coord_Free(&interactiveCases);
if(renderer != NULL) { if(renderer != NULL) {
SDL_DestroyRenderer(renderer); SDL_DestroyRenderer(renderer);
} }

@ -0,0 +1,8 @@
#ifndef PRINTER_INCLUDED
#define PRINTER_INCLUDED
#include <model/Coord.h>
void printCoord(const Coord coord);
#endif //PRINTER_INCLUDED

@ -0,0 +1,106 @@
/**
* \file ArrayUtils.h
* \brief This file define a macro used to generate dynamic array structs and associated functions
* \author Martin Rouault
* \date 3/01/2022
*/
#ifndef ARRAY_UTILS_INCLUDED
#define ARRAY_UTILS_INCLUDED
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
/**
* \brief Generate a dynamic array for type T
* If you want an int array use
* GENERATE_DYNAMIC_ARRAY(int)
* If you miss a function, write it with a type as int first then rewrite it in the macro
* You will need to follow function naming convetions to avoid multiple functions with the same name
* Functions in header must be marked as inline
* Don't forget antislashes
*/
#define GENERATE_DYNAMIC_ARRAY(T) \
struct array_##T { \
T* elems; \
size_t arraySize; \
size_t arraySpace; \
}; \
\
/*Contruct an empty array*/\
inline struct array_##T array_##T##_Create() { \
struct array_##T array = {.elems=NULL, .arraySize=0, .arraySpace=0}; \
return array; \
} \
\
/*Free an array*/ \
inline void array_##T##_Free(struct array_##T* array) { \
free(array->elems); \
array->elems = NULL; \
array->arraySize = 0; \
array->arraySpace = 0; \
} \
\
/*Reserve space for an array*/\
inline void array_##T##_Reserve(struct array_##T* array, const size_t space) { \
array->arraySpace = space; \
array->elems = realloc(array->elems, sizeof(T)*(array->arraySpace)); \
if (array->elems == NULL) exit(errno); \
} \
\
/*Fit space to size for an array*/\
inline void array_##T##_FitToSize(struct array_##T* array) { \
array->arraySpace = array->arraySize; \
array->elems = realloc(array->elems, sizeof(T)*(array->arraySpace)); \
if (array->elems == NULL) exit(errno); \
} \
\
/*Add an element to an array*/\
inline void array_##T##_AddElement(struct array_##T* array, const T element) { \
++(array->arraySize); \
if (array->arraySize > array->arraySpace) { \
++(array->arraySpace); \
array->elems = realloc(array->elems, sizeof(T)*(array->arraySpace)); \
if (array->elems == NULL) exit(errno); \
} \
\
array->elems[array->arraySize - 1] = element; \
} \
\
/*Remove an element from an array*/\
inline bool array_##T##_RemoveElement(struct array_##T* array, const T element, bool (*areEqual)(const T, const T)) { \
for (size_t i=0; i<array->arraySize; ++i) { \
if (areEqual(array->elems[i], element)) { \
for (;i<array->arraySize-1; ++i) { \
array->elems[i] = array->elems[i+1]; \
} \
--(array->arraySize); \
return true; \
} \
} \
return false; \
} \
\
/*Check if an array contains an element*/\
inline bool array_##T##_Contains(const struct array_##T* const array, const T element, bool (*areEqual)(const T, const T)) { \
for (size_t i = 0; i < array->arraySize; i++) { \
if (areEqual(array->elems[i], element)) { \
return true; \
} \
} \
return false; \
}\
\
/*Apply a function to each element in the array*/\
inline void array_##T##_Foreach(const struct array_##T* const array, void (*func)(const T)) { \
for(size_t i = 0; i<array->arraySize; ++i) { \
func(array->elems[i]);\
}\
}
#endif //ARRAY_UTILS_INCLUDED

@ -1,23 +0,0 @@
/**
* \file Audio.h
* \brief Audio management
* \author Théotime Maillarbaux
* \date 13/12/2021
*/
#ifndef AUDIO_H
#define AUDIO_H
#include <SDL2/SDL_mixer.h>
/**
* \brief Fades out a music and plays another one.
* \param[in] music A pointer to the Mix_Music struct used to play the current track
* \param[in] path The path to the new track to be played
* \warning The program won't know if it failed.
*
* This function creates a thread that will detach on its own completion.
*/
void switchMusic(Mix_Music* music, char path[]);
#endif // AUDIO_H

@ -0,0 +1,126 @@
/**
* \file AudioHandler.h
* \brief Audio management (music and sound effects)
* \author Théotime Maillarbaux
* \date 13/12/2021
*/
#ifndef AUDIO_H
#define AUDIO_H
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_thread.h>
#include <stdio.h>
#include <stdbool.h>
/**
* Macro used to generate enums elements and paths for musics.
* It should take either #MACRO_MUSIC_ENUM_GEN(E) or #MACRO_TO_MUSIC_PATH(P)
* as parameter.
*
* If new audios are added to the program, they should be added here.
* \sa #MACRO_FOR_ALL_SFX(E)
*/
#define MACRO_FOR_ALL_MUSICS(M) \
M(base_tardi) \
M(testMus)
/**
* Macro used to generate enums elements and paths for sound effects.
* It works the same way as #MACRO_FOR_ALL_MUSICS(M).
* \sa #MACRO_FOR_ALL_MUSICS(M)
*/
#define MACRO_FOR_ALL_SFX(M) \
M(testClick)
/**
* Macro used to generate the entries for the musics in #EnumAudios.
* It should be used in #MACRO_FOR_ALL_MUSICS(M) as a parameter.
* Each entry of #MACRO_FOR_ALL_MUSICS(M) will be converted as MUSIC_name.
* \sa #MACRO_SFX_ENUM_GEN(E)
*/
#define MACRO_MUSIC_ENUM_GEN(E) MUSIC_##E,
/**
* Macro used to generate the entries for the SFX in #EnumAudios.
* It works the same way as #MACRO_MUSIC_ENUM_GEN(E), except the entries start with SFX_
* instead of MUSIC_.
* \sa #MACRO_MUSIC_ENUM_GEN(E).
*/
#define MACRO_SFX_ENUM_GEN(E) SFX_##E,
/**
* Macro used to generate the paths to the musics.
* It should be used in #MACRO_FOR_ALL_MUSICS(M) as a parameter.
* Each entry of #MACRO_FOR_ALL_MUSICS(M) will be converted as rsrc/music/name.mp3.
* \sa #MACRO_TO_SFX_PATH(P)
*/
#define MACRO_TO_MUSIC_PATH(P) "rsrc/music/"#P".mp3",
/**
* Macro used to generate the paths to the SFX.
* It works the same way as #MACRO_TO_MUSIC_PATH(P),
* except the entries are converted to rsrc/sfx/name.wav.
* \sa MACRO_TO_MUSIC_PATH(P)
*/
#define MACRO_TO_SFX_PATH(P) "rsrc/sfx/"#P".wav",
/**
* \enum EnumAudios
* \brief Lists audios used in the program.
*/
typedef enum {
MACRO_FOR_ALL_MUSICS(MACRO_MUSIC_ENUM_GEN)
NB_MUSIC_DEFINED, ///< Index of this entry == number of musics
MACRO_FOR_ALL_SFX(MACRO_SFX_ENUM_GEN)
NB_AUDIO_DEFINED ///< Index of this entry == number of audios + 1
} EnumAudios;
/**
* \struct AudioHandler
* \brief A struct to store and handle all audios.
*/
typedef struct {
bool canPlayAudio; ///< true if audio could be initialized, else false. It shouldn't be changed manually.
Mix_Music* musics[NB_MUSIC_DEFINED]; ///< Paths to the musics
Mix_Chunk* sfx[NB_AUDIO_DEFINED - NB_MUSIC_DEFINED - 1]; ///< Paths to the SFX
} AudioHandler;
/**
* \brief Initializes the audio and creates a new AudioHandler.
* \param[in] volMusic Volume of the music
* \param[in] volSFX Volume of the sound effects.
* \return A new AudioHandler.
* \warning The program won't know if opening the audio device and the files failed.
*/
AudioHandler newAudioHandler(int volMusic, int volSFX);
/**
* \brief Changes volume for the SFX.
* \param[in] volSFX The new volume for the SFX.
*/
void changeSFXVol(int volSFX);
/**
* \brief Frees the music and SFX, and un-initializes the audio.
* \param[in,out] audioHandler A pointer to the AudioHandler to be freed.
*/
void freeAudioHandler(AudioHandler audioHandler);
/**
* \brief Plays a music. If another music is currently playing, the previous one will fade out.
* \param[in] music The music to be played. Should be a value of #EnumAudios starting with MUSIC_.
* \param[in] audioHandler The AudioHandler used to store the musics.
*/
void playMusic(EnumAudios music, AudioHandler audioHandler);
/**
* \brief Plays a sound effect.
* \param[in] sfx The SFX to be played. Should be a value of #EnumAudios starting with SFX_.
* \param[in] channel The channel the SFX should be played on.
* \param[in] audioHandler The AudioHandler used to store the SFX.
*/
void playSFX(EnumAudios sfx, int channel, AudioHandler audioHandler);
#endif // AUDIO_H

@ -12,18 +12,23 @@
#include <stdio.h> #include <stdio.h>
#include "engine/TextureLoader.h" #include "engine/TextureLoader.h"
// List here the different texture to handle /** List here the different texture to handle
// In the enum * In the enum
// Island become TEXTURE_Island * Island become TEXTURE_Island
// In file * In file
// Island become Island.png * Island become Island.png
* \sa MACRO_TEXTURE_ENUM_GEN(E)
*/
#define MACRO_FOR_ALL_TEXTURES(M) \ #define MACRO_FOR_ALL_TEXTURES(M) \
M(Island) \ M(Island) \
M(Bridge) \ M(Bridge) \
M(Piece) \ M(Piece) \
M(Water) M(Water)
// Allow the generation of enum /**
* \brief Allow the generation of enum
* \sa MACRO_FOR_ALL_TEXTURES(M)
*/
#define MACRO_TEXTURE_ENUM_GEN(E) TEXTURE_##E, #define MACRO_TEXTURE_ENUM_GEN(E) TEXTURE_##E,
/** /**
@ -50,7 +55,7 @@ typedef struct
/** /**
* \brief Create a TextureHandler and load each texture defined in MACRO_FOR_ALL_TEXTURES in it * \brief Create a TextureHandler and load each texture defined in MACRO_FOR_ALL_TEXTURES in it
* \param renderer The renderer which is passed to texture when they are created * \param renderer The renderer which is passed to texture when they are created
* \return ** TextureHandler filled with textures * \return TextureHandler filled with textures
*/ */
TextureHandler newTextureHandler(SDL_Renderer* renderer); TextureHandler newTextureHandler(SDL_Renderer* renderer);

@ -1,3 +1,9 @@
/**
* \file TextureLoader.h
* \brief Define functions to load textures
* \author Allan Point
*/
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_image.h> #include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_ttf.h>

@ -1,7 +1,7 @@
/** /**
* \file Bridge.h * \file Bridge.h
* \brief Bridge * \brief Bridge
* \autor Martin Rouault, Jacques Thomas * \author Martin Rouault, Jacques Thomas
* \date 13/12/2021 * \date 13/12/2021
*/ */

@ -9,6 +9,8 @@
#define COORD_INCLUDED #define COORD_INCLUDED
#include <stdbool.h> #include <stdbool.h>
#include "model/Island.h"
#include "engine/ArrayUtils.h"
/** /**
* \struct Coord * \struct Coord
@ -46,4 +48,12 @@ bool coordValid(const Coord coord);
*/ */
bool coordEqual(const Coord a, const Coord b); bool coordEqual(const Coord a, const Coord b);
/**
* \brief Convert an island to a coord
*
* \param[in] island The island to convert
* \return Coord from the island
*/
Coord islandToCoord(const Island* island);
#endif //COORD_INCLUDED #endif //COORD_INCLUDED

@ -1,7 +1,7 @@
/** /**
* \file Game.h * \file Game.h
* \brief Management of a Game * \brief Management of a Game
* \author Théotime Maillarbaux, Jacques Thomas * \author Théotime Maillarbaux, Jacques Thomas, Martin Rouault
* \date 29/11/2021 * \date 29/11/2021
*/ */
@ -13,6 +13,7 @@
#include "model/Bridge.h" #include "model/Bridge.h"
#include "model/Island.h" #include "model/Island.h"
#include "model/Coord.h" #include "model/Coord.h"
#include "model/arrayCoord.h"
#include <SDL2/SDL_pixels.h> #include <SDL2/SDL_pixels.h>
#include <stdbool.h> #include <stdbool.h>
@ -37,7 +38,7 @@ typedef struct {
//TODO duree //TODO duree
Phase phase; ///< The current state of the game Phase phase; ///< The current state of the game
Player arrPlayers[4]; ///< The array of all the players in this game Player arrPlayers[4]; ///< The array of all the players in this game
size_t nbPlayers; size_t nbPlayers;
Board board; ///< The board for this game Board board; ///< The board for this game
} Game; } Game;
@ -146,6 +147,7 @@ bool checkBridge(const Island start, const Island target, const Board* b);
* \param[in] arrPieces Array of all pieces * \param[in] arrPieces Array of all pieces
* \param[in] logicalSize The logical size of arrPieces * \param[in] logicalSize The logical size of arrPieces
* \param[in] island The island on the one we want to check the piece * \param[in] island The island on the one we want to check the piece
* \return the piece address if there is one the island otherwise return NULL
*/ */
Piece* getPieceFromIsland(Piece arrPieces[9], const size_t logicalSize, const Island island); Piece* getPieceFromIsland(Piece arrPieces[9], const size_t logicalSize, const Island island);
@ -177,5 +179,14 @@ bool clickOnBoard(const Coord coord, Game* game);
*/ */
bool rmBridge(Bridge bridge, Board* board); bool rmBridge(Bridge bridge, Board* board);
/**
* \brief List cases that can be interacted with for movement
*
* \param[in] game The game
* \param[in] selectedCase The selected case
* \return struct array_Coord An array of coord /!\ Care to free this array with array_Coord_Free
*/
struct array_Coord getInteractiveCases(const Game* const game, const Coord selectedCase);
#endif //GAME_H #endif //GAME_H

@ -0,0 +1,9 @@
#ifndef ARRAY_COORD_INCLUDED
#define ARRAY_COORD_INCLUDED
#include "model/Coord.h"
#include "engine/ArrayUtils.h"
GENERATE_DYNAMIC_ARRAY(Coord)
#endif //ARRAY_COORD_INCLUDED

Binary file not shown.

@ -0,0 +1,7 @@
#include "debug/printer.h"
#include <stdio.h>
void printCoord(const Coord coord) {
fprintf(stderr, "(%d, %d)", coord.x, coord.y);
}

@ -1,35 +0,0 @@
#include "engine/Audio.h"
struct params {
Mix_Music* music; // AA pointer to the Mix_Music struct used for the current track
char* path; // The path to the new track to be played
};
int fadeOut(void* args) {
struct params* argsCast = (struct params*)args;
Mix_Music* newMusic = Mix_LoadMUS(argsCast->path);
if (argsCast->music != NULL) {
if(Mix_FadeOutMusic(500) == 0) {
while (Mix_PlayingMusic()) {
;
}
}
}
if (newMusic != NULL) {
argsCast->music = newMusic;
return Mix_PlayMusic(argsCast->music,-1);
}
else return -2;
}
void switchMusic(Mix_Music* music, char path[]) {
struct params args = {
.music = music,
.path = path
};
SDL_Thread* thread = SDL_CreateThread(&fadeOut, "Fade out", (void*)&args);
SDL_DetachThread(thread); // Won't wait until thread is done to continue
}

@ -0,0 +1,186 @@
#include "engine/AudioHandler.h"
// A channel represents the number of SFX we can play at the same time.
// We normally should use only 1 channel, and we add one for safety.
#define NBCHANNELS 2
// Local functions
/*
* Used in a thread. Fades out the currently played music,
* then plays the music passed in as parameter.
* args should be passed as a pointer to void,
* but should actually be a pointer to Mix_Music.
* It is the music we want to play next;
*/
int fadeOut(void* args) {
// Since args is a pointer to void
// (the way C handles undefined types),
// casting args to a pointer to Mix_Music
Mix_Music* = (Mix_Music*)args;
int ret;
if(Mix_FadeOutMusic(500) == 0) { // Starting the fadeout
while (Mix_PlayingMusic()) {
; // Waiting until it's done
}
} else {
fprintf(stderr,"WARNING: couldn't fade out");
Mix_HaltMusic();
}
ret = Mix_PlayMusic(argsCast->music,-1);
if (ret != 0) {
fprintf(stderr,"WARNING: %s\n",Mix_GetError());
}
// We're supposed to return an int to use SDL_thread.
// We're not using the return value though.
return ret;
}
// Global functions
AudioHandler newAudioHandler(int volMusic, int volSFX) {
AudioHandler audioHandler;
int nb_SFX = NB_AUDIO_DEFINED - NB_MUSC_DEFINED - 1;
// Generating paths to musics and SFX files using macros
char* musicsPaths[] = {MACRO_FOR_ALL_MUSICS(MACRO_TO_MUSIC_PATH)};
char* sfxPaths[] = {MACRO_FOR_ALL_SFX(MACRO_TO_SFX_PATH)};
audioHandler.canPlayAudio = true;
// Initialize + verify opening audio device
if (0 != Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024)) {
fprintf(stderr,"Error when initializing audio.\n");
return audioHandler;
}
audioHandler.canPlayAudio = true;
fprintf(stderr,"Musics: %d\nSFX: %d\n",NB_MUSIC_DEFINED,nb_SFX);
// Loading musics
for (size_t i = 0; i < NB_MUSIC_DEFINED; i++) {
if ((audioHandler.musics[i] = LoadMUS(musicPaths[i]) == NULL)) {
fprintf(stderr,"WARNING: %s\n",Mix_GetError());
} else {
fprintf(stderr,"Loaded %s\n",musicPaths[i]);
}
}
Mix_VolumeMusic(volMusic);
// Initializing SFX
Mix_AllocateChannels(NBCHANNELS);
// Loading SFX
for (size_t i = 0; i < nb_SFX; i++) {
if ((audioHandler.sfx[i] = Mix_LoadWAV(sfxPaths[i])) == NULL) {
fprintf(stderr,"WARNING: %s\n",Mix_GetError());
} else {
fprintf(stderr,"Loaded %s\n",sfxPaths[i]);
}
}
changeSFXVol(volSFX);
return audioHandler;
}
void changeSFXVol(int volSFX) {
for (size_t i = 0; i < NBCHANNELS; i++) {
Mix_Volume(i, volSFX);
}
}
void freeAudioHandler(AudioHandler* audioHandler) {
// Freeing the music
Mix_HaltMusic();
for (size_t i = 0; i < NB_MUSIC_DEFINED; i++) {
if (audioHandler->musics[i] != NULL) {
Mix_FreeMusic(audioHandler->musics[i]);
audioHandler->musics[i] = NULL; // "to be safe...", says the docs
}
}
// Freeing the SFX
Mix_HaltChannel(-1); // Stopping playback on ALL channels
for (size_t i = 0; i < NB_AUDIO_DEFINED - NB_MUSIC_DEFINED - 1; i++) {
if (audioHandler->sfx[i] != NULL) {
Mix_FreeChunk(audioHandler->sfx[i]);
audioHandler->sfx[i] = NULL; // "to be safe...", says the docs
}
}
Mix_AllocateChannels(0); // Unallocating all channels
// Un-initializing the audio
Mix_CloseAudio();
audioHandler->canPlayAudio = false;
}
void playMusic(EnumAudios music, AudioHandler audioHandler) {
// music should be a value of EnumAudios that starts by MUSIC_
// In other words, it should be an enumerator before NB_MUSIC_DEFINED.
if (music >= NB_MUSIC_DEFINED) {
fprintf(stderr,"WARNING: tried to play an arbitrary value as a music\n");
return;
}
// Checking if audio has been opened.
if (!(audioHandler.canPlayAudio)) {
fprintf(stderr,"WARNING: tried to play a music with an unusable AudioHandler\n");
return;
}
// If another music is playing, fading the previous one out
if (Mix_PlayingMusic()) {
// Creating the thread, passing the music as parameter
SDL_Thread* thread = SDL_CreateThread(&fadeOut, "Fade out", (void*)audioHandler.musics[music]);
if (thread == NULL) {
fprintf(stderr,"WARNING: couldn't create thread to fade out music\n");
}
// playMusic won't wait until the thread is finished to end
SDL_DetachThread(thread);
// No other music is playing: starting a music normally.
} else {
if (Mix_PlayMusic(audioHandler.musics[music],-1) != 0) {
fprintf("WARNING: %s\n",Mix_GetError());
}
}
}
void playSFX(EnumAudios sfx, AudioHandler audioHandler) {
int nb_SFX = NB_AUDIO_DEFINED - NB_MUSIC_DEFINED - 1;
int channel;
Mix_Chunk* chunkSFX;
// sfx should be a value of EnumAudios that starts by SFX_.
// In other words, it should be an enumerator after NB_MUSIC_DEFINED but before NB_AUDIO_DEFINED.
if (sfx <= NB_MUSIC_DEFINED || sfx >= NB_AUDIO_DEFINED) {
fprintf(stderr,"WARNING: tried to play an arbitrary value as a SFX\n");
return;
}
// Checking if SFX has been opened.
if (!(audioHandler.canPlayAudio)) {
fprintf(stderr,"WARNING: tried to play an SFX with an unusable AudioHandler\n");
return;
}
// Getting actual chunk
chunkSFX = audioHandler.sfx[sfx - NB_MUSIC_DEFINED - 1];
// Getting first available channel
channel = Mix_GroupAvailable(-1);
if (channel == -1) {
fprintf(stderr,"WARNING: cannot play SFX because all channels are used\n");
return;
}
// Playing the SFX once (0 repetitions)
if (Mix_PlayChannel(channel,chunkSFX,0) != 0) {
fprintf(stderr,"WARNING: %s\n",Mix_GetError());
return;
}
}

@ -15,3 +15,8 @@ bool coordEqual(const Coord a, const Coord b)
{ {
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
Coord islandToCoord(const Island* island) {
Coord coord = {.x = island->x*2, .y = island->y*2};
return coord;
}

@ -1,5 +1,6 @@
#include "model/Game.h" #include "model/Game.h"
#include "model/IslandOrBridge.h" #include "model/IslandOrBridge.h"
#include "engine/ArrayUtils.h"
#include <assert.h> #include <assert.h>
// Not defined in header to not pollute inferface // Not defined in header to not pollute inferface
@ -93,7 +94,7 @@ void changePhaseOrPlayerTurn(Game* game)
game->board.nbPieces)); game->board.nbPieces));
fprintf(stderr, "Player n°%lld turn\n", game->currentPlayerID); fprintf(stderr, "Player n°%ld turn\n", game->currentPlayerID);
fflush(stderr); fflush(stderr);
if (anyOfPlayersPiecesCanMove(game->currentPlayerID, &game->board)) if (anyOfPlayersPiecesCanMove(game->currentPlayerID, &game->board))
@ -189,12 +190,14 @@ bool checkBridge(const Island start, const Island target, const Board* board)
// Vertical bridge // Vertical bridge
if (xdiff == 0 && abs(ydiff) == 1) if (xdiff == 0 && abs(ydiff) == 1)
{ {
return board->vBridges[start.y + ydiff][start.x]; const int coordY = start.y - (ydiff==-1?1:0);
return board->vBridges[coordY][start.x];
} }
// Horizontal bridge // Horizontal bridge
else if (abs(xdiff) == 1 && ydiff == 0) else if (abs(xdiff) == 1 && ydiff == 0)
{ {
return board->hBridges[start.y][start.x + xdiff]; const int coordX = start.x - (xdiff==-1?1:0);
return board->hBridges[start.y][coordX];
} }
// Not a bridge // Not a bridge
else else
@ -374,3 +377,92 @@ bool rmBridge(Bridge bridge, Board* board)
return false; return false;
} }
struct array_Coord getInteractiveCases(const Game* const game, const Coord selectedCase) {
switch (game->phase)
{
case PLACEMENT: {
struct array_Coord retVal = array_Coord_Create();
array_Coord_Reserve(&retVal, 25);
for (int y = 0; y<5; y+=2) {
for (int x = 0; x<5; x+=2) {
array_Coord_AddElement(&retVal, newCoord(x,y));
}
}
for (size_t i = 0; i < game->board.nbPieces; i++)
{
if (islandValid(game->board.arrPieces[i].island)) {
array_Coord_RemoveElement(&retVal, islandToCoord(&game->board.arrPieces[i].island), &coordEqual);
}
}
array_Coord_FitToSize(&retVal);
return retVal;
}
case MOVE_PIECE: {
struct array_Coord retVal = array_Coord_Create();
array_Coord_Reserve(&retVal, 4);
for (size_t i = 0; i < game->board.nbPieces; ++i)
{
if (game->board.arrPieces[i].idJ == game->currentPlayerID && !game->board.arrPieces[i].stuck) {
size_t nbIsland;
Island* islands = islandsAround(game->board.arrPieces[i].island, &nbIsland);
if (nbIsland != 0) {
Coord pieceCoord = islandToCoord(&game->board.arrPieces[i].island);
if (!coordValid(selectedCase)) {
array_Coord_AddElement(&retVal, pieceCoord);
}
else {
if (coordEqual(pieceCoord, selectedCase)) {
for (size_t iIsle = 0; iIsle < nbIsland; ++iIsle)
{
if (pieceCanMoveTo(&game->board.arrPieces[i], islands[iIsle], &game->board)) {
Coord coordIsland = islandToCoord(&islands[iIsle]);
array_Coord_AddElement(&retVal, coordIsland);
}
}
free(islands);
return retVal;
}
}
}
free(islands);
}
}
array_Coord_FitToSize(&retVal);
return retVal;
}
case RM_BRIDGE: {
struct array_Coord retVal = array_Coord_Create();
array_Coord_Reserve(&retVal, 40);
for (size_t y = 0; y<5; ++y) {
for (size_t x = 0; x<4; ++x) {
if (game->board.hBridges[y][x]) {
Coord coord = {.x=x*2+1, .y=y*2};
array_Coord_AddElement(&retVal, coord);
}
}
}
for (size_t y = 0; y<4; ++y) {
for (size_t x = 0; x<5; ++x) {
if (game->board.vBridges[y][x]) {
Coord coord = {.x=x*2, .y=y*2+1};
array_Coord_AddElement(&retVal, coord);
}
}
}
return retVal;
}
default:
return array_Coord_Create();
}
}

@ -4,16 +4,16 @@
bool drawGame(SDL_Renderer* renderer, const SDL_Rect* windowSize, const SDL_Rect* boardRect, const Game* game,TextureHandler* textureHandler) bool drawGame(SDL_Renderer* renderer, const SDL_Rect* windowSize, const SDL_Rect* boardRect, const Game* game,TextureHandler* textureHandler)
{ {
SDL_Texture* menuTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 50, 70); //SDL_Texture* menuTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 50, 70);
SDL_SetRenderTarget(renderer, menuTexture); /*SDL_SetRenderTarget(renderer, menuTexture);
SDL_SetRenderDrawColor(renderer, 150, 243, 59, 255); SDL_SetRenderDrawColor(renderer, 150, 243, 59, 255);
SDL_Rect buttonRect = {.x = 0,.y = 0,.w = 50,.h = 70}; SDL_Rect buttonRect = {.x = 0,.y = 0,.w = 50,.h = 70};
SDL_RenderFillRect(renderer, &buttonRect); SDL_RenderFillRect(renderer, &buttonRect);
SDL_SetRenderTarget(renderer, NULL); SDL_SetRenderTarget(renderer, NULL);*/
//P_Button menu = createButton(menuTexture, NULL, (windowSize->w*5)/100, (windowSize->h*5)/100, 50, 70, NULL); //P_Button menu = createButton(menuTexture, NULL, (windowSize->w*5)/100, (windowSize->h*5)/100, 50, 70, NULL);
P_Button menu = createButton(menuTexture, NULL, 10, 10, 50, 70, NULL); //P_Button menu = createButton(menuTexture, NULL, 10, 10, 50, 70, NULL);
drawBoard(renderer, boardRect, &(game->board), textureHandler->textures[TEXTURE_Island], textureHandler->textures[TEXTURE_Bridge], textureHandler->textures[TEXTURE_Water]); drawBoard(renderer, boardRect, &(game->board), textureHandler->textures[TEXTURE_Island], textureHandler->textures[TEXTURE_Bridge], textureHandler->textures[TEXTURE_Water]);

Loading…
Cancel
Save