From 28eff8489366a6919375e9b44b8def2136a44bec Mon Sep 17 00:00:00 2001 From: Paul GEORGES <43345813+paulgeorges1998@users.noreply.github.com> Date: Thu, 6 Dec 2018 18:41:57 +0100 Subject: [PATCH] degats + effets Ajout degats/mort ennemis, ajout effets, modifications mineures fonctions Listes --- effets.c | 20 +++ effets.h | 16 +++ listeB.c | 29 ++-- listeB.h | 12 +- listeE.c | 44 ++++++ listeE.h | 14 ++ listeP.c | 68 ++++----- listeP.h | 18 ++- listeR.c | 37 ++--- listeR.h | 4 +- main.c | 198 +++++++++++++++++++++++++++ personnage.c | 144 +++++++++++++++++++ personnage.h | 1 + projectile.c | 3 +- projectile.h | 3 +- sprites/effets/blood/blood_hitv3.png | Bin 0 -> 8831 bytes 16 files changed, 532 insertions(+), 79 deletions(-) create mode 100644 effets.c create mode 100644 effets.h create mode 100644 listeE.c create mode 100644 listeE.h create mode 100644 main.c create mode 100644 personnage.c create mode 100644 sprites/effets/blood/blood_hitv3.png diff --git a/effets.c b/effets.c new file mode 100644 index 0000000..5436286 --- /dev/null +++ b/effets.c @@ -0,0 +1,20 @@ +#include "effets.h" + +Effet nouvel_effet_bloodHit(SDL_Texture **sprites, SDL_Rect pos, int angle){ + Effet e; + e.pos = pos; + e.srcrect.x = 0; + e.srcrect.y = 0; + e.srcrect.w = 128; + e.srcrect.h = 128; + e.image = sprites[2]; + e.angle = angle - 90; + e.xMax = 1920; + return e; +} + + + +void afficher_effet(SDL_Renderer *renderer, Effet e){ + SDL_RenderCopyEx(renderer, e.image, &e.srcrect, &e.pos, e.angle, NULL, SDL_FLIP_NONE); +} diff --git a/effets.h b/effets.h new file mode 100644 index 0000000..3327638 --- /dev/null +++ b/effets.h @@ -0,0 +1,16 @@ +#include <SDL2/SDL.h> + + +typedef struct s_Effet Effet, s_Effet; +struct s_Effet +{ + SDL_Rect pos; + SDL_Rect srcrect; + SDL_Texture *image; + float angle; + int xMax; +}; + +Effet nouvel_effet_bloodHit(SDL_Texture **sprites, SDL_Rect pos, int angle); +void afficher_effet(SDL_Renderer *renderer, Effet e); + diff --git a/listeB.c b/listeB.c index a3adaf4..5efee12 100644 --- a/listeB.c +++ b/listeB.c @@ -8,11 +8,12 @@ ListeB nouvelle_listeB(balle data){ return L; } -ListeB cons_listeB(ListeB L, balle data){ - ListeB tmp; - tmp = nouvelle_listeB(data); - tmp->next = L; - return tmp; +void cons_listeB(ListeB *L, balle data){ + ListeB tmp = malloc(sizeof(s_ListeB)); + tmp->data = data; + tmp->next = *L; + *L = tmp; + return ; } bool est_vide_listeB(ListeB L) { @@ -21,7 +22,7 @@ bool est_vide_listeB(ListeB L) { -ListeB incrementer_balles(ListeB LB, ListeP LP, ListeR LR, int v, int xCamera, int yCamera) +ListeB incrementer_balles(ListeB LB, ListeP LP, ListeR LR, ListeE *LE, int v, int xCamera, int yCamera, SDL_Texture **sprites) { if(LB == NULL){ return LB; @@ -38,7 +39,7 @@ ListeB incrementer_balles(ListeB LB, ListeP LP, ListeR LR, int v, int xCamera, i if(ballePos.x < 0 || ballePos.x >= 1000 || ballePos.y <= 0 || ballePos.y >= 700 || detecter_collision_murs(LR, ballePos, xCamera, yCamera)){ LB = LB->next; - return incrementer_balles(LB, LP, LR, v, xCamera, yCamera); + return incrementer_balles(LB, LP, LR, LE, v, xCamera, yCamera, sprites); } ballePos.w = 6; @@ -46,13 +47,13 @@ ListeB incrementer_balles(ListeB LB, ListeP LP, ListeR LR, int v, int xCamera, i ballePos.x = LB->data.ballePos.x - 3; ballePos.y = LB->data.ballePos.y - 3; - if(detecter_collision_perso(LP, ballePos, xCamera, yCamera)) { + if(detecter_collision_perso(LP, LE, ballePos, LB->data.degats ,xCamera, yCamera, sprites)) { LB = LB->next; - return incrementer_balles(LB, LP, LR, v, xCamera, yCamera); + return incrementer_balles(LB, LP, LR, LE, v, xCamera, yCamera, sprites); } - LB->next = incrementer_balles(LB->next, LP, LR, v, xCamera, yCamera); + LB->next = incrementer_balles(LB->next, LP, LR, LE, v, xCamera, yCamera, sprites); return LB; @@ -67,21 +68,23 @@ void afficher_listeB(SDL_Renderer *renderer, ListeB L) { } } -ListeB tir_update(ListeB LB, ListeP LP, ListeR LR, int time, SDL_Texture *balleLongueJaune, int v, int xCamera, int yCamera){ +ListeB tir_update(ListeB LB, ListeP LP, ListeR LR, ListeE *LE, int time, SDL_Texture *balleLongueJaune, int v, int xCamera, int yCamera, SDL_Texture **sprites){ //Si perso en train de tirer s_ListeP *tmp = LP; while(tmp != NULL){ if(tmp->data.tir){ //On fait pop une nouvelle balle toutes les X ms if(time > tmp->data.tempsTirPrecedent + 200) { - LB = cons_listeB(LB, nouvelle_balle(balleLongueJaune, tmp->data.angle, tmp->data.pos)); + cons_listeB(&LB, nouvelle_balle(balleLongueJaune, tmp->data.angle, tmp->data.degats, tmp->data.pos)); tmp->data.tempsTirPrecedent = time; } } tmp = tmp->next; } //On met a jour les coordonn�es des balles d�j� tir�es, d�pop si n�c�ssaire - LB = incrementer_balles(LB, LP, LR, v, xCamera, yCamera); + LB = incrementer_balles(LB, LP, LR, LE, v, xCamera, yCamera, sprites); + + return LB; } diff --git a/listeB.h b/listeB.h index a3f75e9..e8d285c 100644 --- a/listeB.h +++ b/listeB.h @@ -1,6 +1,8 @@ +#include "listeP.h" #include <stdio.h> #include "projectile.h" -#include "listeP.h" + + typedef struct s_ListeB *ListeB, s_ListeB; struct s_ListeB @@ -10,8 +12,10 @@ struct s_ListeB }; ListeB nouvelle_listeB(balle data); -ListeB cons_listeB(ListeB L, balle data); +void cons_listeB(ListeB *L, balle data); bool est_vide_listeB(ListeB L); -ListeB incrementer_balles(ListeB LB, ListeP LP, ListeR LR, int v, int xCamera, int yCamera); +ListeB incrementer_balles(ListeB LB, ListeP LP, ListeR LR, ListeE *LE, int v, int xCamera, int yCamera, SDL_Texture **sprites); void afficher_listeB(SDL_Renderer *renderer, ListeB L); -ListeB tir_update(ListeB LB, ListeP LP, ListeR LR, int time, SDL_Texture *balleLongueJaune, int v, int xCamera, int yCamera); +ListeB tir_update(ListeB LB, ListeP LP, ListeR LR, ListeE *LE, int time, SDL_Texture *balleLongueJaune, int v, int xCamera, int yCamera, SDL_Texture **sprites); + + diff --git a/listeE.c b/listeE.c new file mode 100644 index 0000000..3c1323a --- /dev/null +++ b/listeE.c @@ -0,0 +1,44 @@ +#include "listeE.h" + +void cons_listeE(ListeE *L, Effet data){ + ListeE tmp = malloc(sizeof(s_ListeE)); + tmp->data = data; + tmp->next = *L; + *L = tmp; + return; +} + +void animer_effets(ListeE L){ + ListeE tmp; + while(L != NULL){ + L->data.srcrect.y += L->data.srcrect.h; + if(L->data.srcrect.y >= L->data.xMax){ + if(L->next == NULL){ + tmp = NULL; + L = tmp; + } else { + tmp = malloc(sizeof(s_ListeE)); + tmp->data = L->next->data; + tmp->next = L->next->next; + *L = *tmp; + } + } else { + L = L->next; + } + } + return; +} + + +void afficher_listeE(SDL_Renderer *renderer, ListeE L, int dxCamera, int dyCamera){ + ListeE tmp = L; + while(tmp != NULL) { + tmp->data.pos.x -= dxCamera; + tmp->data.pos.y -= dyCamera; + afficher_effet(renderer, tmp->data); + tmp = tmp->next; + } +} + + + diff --git a/listeE.h b/listeE.h new file mode 100644 index 0000000..a402d1e --- /dev/null +++ b/listeE.h @@ -0,0 +1,14 @@ +#include "effets.h" +#include <stdlib.h> + + +typedef struct s_ListeE *ListeE, s_ListeE; +struct s_ListeE +{ + ListeE next; + Effet data; +}; + +void cons_listeE(ListeE *L, Effet e); +void afficher_listeE(SDL_Renderer *renderer, ListeE L, int dxCamera, int dyCamera); +void animer_effets(ListeE L); diff --git a/listeP.c b/listeP.c index 0cb33d8..b5fb580 100644 --- a/listeP.c +++ b/listeP.c @@ -9,12 +9,16 @@ ListeP nouvelle_listeP(Perso data){ return L; } -ListeP cons_listeP(ListeP L, Perso data){ - ListeP tmp = nouvelle_listeP(data); - tmp->next = L; - return tmp; +void cons_listeP(ListeP *L, Perso data){ + ListeP tmp = malloc(sizeof(s_ListeP)); + tmp->data = data; + tmp->next = *L; + *L = tmp; + return; } + + bool est_vide_listeP(ListeP L){ return (L == NULL); } @@ -28,46 +32,46 @@ void afficher_listeP(SDL_Renderer *renderer, ListeP L){ } Perso* joueur(ListeP L){ - s_ListeP *tmp = L; - while(tmp != NULL){ - if(tmp->data.ennemi == false){ - return &tmp->data; + while(L != NULL){ + if(L->data.ennemi == false){ + return &L->data; } - tmp = tmp->next; + L = L->next; } return NULL; } - -ListeP deplacement_ennemis(ListeP L, int xCamera, int yCamera, int dxCamera, int dyCamera){ - - if(L == NULL){ - return L; - } - - s_ListeP *tmp = L; - while(tmp != NULL){ - deplacement_ennemi(&tmp->data, xCamera, yCamera, dxCamera, dyCamera); - tmp = tmp->next; +void deplacement_ennemis(ListeP L, int xCamera, int yCamera, int dxCamera, int dyCamera){ + while(L != NULL){ + if(L->data.vie <= 0){ + *L = *L->next; + L = L->next; + } else { + deplacement_ennemi(&L->data, xCamera, yCamera, dxCamera, dyCamera); + L = L->next; + } } - - return L; - + return; } -bool detecter_collision_perso(ListeP L, SDL_Rect rect, int xCamera, int yCamera){ +bool detecter_collision_perso(ListeP L, ListeE *LE, SDL_Rect rect, int degats, int xCamera, int yCamera, SDL_Texture **sprites){ int ax1, ax2, bx1, bx2, ay1, ay2, by1, by2; + Effet e; while(L != NULL){ - ax1 = rect.x;//+ xCamera; - ax2 = rect.x + rect.w ;//+ xCamera; + ax1 = rect.x; + ax2 = rect.x + rect.w ; bx1 = L->data.pos.x; bx2 = L->data.pos.x + L->data.pos.w; - ay1 = rect.y;// + yCamera; - ay2 = rect.y;// + rect.h + yCamera; + ay1 = rect.y; + ay2 = rect.y; by1 = L->data.pos.y; by2 = L->data.pos.y + L->data.pos.h; + if(ax1 < bx2 && ax2 > bx1 && ay1 < by2 && ay2 > by1 && L->data.ennemi){ + L->data.vie -= degats; + e = nouvel_effet_bloodHit(sprites, L->data.pos, L->data.angle); + cons_listeE(LE, e); return true; } L = L->next; @@ -76,18 +80,14 @@ bool detecter_collision_perso(ListeP L, SDL_Rect rect, int xCamera, int yCamera) } -void animer_persos2(ListeP L){ +void animer_persos(ListeP L){ while(L != NULL){ if(L->data.ennemi){ animer_perso(&L->data); } L = L->next; } -} - -void animer_persos(ListeP L){ - - animer_persos2(L); return; } + diff --git a/listeP.h b/listeP.h index a7e0f05..ce6c114 100644 --- a/listeP.h +++ b/listeP.h @@ -1,5 +1,7 @@ #include "personnage.h" -#include <stdio.h> +#include <stdio.h> +#include "listeE.h" + typedef struct s_ListeP *ListeP, s_ListeP; @@ -7,14 +9,18 @@ struct s_ListeP { ListeP next; Perso data; -}; +}; + + ListeP nouvelle_listeP(Perso data); -ListeP cons_listeP(ListeP L, Perso data); +void cons_listeP(ListeP *L, Perso data); bool est_vide_listeP(ListeP L); void afficher_listeP(SDL_Renderer *renderer, ListeP L); Perso* joueur(ListeP L); -ListeP deplacement_ennemis(ListeP L, int xCamera, int yCamera, int dxCamera, int dyCamera); -bool detecter_collision_perso(ListeP L, SDL_Rect rect, int xCamera, int yCamera); +void supprimer_ennemi(ListeP L); +void deplacement_ennemis(ListeP L, int xCamera, int yCamera, int dxCamera, int dyCamera); +bool detecter_collision_perso(ListeP L, ListeE *LE, SDL_Rect rect, int degats, int xCamera, int yCamera, SDL_Texture **sprites); void animer_persos(ListeP L); -void animer_persos2(ListeP L); + + diff --git a/listeR.c b/listeR.c index b4cab06..eeeb326 100644 --- a/listeR.c +++ b/listeR.c @@ -9,14 +9,16 @@ ListeR nouvelle_listeR(SDL_Rect data){ return L; } -ListeR cons_listeR(ListeR L, SDL_Rect data){ - ListeR tmp = nouvelle_listeR(data); - tmp->next = L; - return tmp; +void cons_listeR(ListeR *L, SDL_Rect data){ + ListeR tmp = malloc(sizeof(s_ListeR)); + tmp->data = data; + tmp->next = *L; + *L = tmp; + return; } -ListeR charger_niveau(int *tab, ListeR L){ +void charger_niveau(int *tab, ListeR *L){ //on met toutes les case � 0 pour dire que tout est du sol (provisoire) for(int j = 0; j < 30; j++){ for(int i = 0; i < 30; i++){ @@ -49,28 +51,28 @@ ListeR charger_niveau(int *tab, ListeR L){ rect.y = j * 50; rect.h = 25; rect.w = 50; - L = cons_listeR(L, rect); + cons_listeR(L, rect); break; case 2: rect.x = i * 50; rect.y = j * 50 + 25; rect.h = 25; rect.w = 50; - L = cons_listeR(L, rect); + cons_listeR(L, rect); break; case 3: rect.x = i * 50; rect.y = j * 50; rect.h = 50; rect.w = 25; - L = cons_listeR(L, rect); + cons_listeR(L, rect); break; case 4: rect.x = i * 50 + 25; rect.y = j * 50; rect.h = 50; rect.w = 25; - L = cons_listeR(L, rect); + cons_listeR(L, rect); break; case 5: @@ -81,31 +83,30 @@ ListeR charger_niveau(int *tab, ListeR L){ rect.y = j * 50; rect.h = 50; rect.w = 50; - L = cons_listeR(L, rect); + cons_listeR(L, rect); break; } } } - return L; + return ; } bool detecter_collision_murs(ListeR L, SDL_Rect rect, int xCamera, int yCamera){ - s_ListeR *tmp = L; int ax1, ax2, bx1, bx2, ay1, ay2, by1, by2; - while(tmp != NULL){ + while(L != NULL){ ax1 = rect.x + xCamera; ax2 = rect.x + rect.w + xCamera; - bx1 = tmp->data.x; - bx2 = tmp->data.x + tmp->data.w; + bx1 = L->data.x; + bx2 = L->data.x + L->data.w; ay1 = rect.y + yCamera; ay2 = rect.y + rect.h + yCamera; - by1 = tmp->data.y; - by2 = tmp->data.y + tmp->data.h; + by1 = L->data.y; + by2 = L->data.y + L->data.h; if(ax1 < bx2 && ax2 > bx1 && ay1 < by2 && ay2 > by1){ return true; } - tmp = tmp->next; + L = L->next; } return false; } diff --git a/listeR.h b/listeR.h index 9f06adc..de90978 100644 --- a/listeR.h +++ b/listeR.h @@ -10,6 +10,6 @@ struct s_ListeR }; ListeR nouvelle_listeR(SDL_Rect data); -ListeR cons_listeR(ListeR L, SDL_Rect data); -ListeR charger_niveau(int *tab, ListeR L); +void cons_listeR(ListeR *L, SDL_Rect data); +void charger_niveau(int *tab, ListeR *L); bool detecter_collision_murs(ListeR L, SDL_Rect rect, int xCamera, int yCamera); diff --git a/main.c b/main.c new file mode 100644 index 0000000..3554096 --- /dev/null +++ b/main.c @@ -0,0 +1,198 @@ +#include "image.h" +#include "listeB.h" + + +int main(int argc, char *argv[]) +{ + srand(time(NULL)); + bool gameover = false; + bool tir = false; + SDL_Window *fenetre; + SDL_Event evenements; + SDL_Renderer *ecran; + SDL_Texture *fond, *perso, *balleLongueJaune; + SDL_Rect persoPos; + float mouseX, mouseY; + int vitesse = 25, tempsActuel = 0, tempsPrecedent = 0, tempsActuelTir = 0, tempsActuelAnim = 0, tempsPrecedentAnim = 0; + ListeB ballesTirees; + ListeP persosListe; + ListeR mursListe; + ListeE effetsListe; + Perso *joueur_ptr; + SDL_Texture *sprites[3]; + SDL_Texture *spritesMap[9]; + int xCamera = 0, yCamera = 0, dxCamera = 0, dyCamera = 0; + int map[30][30]; + + + //Initialisation SDL + if(SDL_Init(SDL_INIT_VIDEO < 0)) + { + printf("Erreur d'initialisation de la SDL %s", SDL_GetError()); + SDL_Quit(); + return EXIT_FAILURE; + } + + //Initialisation SDL_image (PNG) + IMG_Init(IMG_INIT_PNG); + + //Cr�ation fen�tre + fenetre = SDL_CreateWindow("gameName", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 700, SDL_WINDOW_RESIZABLE); + if(fenetre == NULL) + { + printf("Erreur d'initialisation de la fenetre %s", SDL_GetError()); + return EXIT_FAILURE; + } + + //Cr�ation renderer + ecran = SDL_CreateRenderer(fenetre, -1, SDL_RENDERER_ACCELERATED); + + //Chargement images + balleLongueJaune = charger_image("sprites/projectiles/balle/balle_longue_jaune.png", ecran, 255, 255, 255); + + + //Chargement du d�cor (murs etc) + spritesMap[0] = charger_image("sprites/map/sol.png", ecran, 0, 0, -1); + spritesMap[1] = charger_image("sprites/map/mur_h.png", ecran, 255, 255, 255); + spritesMap[2] = charger_image("sprites/map/mur_b.png", ecran, 255, 255, 255); + spritesMap[3] = charger_image("sprites/map/mur_g.png", ecran, 255, 255, 255); + spritesMap[4] = charger_image("sprites/map/mur_d.png", ecran, 255, 255, 255); + spritesMap[5] = charger_image("sprites/map/mur_hg.png", ecran, 255, 255, 255); + spritesMap[6] = charger_image("sprites/map/mur_hd.png", ecran, 255, 255, 255); + spritesMap[7] = charger_image("sprites/map/mur_bg.png", ecran, 255, 255, 255); + spritesMap[8] = charger_image("sprites/map/mur_bd.png", ecran, 255, 255, 255); + + fond = charger_image("sprites/fond.png", ecran, -1, -1, -1); + perso = charger_image("sprites/perso/handgun/idle/survivor_idle.png", ecran, 255, 255, 255); + sprites[0] = perso; + perso = charger_image("sprites/ennemis/zombie/move/zombie_move.png", ecran, 255, 255, 255); + sprites[1] = perso; + perso = charger_image("sprites/effets/blood/blood_hitv3.png", ecran, 0, 0, -1); + sprites[2] = perso; + + + SDL_Rect tmpRect; + tmpRect.x = 0; + tmpRect.y = 0; + tmpRect.w = 0; + tmpRect.h = 0; + mursListe = nouvelle_listeR(tmpRect); + charger_niveau(map[0], &mursListe); + + + Perso p = nouveau_joueur(ecran , sprites); + persosListe = nouvelle_listeP(p); + p = nouvel_ennemi_1(ecran, sprites); + cons_listeP(&persosListe, p); + p = nouvel_ennemi_1(ecran, sprites); + cons_listeP(&persosListe, p); + p = nouvel_ennemi_1(ecran, sprites); + cons_listeP(&persosListe, p); + p = nouvel_ennemi_1(ecran, sprites); + cons_listeP(&persosListe, p); + p = nouvel_ennemi_1(ecran, sprites); + cons_listeP(&persosListe, p); + p = nouvel_ennemi_1(ecran, sprites); + cons_listeP(&persosListe, p); + + + balle b = nouvelle_balle(balleLongueJaune, 0, 0, persoPos); + ballesTirees = nouvelle_listeB(b); + + effetsListe = NULL; + + //Boucle de jeu + while(!gameover) + { + //Petit timer pour pas d�passer 60 ex�cutions/sec (provisoire) + tempsActuel = SDL_GetTicks(); + if (tempsActuel > tempsPrecedent + 16) + { + //D�tection �v�nements + while(SDL_PollEvent(&evenements)) + { + switch(evenements.type) + { + case SDL_QUIT: + gameover = true; + break; + case SDL_MOUSEMOTION: + mouseX = evenements.motion.x; + mouseY = evenements.motion.y; + break; + case SDL_MOUSEBUTTONDOWN: + switch(evenements.button.button) + { + case SDL_BUTTON_LEFT: + tir = true; + break; + } + break; + case SDL_MOUSEBUTTONUP: + switch(evenements.button.button) + { + case SDL_BUTTON_LEFT: + tir = false; + break; + } + break; + + case SDL_KEYDOWN: + switch(evenements.key.keysym.sym) + { + case SDLK_ESCAPE: + gameover = true; + break; + } + break; + + } + } + + + joueur_ptr = joueur(persosListe); + if(joueur_ptr != NULL){ + //Gestion d�placement/angle de tir + joueur_ptr->tir = tir; + deplacement_joueur(joueur_ptr, mursListe, &xCamera, &yCamera, &dxCamera, &dyCamera); + angle_joueur((joueur_ptr), mouseX, mouseY); + } + + + tempsActuelAnim = SDL_GetTicks(); + if(tempsActuelAnim > tempsPrecedentAnim + 40 ){ + animer_persos(persosListe); + animer_effets(effetsListe); + tempsPrecedentAnim = tempsActuelAnim; + } + + + + + + //D�placement/angle de tir ennemis + deplacement_ennemis(persosListe, xCamera, yCamera, dxCamera, dyCamera); + + //Tir + tempsActuelTir = SDL_GetTicks(); + ballesTirees = tir_update(ballesTirees, persosListe, mursListe, &effetsListe, tempsActuelTir, balleLongueJaune, vitesse, xCamera, yCamera, sprites); + + //Affichage + SDL_RenderClear(ecran); + afficher_niveau(map[0], ecran, spritesMap, xCamera, yCamera); + afficher_listeE(ecran, effetsListe, dxCamera, dyCamera); + afficher_listeP(ecran, persosListe); + afficher_listeB(ecran, ballesTirees); + SDL_RenderPresent(ecran); + tempsPrecedent = tempsActuel; + } + } + + //Nettoyage + SDL_DestroyWindow(fenetre); + SDL_DestroyTexture(fond); + SDL_DestroyTexture(perso); + IMG_Quit(); + SDL_Quit(); + return EXIT_SUCCESS; +} diff --git a/personnage.c b/personnage.c new file mode 100644 index 0000000..93c06e9 --- /dev/null +++ b/personnage.c @@ -0,0 +1,144 @@ +#include "personnage.h" + + +Perso nouveau_joueur(SDL_Renderer *renderer, SDL_Texture **sprites){ + Perso p; + p.tempsTirPrecedent = 0; + p.image = sprites[0]; + p.pos.x = 480; + p.pos.y = 330; + p.pos.w = 40; + p.pos.h = 40; + p.srcrect.x = 0; + p.srcrect.y = 0; + p.srcrect.w = 258; + p.srcrect.h = 220; + p.angle = 0; + p.vie = 100; + p.degats = 25; + p.vitesse = 4; + p.tir = false; + p.ennemi = false; + p.animFlip = 1; + return p; +} + +Perso nouvel_ennemi_1(SDL_Renderer *renderer, SDL_Texture **sprites){ + Perso p; + p.tempsTirPrecedent = 0; + p.image = sprites[1]; + //g�n�re des coordonn�es de spawn al�atoires(provisoire) + p.pos.x = rand()%100 + 0; + p.pos.y = rand()%700 + 0; + p.pos.w = 60; + p.pos.h = 60; + p.srcrect.x = 0; + p.srcrect.y = 0; + p.srcrect.w = 288; + p.srcrect.h = 311; + p.angle = 0; + p.vie = 100; + p.degats = 10; + p.vitesse = 2; + p.tir = false; + p.ennemi = true; + p.animFlip = 1; + return p; +} + +void afficher_perso(SDL_Renderer *renderer, Perso p) +{ + SDL_RenderCopyEx(renderer, p.image, &p.srcrect, &p.pos, p.angle, NULL, SDL_FLIP_NONE); +} + +void deplacement_joueur(Perso *p, ListeR L, int *xCamera, int *yCamera, int *dxCamera, int *dyCamera) +{ + int dX = 0; + int dY = 0; + + const Uint8 *state = SDL_GetKeyboardState(NULL); + + if(state[SDL_GetScancodeFromKey(SDLK_z)]){ + dY -= 1; + } + + if(state[SDL_GetScancodeFromKey(SDLK_s)]){ + dY += 1; + } + + if(state[SDL_GetScancodeFromKey(SDLK_q)]){ + dX -= 1; + } + + if(state[SDL_GetScancodeFromKey(SDLK_d)]){ + dX += 1; + } + + + dX = dX * p->vitesse; + dY = dY * p->vitesse; + + + *xCamera += dX; + *yCamera += dY; + *dxCamera = dX; + *dyCamera = dY; + + + if(detecter_collision_murs(L, p->pos, *xCamera, *yCamera)){ + *xCamera -= dX; + *dxCamera = 0; + if(detecter_collision_murs(L, p->pos, *xCamera, *yCamera)){ + *xCamera += dX; + *dxCamera = dX; + *yCamera -= dY; + *dyCamera = 0; + if(detecter_collision_murs(L, p->pos, *xCamera, *yCamera)){ + *xCamera -= dX; + *dxCamera = 0; + } + } + } + + return; +} + +void deplacement_ennemi(Perso *p, int xCamera, int yCamera, int dxCamera, int dyCamera){ + if(p != NULL){ + if(p->ennemi){ + //M�j de la direction du perso + angle_ennemi(p); + //Compensation du d�calage de la cam�ra + ajout du d�placement + p->pos.x += round(-dxCamera + cos(p->angle) * p->vitesse); + p->pos.y += round(-dyCamera + sin(p->angle) * p->vitesse); + p->angle = (p->angle * 180.0000)/PI; + } + } + return; +} + +void angle_joueur(Perso *p, float mouseX, float mouseY){ + float angle; + angle = atan2(mouseY - (p->pos.y + 20), mouseX - (p->pos.x + 20)); + angle = (angle * 180.0000)/PI; + p->angle = angle; + return; +} + +void angle_ennemi(Perso *p){ + float angle; + angle = atan2( 350 - (p->pos.y + 20), 500 - (p->pos.x + 20)); + p->angle = angle; + return; +} + +void animer_perso(Perso *p){ + p->srcrect.y += p->srcrect.h * p->animFlip; + if(p->srcrect.y > 4976|| p->srcrect.y < 0){ + p->animFlip = -p->animFlip; + p->srcrect.y += p->srcrect.h * p->animFlip; + } + return; +} + + diff --git a/personnage.h b/personnage.h index efba971..063d219 100644 --- a/personnage.h +++ b/personnage.h @@ -16,6 +16,7 @@ struct s_Personnage float angle; int tempsTirPrecedent; int vie; + int degats; int vitesse; int animFlip; bool tir; diff --git a/projectile.c b/projectile.c index eb2e94c..7653b09 100644 --- a/projectile.c +++ b/projectile.c @@ -1,13 +1,14 @@ #include "projectile.h" -balle nouvelle_balle(SDL_Texture *image, float angle, SDL_Rect persoPos) +balle nouvelle_balle(SDL_Texture *image, float angle, int degats, SDL_Rect persoPos) { balle b; b.angle = angle; b.collision = false; b.image = image; b.ballePos = persoPos; + b.degats = degats; return b; } diff --git a/projectile.h b/projectile.h index 8d1c272..fd3bd0a 100644 --- a/projectile.h +++ b/projectile.h @@ -11,9 +11,10 @@ struct s_Balle float angle; SDL_Texture *image; bool collision; + int degats; }; -balle nouvelle_balle(SDL_Texture *image, float angle, SDL_Rect persoPos); +balle nouvelle_balle(SDL_Texture *image, float angle, int degats, SDL_Rect persoPos); void incrementer_balle(balle *b, int vitesse); void afficher_balle(SDL_Renderer *renderer, balle b); diff --git a/sprites/effets/blood/blood_hitv3.png b/sprites/effets/blood/blood_hitv3.png new file mode 100644 index 0000000000000000000000000000000000000000..d8b1451ebeeb3ef70fd94f8a4aeb5673fbaab0af GIT binary patch literal 8831 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 E06GXgO8@`> literal 0 HcmV?d00001 -- GitLab