Mario-Sokoban from the OpenClassroom C Lesson exercice.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //
  2. // game.c
  3. // Mario Sokoban
  4. //
  5. // Created by Benoit Sida on 2014-02-16.
  6. // Copyright (c) 2014 Benoit Sida. All rights reserved.
  7. //
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <SDL2/SDL.h>
  11. #include <SDL2_image/SDL_image.h>
  12. #include "constantes.h"
  13. #include "level.h"
  14. void mooveMario(int map[][NB_BLOCS_HAUTEUR], SDL_Rect*, int);
  15. void mooveBox(int*, int*);
  16. void game(int diff, SDL_Window *ecran, SDL_Surface *screen)
  17. {
  18. SDL_Surface *mario[4] = {NULL};
  19. SDL_Surface *wall = NULL, *marioActuel = NULL, *box = NULL, *target = NULL, *boxOK = NULL, *win = NULL, *commandes = NULL;
  20. SDL_Rect position, posMario;
  21. SDL_Event event;
  22. int running = 1, target_r = 0, i = 0, j = 0, returnMenu = 0, continuer = 0, niveau = 0, nbLevel = 0;
  23. int map[NB_BLOCS_LARGEUR][NB_BLOCS_HAUTEUR] = {0};
  24. wall = IMG_Load("sprites/mur.jpg");
  25. box = IMG_Load("sprites/caisse.jpg");
  26. boxOK = IMG_Load("sprites/caisse_ok.jpg");
  27. target = IMG_Load("sprites/objectif.png");
  28. win = IMG_Load("sprites/win.png");
  29. commandes = IMG_Load("sprites/commandes.png");
  30. mario[HAUT] = IMG_Load("sprites/mario_haut.gif");
  31. mario[BAS] = IMG_Load("sprites/mario_bas.gif");
  32. mario[GAUCHE] = IMG_Load("sprites/mario_gauche.gif");
  33. mario[DROITE] = IMG_Load("sprites/mario_droite.gif");
  34. marioActuel = mario[BAS];
  35. nbLevel =loadLevel(niveau, diff, map);
  36. if (nbLevel == 0) {
  37. exit(EXIT_FAILURE);
  38. } // Charge le niveau
  39. for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  40. {
  41. for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  42. {
  43. if (map[i][j] == MARIO)
  44. {
  45. posMario.x = i;
  46. posMario.y = j;
  47. map[i][j] = VIDE;
  48. }
  49. }
  50. } // Position du Joueur au départ
  51. SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 139, 111, 71));
  52. for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  53. {
  54. for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  55. {
  56. position.x = i * TAILLE_BLOC;
  57. position.y = j * TAILLE_BLOC;
  58. switch(map[i][j])
  59. {
  60. case WALL:
  61. SDL_BlitSurface(wall, NULL, screen, &position);
  62. break;
  63. case BOX:
  64. SDL_BlitSurface(box, NULL, screen, &position);
  65. break;
  66. case BOX_OK:
  67. SDL_BlitSurface(boxOK, NULL, screen, &position);
  68. break;
  69. case TARGET:
  70. SDL_BlitSurface(target, NULL, screen, &position);
  71. target_r = 1;
  72. break;
  73. }
  74. }
  75. } // Dessine la map
  76. position.x = 0;
  77. position.y = 0;
  78. SDL_BlitSurface(commandes, NULL, screen, &position);
  79. position.x = posMario.x * TAILLE_BLOC;
  80. position.y = posMario.y * TAILLE_BLOC;
  81. SDL_BlitSurface(marioActuel, NULL, screen, &position); // Place le joueur
  82. SDL_UpdateWindowSurface(ecran);
  83. while (!continuer) {
  84. SDL_WaitEvent(&event);
  85. switch(event.type)
  86. {
  87. case SDL_QUIT:
  88. exit(EXIT_SUCCESS);
  89. break;
  90. case SDL_KEYDOWN:
  91. switch(event.key.keysym.sym)
  92. {
  93. case SDLK_ESCAPE:
  94. running = 0;
  95. returnMenu = 1;
  96. break;
  97. case SDLK_RETURN:
  98. continuer = 1;
  99. break;
  100. case SDLK_SPACE:
  101. continuer = 1;
  102. break;
  103. }
  104. break;
  105. } // Acton du joueur
  106. }
  107. while (running) {
  108. if (!loadLevel(niveau,diff, map)) {
  109. exit(EXIT_FAILURE);
  110. } // Charge le niveau
  111. for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  112. {
  113. for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  114. {
  115. if (map[i][j] == MARIO)
  116. {
  117. posMario.x = i;
  118. posMario.y = j;
  119. map[i][j] = VIDE;
  120. }
  121. }
  122. } // Position du Joueur au départ
  123. continuer = 0;
  124. while (!continuer) {
  125. SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 139, 111, 71));
  126. target_r = 0;
  127. for (i = 0 ; i < NB_BLOCS_LARGEUR ; i++)
  128. {
  129. for (j = 0 ; j < NB_BLOCS_HAUTEUR ; j++)
  130. {
  131. position.x = i * TAILLE_BLOC;
  132. position.y = j * TAILLE_BLOC;
  133. switch(map[i][j])
  134. {
  135. case WALL:
  136. SDL_BlitSurface(wall, NULL, screen, &position);
  137. break;
  138. case BOX:
  139. SDL_BlitSurface(box, NULL, screen, &position);
  140. break;
  141. case BOX_OK:
  142. SDL_BlitSurface(boxOK, NULL, screen, &position);
  143. break;
  144. case TARGET:
  145. SDL_BlitSurface(target, NULL, screen, &position);
  146. target_r = 1;
  147. break;
  148. }
  149. }
  150. } // Dessine la map
  151. if (!target_r) {
  152. continuer = 1;
  153. niveau++;
  154. }// change de niveau
  155. if (niveau == nbLevel + 1) {
  156. running = 0;// Test de victoire
  157. }
  158. position.x = posMario.x * TAILLE_BLOC;
  159. position.y = posMario.y * TAILLE_BLOC;
  160. SDL_BlitSurface(marioActuel, NULL, screen, &position); // Place le joueur
  161. SDL_UpdateWindowSurface(ecran);
  162. SDL_WaitEvent(&event);
  163. switch(event.type)
  164. {
  165. case SDL_QUIT:
  166. exit(EXIT_SUCCESS);
  167. break;
  168. case SDL_KEYDOWN:
  169. switch(event.key.keysym.sym)
  170. {
  171. case SDLK_ESCAPE:
  172. continuer = 1;
  173. running = 0;
  174. returnMenu = 1;
  175. break;
  176. case SDLK_UP:
  177. marioActuel = mario[HAUT];
  178. mooveMario(map, &posMario, HAUT);
  179. break;
  180. case SDLK_DOWN:
  181. marioActuel = mario[BAS];
  182. mooveMario(map, &posMario, BAS);
  183. break;
  184. case SDLK_RIGHT:
  185. marioActuel = mario[DROITE];
  186. mooveMario(map, &posMario, DROITE);
  187. break;
  188. case SDLK_LEFT:
  189. marioActuel = mario[GAUCHE];
  190. mooveMario(map, &posMario, GAUCHE);
  191. break;
  192. }
  193. break;
  194. } // Acton du joueur
  195. }
  196. } // Boucle principale
  197. while (!returnMenu) {
  198. position.x = 0;
  199. position.y = 0;
  200. SDL_BlitSurface(win, NULL, screen, &position);
  201. SDL_UpdateWindowSurface(ecran);
  202. SDL_WaitEvent(&event);
  203. switch(event.type)
  204. {
  205. case SDL_QUIT:
  206. exit(EXIT_SUCCESS);
  207. break;
  208. case SDL_KEYDOWN:
  209. switch(event.key.keysym.sym)
  210. {
  211. case SDLK_ESCAPE:
  212. returnMenu = 1;
  213. break;
  214. case SDLK_RETURN:
  215. returnMenu = 1;
  216. break;
  217. }
  218. break;
  219. } // Acton du joueur
  220. }
  221. SDL_FreeSurface(wall);
  222. SDL_FreeSurface(box);
  223. SDL_FreeSurface(boxOK);
  224. SDL_FreeSurface(target);
  225. for (i = 0 ; i < 4 ; i++)
  226. SDL_FreeSurface(mario[i]); // Libère la mémoire
  227. }
  228. void mooveMario(int map[][NB_BLOCS_HAUTEUR], SDL_Rect *pos, int direction)
  229. {
  230. switch (direction) {
  231. case HAUT:
  232. if (pos->y - 1 < 0)
  233. break;
  234. if (map[pos->x][pos->y - 1] == WALL)
  235. break;
  236. if ((map[pos->x][pos->y - 1] == BOX || map[pos->x][pos->y - 1] == BOX_OK) && (pos->y - 2 < 0 || map[pos->x][pos->y - 2] == WALL || map[pos->x][pos->y - 2] == BOX || map[pos->x][pos->y - 2] == BOX_OK))
  237. break;
  238. mooveBox(&map[pos->x][pos->y - 1], &map[pos->x][pos->y - 2]);
  239. // Si on arrive là, c'est qu'on peut déplacer le joueur ! On vérifie d'abord s'il y a une caisse à déplacer
  240. pos->y--; // On peut enfin faire monter le joueur (oufff !)
  241. break;
  242. case BAS:
  243. if (pos->y + 1 > 12)
  244. break;
  245. if (map[pos->x][pos->y + 1] == WALL)
  246. break;
  247. if ((map[pos->x][pos->y + 1] == BOX || map[pos->x][pos->y + 1] == BOX_OK) && (pos->y + 2 > 12 || map[pos->x][pos->y + 2] == WALL || map[pos->x][pos->y + 2] == BOX || map[pos->x][pos->y + 2] == BOX_OK))
  248. break;
  249. mooveBox(&map[pos->x][pos->y + 1], &map[pos->x][pos->y + 2]);
  250. pos->y++;
  251. break;
  252. case GAUCHE:
  253. if (pos->x - 1 < 0)
  254. break;
  255. if (map[pos->x - 1][pos->y] == WALL)
  256. break;
  257. if ((map[pos->x - 1][pos->y] == BOX || map[pos->x - 1][pos->y] == BOX_OK) && (pos->x - 2 < 0 || map[pos->x - 2][pos->y] == WALL || map[pos->x - 2][pos->y] == BOX || map[pos->x - 2][pos->y] == BOX_OK))
  258. break;
  259. mooveBox(&map[pos->x - 1][pos->y], &map[pos->x - 2][pos->y]);
  260. pos->x--;
  261. break;
  262. case DROITE:
  263. if (pos->x + 1 > 12)
  264. break;
  265. if (map[pos->x + 1][pos->y] == WALL)
  266. break;
  267. if ((map[pos->x + 1][pos->y] == BOX || map[pos->x + 1][pos->y] == BOX_OK) && (pos->x + 2 > 12 || map[pos->x + 2][pos->y] == WALL || map[pos->x + 2][pos->y] == BOX || map[pos->x + 2][pos->y] == BOX_OK))
  268. break;
  269. mooveBox(&map[pos->x + 1][pos->y], &map[pos->x + 2][pos->y]);
  270. pos->x++;
  271. break;
  272. }
  273. }
  274. void mooveBox(int *premiereCase, int *secondeCase)
  275. {
  276. if (*premiereCase == BOX || *premiereCase == BOX_OK)
  277. {
  278. if (*secondeCase == TARGET)
  279. *secondeCase = BOX_OK;
  280. else
  281. *secondeCase = BOX;
  282. if (*premiereCase == BOX_OK)
  283. *premiereCase = TARGET;
  284. else
  285. *premiereCase = VIDE;
  286. }
  287. }