changement organisation
This commit is contained in:
218
script/display.c
Normal file
218
script/display.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* \file display.c
|
||||
*
|
||||
*/
|
||||
#include "../include/display.h"
|
||||
#include "../include/function.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_mutex.h>
|
||||
#include <SDL2/SDL_rect.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_surface.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* \brief La fonction permet d'afficher simplement le plateau de jeu dans le
|
||||
* terminal.
|
||||
* \param tab Le tableau 2d carre du plateau.
|
||||
* \param size La taille du plateau.
|
||||
* \return Void
|
||||
*/
|
||||
void screenDisplay (char **tab, int size)
|
||||
{
|
||||
// puts("0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 ");
|
||||
char element[7] = { ' ', '#', 'S', '.', '*', '@', '+' };
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
for (int j = 0; j < size; ++j)
|
||||
{
|
||||
printf ("%c ", element[(int)tab[i][j]]);
|
||||
}
|
||||
puts ("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief La fonction affiche a l'aide de SDL la zone de jeu.
|
||||
* \param tab Le tableau 2d de la zone de jeu.
|
||||
* \param display_user La structure qui possede tous ce qu'il faut pour
|
||||
* l'affichage SDL
|
||||
* \return Void
|
||||
*/
|
||||
void screenDisplayGameSDL (char **tab, dis *display_user)
|
||||
{
|
||||
unsigned int display_game
|
||||
= display_user->size_window - display_user->size_menu;
|
||||
int size = display_game / display_user->size_box;
|
||||
unsigned int marge = display_user->size_menu / 2;
|
||||
unsigned int i, j;
|
||||
|
||||
SDL_Surface *img;
|
||||
SDL_Texture *texture;
|
||||
for (i = 0; i < display_user->size_box; ++i)
|
||||
{
|
||||
for (j = 0; j < display_user->size_box; ++j)
|
||||
{
|
||||
vect pos = { i * size + marge, j * size };
|
||||
switch (tab[j][i])
|
||||
{
|
||||
case EMPTY:
|
||||
img = IMG_Load ("image/empty.png");
|
||||
break;
|
||||
case WALL:
|
||||
img = IMG_Load ("image/wall.png");
|
||||
break;
|
||||
case PLAYER:
|
||||
img = IMG_Load ("image/player.png");
|
||||
break;
|
||||
case TARGET:
|
||||
img = IMG_Load ("image/target.png");
|
||||
break;
|
||||
case BOX:
|
||||
img = IMG_Load ("image/box.png");
|
||||
break;
|
||||
case BOX_ON_TARGET:
|
||||
img = IMG_Load ("image/box_on_target.png");
|
||||
break;
|
||||
case PLAYER_ON_TARGET:
|
||||
img = IMG_Load ("image/player_on_target.png");
|
||||
break;
|
||||
}
|
||||
texture
|
||||
= SDL_CreateTextureFromSurface (display_user->renderer, img);
|
||||
displayImage (display_user->renderer, texture, pos, size);
|
||||
SDL_FreeSurface (img);
|
||||
SDL_DestroyTexture (texture);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_RenderPresent (display_user->renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Taille de l'ecrant carre en fonction de l'ecrant du joueur avec une
|
||||
* marge.
|
||||
* \param display_user Qui serra modifier pour stoquer les information.
|
||||
* \return La taille max pour la fenetre de l'utilisateur.
|
||||
*/
|
||||
int getMaxSize (dis display_user)
|
||||
{
|
||||
SDL_Init (SDL_INIT_VIDEO); // init if error
|
||||
SDL_DisplayMode display;
|
||||
SDL_GetCurrentDisplayMode (0, &display); // get dim display user
|
||||
int result = 0;
|
||||
if (display.w <= display.h)
|
||||
{
|
||||
result = display.w;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = display.h;
|
||||
}
|
||||
SDL_Quit ();
|
||||
int minus_mod = (result - 50) % display_user.size_box;
|
||||
// printf("DIS :%d, size : %d ,mod : %d\n",result, size_box,minus_mod);
|
||||
return (result - 50 - minus_mod); // margin
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialise SDL.
|
||||
* \param display_user Stockage d'éléments SDL.
|
||||
* \return Void
|
||||
*/
|
||||
void initSDL (dis *display_user)
|
||||
{
|
||||
SDL_Init (SDL_INIT_VIDEO);
|
||||
TTF_Init ();
|
||||
display_user->window
|
||||
= SDL_CreateWindow ("Sokoman", SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED, display_user->size_window,
|
||||
display_user->size_window, SDL_WINDOW_SHOWN);
|
||||
if (!display_user->window)
|
||||
{
|
||||
SDL_Quit ();
|
||||
perror ("Window null");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
display_user->renderer
|
||||
= SDL_CreateRenderer (display_user->window, -1, SDL_RENDERER_SOFTWARE);
|
||||
if (!display_user->renderer)
|
||||
{
|
||||
SDL_Quit ();
|
||||
perror ("Renderer null");
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Cette fonction affiche l'image dans la fenetre de l'utilisateur.
|
||||
* \param renderer Le renderer de l'utilisateur.
|
||||
* \param texture La texture de l'image à appliquer.
|
||||
* \param pos La position de l'image à afficher.
|
||||
* \param size La taile de l'image.
|
||||
* \return Void
|
||||
**/
|
||||
void displayImage (SDL_Renderer *renderer, SDL_Texture *texture, vect pos,
|
||||
int size)
|
||||
{
|
||||
SDL_Rect rect = { pos.x, pos.y, size, size };
|
||||
SDL_RenderCopy (renderer, texture, NULL, &rect);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Cette fonction affiche du texte dans la fenetre de l'utilisateur.
|
||||
* \param display_user Tous les éléments SDL de l'utilisateur.
|
||||
* \param text Le string à afficher.
|
||||
* \param coor Les coordonnée du texte.
|
||||
* \param size La taille du texte.
|
||||
* \param font_size La taille de la font.
|
||||
* \return Void
|
||||
*/
|
||||
void displayTextSDL (dis *display_user, char *text, vect coor, vect size,
|
||||
int font_size)
|
||||
{
|
||||
TTF_Font *Sans = TTF_OpenFont ("Roboto-Regular.ttf", font_size);
|
||||
SDL_Color white = { 255, 255, 255, 255 };
|
||||
int text_width, text_height;
|
||||
|
||||
SDL_Rect background;
|
||||
SDL_Surface *surface_text = TTF_RenderText_Solid (Sans, text, white);
|
||||
|
||||
TTF_SizeText (Sans, text, &text_height, &text_width);
|
||||
SDL_Rect message_rect;
|
||||
message_rect.x = coor.x;
|
||||
message_rect.y = coor.y;
|
||||
message_rect.w = text_height;
|
||||
message_rect.h = text_width;
|
||||
background.x = coor.x;
|
||||
background.y = coor.y;
|
||||
background.w = text_height;
|
||||
background.h = text_width;
|
||||
|
||||
if (message_rect.w > size.y)
|
||||
{
|
||||
message_rect.w = size.y;
|
||||
background.w = size.y;
|
||||
}
|
||||
if (message_rect.h > size.x)
|
||||
{
|
||||
message_rect.h = size.x;
|
||||
background.h = size.x;
|
||||
}
|
||||
|
||||
SDL_Texture *message
|
||||
= SDL_CreateTextureFromSurface (display_user->renderer, surface_text);
|
||||
SDL_SetRenderDrawColor (display_user->renderer, 0, 0, 0, 255);
|
||||
SDL_RenderFillRect (display_user->renderer, &background);
|
||||
|
||||
SDL_RenderCopy (display_user->renderer, message, NULL, &message_rect);
|
||||
SDL_RenderPresent (display_user->renderer);
|
||||
|
||||
SDL_FreeSurface (surface_text);
|
||||
SDL_DestroyTexture (message);
|
||||
TTF_CloseFont (Sans);
|
||||
}
|
||||
528
script/function.c
Normal file
528
script/function.c
Normal file
@@ -0,0 +1,528 @@
|
||||
/**
|
||||
* \file function.c
|
||||
* Ce fichier contient toute les fonction utile pour le jeu. Sauf pour l'affichage.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../include/function.h"
|
||||
#include "../include/display.h"
|
||||
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_keycode.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <SDL2/SDL_scancode.h>
|
||||
#include <SDL2/SDL_timer.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
/**
|
||||
* \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 pointeur du tableau 2D carre de char (1 octet).
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Cette fontion permet de liberer l'espace tu tableau 2D de char.
|
||||
* \param tab Le tableau 2D.
|
||||
* \param N Le nombre d'éléments.
|
||||
* \return Void.
|
||||
*/
|
||||
void free2D (char **tab, int N)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N; ++i)
|
||||
{
|
||||
free (tab[i]);
|
||||
}
|
||||
free (tab);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief La fontction permet de savoir si le joueur peut ce deplacer dans une direction.
|
||||
* \param valueOfNCase La valeur de la case dans la direction que le joueur veut aller.
|
||||
* \param valueOfNPlusOneCase La valeur de la case dans la direction que le joueur veut aller mais une fois de plus.
|
||||
* \return 0 Si c'est un mur devant le joueur, 1 si c'est vide devant le joueur, 2 si c'est une boite mais qu'on peux la pousser
|
||||
* ,3 si le joueur pousse une boite sur un point d'interer, 4 si le joueur bouge sur un point d'interer, 5 si le joueur peux pousser
|
||||
* une boite mais le joueur se place sur un point d'interer et 6 si le joeuur pousse une boite sur un point d'interer et que le joueu
|
||||
* est aussi sur un point d'interer.
|
||||
*/
|
||||
char canIGoDirection (char valueOfNCase,
|
||||
char 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Cette fonction effectue les deplacements du joueur et des boites en fonction de la situation.
|
||||
* \param tab Le tableau 2D du plateau de jeu.
|
||||
* \param playerpos La position actuel du joueur.
|
||||
* \param direction La direction que le joueur veut effectuer.
|
||||
* \param score_user Toutes les données nécessaire pour calculer le score fini du joueur.
|
||||
* \return Void
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* \brief La fonction permet de faire la boucle de jeu.
|
||||
* \param tab2d Le tableau 2d carre.
|
||||
* \param N LE nombre d'element de tab2d.
|
||||
* \param playerPos La position de depart du joueur.
|
||||
* \param targets Le tableau de toutes les positions des points d'interer de la maps.
|
||||
* \param int nbr_targets Le nombre de point d'interer.
|
||||
* \param display_user Tout les information SDL pour afficher le jeu.
|
||||
* \param score_user Toute les données nécessaire pour calculer le score fini du joueur.
|
||||
* \return Void
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Cette fonction verrifie si la partie est gagnante.
|
||||
* \param tab2d Le tableau 2D du jeu.
|
||||
* \param targets Le tableau de toute les positions des points d'interer.
|
||||
* \param nbr_targets Le nombre de points d'interer.
|
||||
* \return True si le joueur a remplis tout les points d'interer, false si ce n'est pas le cas .
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief La fonction renvois si la partie est perdante.
|
||||
* \param tab2d Le tableau 2d carre du plateau de jeu.
|
||||
* \param N Le nombre d'éléments dans le tab2d.
|
||||
* \return True si c'est perdu, false si c'est pas perdu a cette instant.
|
||||
*
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief La fonction fait une addition de vecteur, (x1+x2, y1+y2).
|
||||
* \param one Premier vecteur.
|
||||
* \param two Deuzieme vecteur.
|
||||
* \return vect Un vecteur de l'addition de one et two.
|
||||
*/
|
||||
vect plusVect (vect one, vect two)
|
||||
{
|
||||
vect result;
|
||||
result.x = one.x + two.x;
|
||||
result.y = one.y + two.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Renvois la longeur Manhattan
|
||||
*/
|
||||
int lengthVect (vect vector) { return abs (vector.x) + abs (vector.y); }
|
||||
|
||||
/**
|
||||
* \brief La fonction permet de savoir si une boite est dans une situation ou le joueur ne poura pas la debloqué.
|
||||
* \param tab2d Le tableau 2D carre du plateau de jeu.
|
||||
* \param box_coor Les corrdonnée de la boite que la fonction test.
|
||||
* \return True si la la boite est bloquer, sinon false.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Cette fonction renvois transforme le forma time en texte. (min:sec)
|
||||
* \param time Le temps qu'on veux convertire.
|
||||
* \return char Le string du texte.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
43
script/main.c
Normal file
43
script/main.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "../include/display.h"
|
||||
#include "../include/function.h"
|
||||
#include "../include/read.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_render.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SIZE_PLAY 19
|
||||
#define SIZE_MENU 200;
|
||||
|
||||
int main ()
|
||||
{
|
||||
dis display_user;
|
||||
display_user.size_menu = SIZE_MENU;
|
||||
display_user.size_box = SIZE_PLAY;
|
||||
display_user.size_window = getMaxSize (display_user);
|
||||
initSDL (&display_user);
|
||||
|
||||
vect *playerPos = (vect *)malloc (sizeof (vect));
|
||||
vect *targets;
|
||||
int nbr_targets;
|
||||
score playerScore;
|
||||
char **tab2d = creatArea2D (SIZE_PLAY);
|
||||
|
||||
score score_user = {0, 0, 0,0};
|
||||
|
||||
|
||||
targets
|
||||
= fileToTab2D ("test.txt", tab2d, SIZE_PLAY, playerPos, &nbr_targets);
|
||||
screenDisplayGameSDL (tab2d, &display_user);
|
||||
screenDisplay (tab2d, SIZE_PLAY);
|
||||
inGameLoop (tab2d, SIZE_PLAY, playerPos, targets, nbr_targets,
|
||||
&display_user, &score_user);
|
||||
|
||||
SDL_DestroyWindow (display_user.window);
|
||||
SDL_DestroyRenderer (display_user.renderer);
|
||||
free2D (tab2d, SIZE_PLAY);
|
||||
free (playerPos);
|
||||
free (targets);
|
||||
SDL_Quit ();
|
||||
return 0;
|
||||
}
|
||||
57
script/read.c
Normal file
57
script/read.c
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "../include/function.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
vect *fileToTab2D (const char *name_file, char **tab,
|
||||
const unsigned N, vect *player, int *nbr_targets)
|
||||
{
|
||||
vect *targets = malloc (sizeof (vect));
|
||||
(*nbr_targets) = 0;
|
||||
FILE *file = fopen (name_file, "r");
|
||||
unsigned int x = 0, y = 0;
|
||||
while (!feof (file))
|
||||
{
|
||||
char current = fgetc (file);
|
||||
|
||||
if (current == EOF)
|
||||
{
|
||||
break;
|
||||
}
|
||||
switch (current)
|
||||
{
|
||||
case '#':
|
||||
tab[x][y] = WALL;
|
||||
break;
|
||||
case 'C':
|
||||
tab[x][y] = BOX;
|
||||
break;
|
||||
case 'I':
|
||||
targets = realloc (targets, sizeof (vect) * (++nbr_targets[0]));
|
||||
targets[nbr_targets[0] - 1].x = x;
|
||||
targets[nbr_targets[0] - 1].y = y;
|
||||
tab[x][y] = TARGET;
|
||||
break;
|
||||
case 'P':
|
||||
player->x = x;
|
||||
player->y = y;
|
||||
tab[x][y] = PLAYER;
|
||||
break;
|
||||
case '\n':
|
||||
y = -1;
|
||||
++x;
|
||||
break;
|
||||
default:
|
||||
tab[x][y] = EMPTY;
|
||||
break;
|
||||
}
|
||||
++y;
|
||||
|
||||
if (x > N || y > N)
|
||||
{
|
||||
perror ("Level out of range !");
|
||||
exit (-1);
|
||||
}
|
||||
}
|
||||
fclose (file);
|
||||
return targets;
|
||||
}
|
||||
Reference in New Issue
Block a user