#include "function.h" #include "display.h" #include #include #include #include #include #include #include #include #include /** * \brief Cette fonction permet de creer une liste 2D carre * \param N La valeur N est le nombre d'élément dans le tableau. * \return Le tableau 2D carre */ char **creatArea2D (const unsigned int N) { char **tab2d; tab2d = calloc (N, sizeof (char *)); if (tab2d == NULL) { return NULL; } bool fail = false; unsigned int i; for (i = 0; i < N && !fail; ++i) { tab2d[i] = calloc (N, sizeof (char)); if (tab2d[i] == NULL) { fail = true; } } if (fail) { unsigned int j; for (j = 0; j < i; ++j) { free (tab2d[j]); } free (tab2d); return NULL; } return tab2d; } void free2D (char **tab, int N) { int i; for (i = 0; i < N; ++i) { free (tab[i]); } free (tab); return; } short int canIGoDirection (short int valueOfNCase, short int valueOfNPlusOneCase) { if (valueOfNCase != WALL) { if ((valueOfNCase == BOX && valueOfNPlusOneCase == EMPTY) || (valueOfNCase == BOX && valueOfNPlusOneCase == TARGET)) { if (valueOfNPlusOneCase == TARGET) { // Box on target return 3; } // move the box return 2; } if ((valueOfNCase == BOX_ON_TARGET && valueOfNPlusOneCase == EMPTY) || (valueOfNCase == BOX_ON_TARGET && valueOfNPlusOneCase == TARGET)) { if (valueOfNPlusOneCase == TARGET) { // Box on target and player on target too return 6; } // move the box but player on a target return 5; } if (valueOfNCase == TARGET) { // move player on target return 4; } if (valueOfNCase == EMPTY) { // move player return 1; } } return 0; } void move (char **tab, vect *playerPos, vect direction, score *score_user) { short int valueOfNCase = tab[playerPos->x + direction.x][playerPos->y + direction.y]; vect add = plusVect (*playerPos, direction); add = plusVect (add, direction); short int valueOfNPlusOneCase; if (add.x < 0 || add.y < 0) { valueOfNPlusOneCase = WALL; } else { valueOfNPlusOneCase = tab[add.x][add.y]; } short int returnValue = canIGoDirection (valueOfNCase, valueOfNPlusOneCase); short int playerState = tab[playerPos->x][playerPos->y]; if (returnValue != 0) score_user->move_player++; switch (returnValue) { case 0: break; case 1: // move player tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER; break; case 2: // move player and the box tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER; tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2] = BOX; score_user->move_box++; break; case 3: // move player and the box is well-placed tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER; tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2] = BOX_ON_TARGET; score_user->move_box++; break; case 4: // move player on a target tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER_ON_TARGET; break; case 5: // move box and player on a target tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2] = BOX; tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER_ON_TARGET; score_user->move_box++; break; case 6: // move player on a target and box on a target tab[playerPos->x + direction.x * 2][playerPos->y + direction.y * 2] = BOX_ON_TARGET; tab[playerPos->x + direction.x][playerPos->y + direction.y] = PLAYER_ON_TARGET; score_user->move_box++; break; default: printf ("Commande inconnue !\n"); } if (returnValue != 0) { if (playerState == PLAYER_ON_TARGET) { tab[playerPos->x][playerPos->y] = TARGET; } else { tab[playerPos->x][playerPos->y] = EMPTY; } playerPos->x = playerPos->x + direction.x; playerPos->y = playerPos->y + direction.y; } } void inGameLoop (char **tab2d, int N, vect *playerPos, vect *targets, int nbr_targets, dis *display_user, score *score_user) { vect size_menu = { display_user->size_menu -10, display_user->size_window / 3 -10}; vect coor_time = { 10, display_user->size_window - display_user->size_menu + 10}; vect coor_move_player = { display_user->size_window / 3 + 10, display_user->size_window - display_user->size_menu + 10}; vect coor_move_box = { (display_user->size_window / 3) * 2 + 10, display_user->size_window - display_user->size_menu + 10}; displayTextSDL (display_user, "MP : 0", coor_move_player, size_menu, 50); displayTextSDL (display_user, "MB : 0", coor_move_box, size_menu, 50); time_t time_start = time (NULL); time_t current_time = time (NULL); time_t delay = 0; vect direction = { 0, 0 }; char input; bool finish = false; SDL_Event event; while (!finish) { SDL_PollEvent (&event); if (event.type == SDL_KEYDOWN) { input = event.key.keysym.scancode; switch (input) { case SDL_SCANCODE_ESCAPE: finish = true; break; case SDL_SCANCODE_D: direction.y = 1; direction.x = 0; break; case SDL_SCANCODE_A: direction.y = -1; direction.x = 0; break; case SDL_SCANCODE_W: direction.x = -1; direction.y = 0; break; case SDL_SCANCODE_S: direction.x = 1; direction.y = 0; break; default: direction.x = 0; direction.y = 0; } move (tab2d, playerPos, direction, score_user); screenDisplayGameSDL (tab2d, display_user); char nbr_p[20]; snprintf (nbr_p, 20, "MP : %d", score_user->move_player); char nbr_b[20]; snprintf (nbr_b, 20, "MB : %d", score_user->move_box); displayTextSDL (display_user, nbr_p, coor_move_player, size_menu, 50); displayTextSDL (display_user, nbr_b, coor_move_box, size_menu, 50); if (isWin (tab2d, targets, nbr_targets)) { puts ("Win!"); finish = true; } if (islose (tab2d, N)) { puts ("lose!"); finish = true; } } current_time = time (NULL); if (current_time > delay) { delay = current_time; char *char_time = timeToText (time(NULL) - time_start); displayTextSDL (display_user, char_time, coor_time, size_menu, 50); free(char_time); } SDL_Delay (16); } } bool isWin (char **tab2d, vect *targets, int nbr_targets) { int i; for (i = 0; i < nbr_targets; ++i) { int x = targets[i].x; int y = targets[i].y; if (tab2d[x][y] != BOX_ON_TARGET) { return false; } } return true; } bool islose (char **tab2d, const int N) { int x = 0, y = 0; for (x = 0; x < N; ++x) { for (y = 0; y < N; ++y) { bool isblock = false; if (tab2d[x][y] == BOX) { vect box; box.x = x; box.y = y; isblock = blockBox (tab2d, box); } if (isblock) { return true; } } } return false; } vect plusVect (vect one, vect two) { vect result; result.x = one.x + two.x; result.y = one.y + two.y; return result; } int lengthVect (vect vector) { return abs (vector.x) + abs (vector.y); } bool blockBox (char **tab2d, vect box_coor) { int nbr_touch = 0; vect card[4] = { { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 } }; int indice_card[4] = { 0 }; int id_box = -1; int i; for (i = 0; i < 4; ++i) { vect test = plusVect (box_coor, card[i]); char val = tab2d[test.x][test.y]; if (val == BOX || val == WALL || val == BOX_ON_TARGET) { nbr_touch++; if (val == BOX || val == BOX_ON_TARGET) { id_box = nbr_touch - 1; } indice_card[nbr_touch - 1] = i; } } if (nbr_touch == 0) return false; if (nbr_touch >= 3) { if (id_box != -1) { vect other1 = card[indice_card[(id_box + 1) % 3]]; vect other2 = card[indice_card[(id_box + 2) % 3]]; vect test_add_other = plusVect (other1, other2); vect coor_box = plusVect (card[indice_card[id_box]], box_coor); vect other_plus_box1 = plusVect (other1, coor_box); vect other_plus_box2 = plusVect (other2, coor_box); int val1 = tab2d[other_plus_box1.x][other_plus_box1.y]; int val2 = tab2d[other_plus_box2.x][other_plus_box2.y]; if (test_add_other.x == 0 && test_add_other.y == 0) { if ((val1 == WALL || val1 == BOX || val1 == BOX_ON_TARGET) || (val2 == WALL || val2 == BOX || val2 == BOX_ON_TARGET)) { return true; } return false; } } return true; } if (nbr_touch == 2) { int id1 = indice_card[0]; int id2 = indice_card[1]; vect add = plusVect (card[id1], card[id2]); if (lengthVect (add) == 2) { if (id_box == -1) return true; vect test = plusVect (card[indice_card[id_box]], card[indice_card[(id_box + 1) % 2]]); test = plusVect (test, box_coor); if (tab2d[test.x][test.y] == WALL) return true; } return false; } vect normal = card[indice_card[0]]; vect director1 = card[(indice_card[0] + 1) % 4]; vect director2 = card[(indice_card[0] + 1) % 4]; vect dir_test[2] = { director1, director2 }; bool wall = false; for (int i = 0; i < 2; ++i) { vect current = plusVect (box_coor, dir_test[i]); while (!wall) { char val = tab2d[current.x][current.y]; if (val == WALL) wall = true; if (val == TARGET) return false; vect cur_nor = plusVect (current, normal); val = tab2d[cur_nor.x][cur_nor.y]; if (val != WALL || val != BOX || val != BOX_ON_TARGET) { return false; } } } return true; perror ("error in blockBox"); exit (0); } char *timeToText (time_t time) { char *result = calloc (20, sizeof (char)); result[0] = '\0'; unsigned int min = time / 60; unsigned int sec = time % 60; snprintf (result, 20, "Time : %02d:%02d", min, sec); return result; }