La présentation est en train de télécharger. S'il vous plaît, attendez

La présentation est en train de télécharger. S'il vous plaît, attendez

Codage d’un jeu de plateforme avec SDL 2.0

Présentations similaires


Présentation au sujet: "Codage d’un jeu de plateforme avec SDL 2.0"— Transcription de la présentation:

1 Codage d’un jeu de plateforme avec SDL 2.0
Formation C Codage d’un jeu de plateforme avec SDL 2.0

2 Sommaire Présentation et installation de la SDL2.0 Principes de base
Gestion du monde Mouvements du personnage Animations

3 La SDL 2.0 Bibliothèque 2D pour le jeu vidéo Écrite en C
Libre et gratuite Gestion d’images, de son Prise en charge de manettes Utilisation de la carte graphique

4 Installation de la SDL Suivre le tutoriel de developpez.com ( laurent.developpez.com/tutoriels/sdl-2/installation-et-configuration/) Projets préconfigurés pour CodeBlocks sur windows et makefile pour linux Rajouter l’option -std=c99 (project build options/compiler settings/other options sous code blocks)

5 Principes de base Boucle de jeux
initialisations update Boucle principale draw free

6 Initialisation de la SDL
int main(int argc, char** argv) { /* initialisation de la SDL */ if (SDL_Init(SDL_INIT_VIDEO) != 0 ) fprintf(stdout,"Échec de l'initialisation de la SDL (%s)\n",SDL_GetError()); return -1; } else /* Création de la fenêtre */ SDL_Window* window = NULL; window = SDL_CreateWindow("Ma première application SDL2",SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); //création du renderer SDL_Renderer* renderer = NULL; renderer = SDL_CreateRenderer( window, 0, SDL_RENDERER_ACCELERATED); /* Initialisations */ if(window) /* Boucle principale */ /* Destructions */ /* Destruction de la fenêtre */ SDL_DestroyWindow(window); fprintf(stderr,"Erreur de création de la fenêtre: %s\n",SDL_GetError()); /* Fermeture de la SDL */ SDL_Quit(); return 0;

7 Gestion du temps SDL_GetTicks() : temps écoulé depuis le lancement du programme (en ms) SDL_Delay(int time) : met en pause durant la durée time (en ms) Framerate cherché : 60 fps Attente entre 2 frames pour limiter le framerate frameTime = SDL_GetTicks(); /* update et draw */ currentTime = SDL_GetTicks(); if(currentTime - frameTime < 1000/60) SDL_Delay(1000/60-currentTime+frameTime);

8 Principes de base Structure du code
main.c le plus léger possible Définit la boucle de jeu et délègue Préfixes ou suffixe pour les noms de fonctions (exemple : updatePlayer() ou player_update()) Choisir une convention de nommage et s’y tenir Coder en anglais ou en français, mais pas les deux

9 Principes de base Gestion des entités
Utilisation de structures : Instantiation et destruction via des fonctions typedef struct Player { float x, y, w, h, vx, vy; int isOnGround; } Player; Player* initPlayer(float x, float y, float w, float h) { Player* player = malloc(sizeof(Player)); player->x = x; player->y = y; player->w = w; player->h = h; player->vx = 0; player->vy = 0; player->isOnGround = 0; return player; } void freePlayer(Player *player) free(player);

10 L’affichage avec SDL Utilisation du renderer
SDL_SetRenderDrawColor : choisit la couleur à utiliser Arguments : renderer et composantes RGBA de la couleur SDL_RenderFillRect : dessine un rectangle avec la couleur choisie Arguments : SDL_Renderer et SDL_Rect Autres fonctions : SDL_RenderDrawLine, SDL_RenderDrawPoint, SDL_RenderClear void drawRect(SDL_Renderer *renderer, int x, int y, int w, int h) { SDL_Rect rect; rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_RenderFillRect(renderer, &rect); }

11 L’affichage avec SDL Utilisation du renderer
SDL_SetRenderDrawColor : choisit la couleur à utiliser Arguments : renderer et composantes RGBA de la couleur SDL_RenderFillRect : dessine un rectangle avec la couleur choisie Arguments : SDL_Renderer et SDL_Rect Autres fonctions : SDL_RenderDrawLine, SDL_RenderDrawPoint, SDL_RenderClear void drawRect(SDL_Renderer *renderer, int x, int y, int w, int h) { SDL_Rect rect; rect.x = x; rect.y = y; rect.w = w; rect.h = h; SDL_RenderFillRect(renderer, &rect); } ATTENTION : l’axe y est vers le bas 800 600

12 Affichage du monde Monde = quadrillages avec cases remplies ou non

13 Affichage du monde Monde = tableau 2D hTile wTile h w

14 Affichage du monde Tableau 2D de dimensions (w, h) = tableau 1D de longueur w*h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 id ligne i colonne j = i*w + j Colonne de la case k = k%w Ligne de la case k = k/w

15 Gestion du monde #ifndef WORLD_H_INCLUDED #define WORLD_H_INCLUDED
typedef struct World { int *tiles; int w, h, wTile, hTile; } World; World* initWorld(int w, int h, int wTile, int hTile); void freeWorld(World *world); void setTile(World *world, int x, int y, int type); int getTile(World *world, int x, int y); void drawWorld(World *world, SDL_Renderer *renderer); #endif // WORLD_H_INCLUDED World* initWorld(int w, int h, int wTile, int hTile) { World* world = malloc(sizeof(World)); world->tiles = malloc(sizeof(int)*w*h); for(int i=0; i<w*h; i++) world->tiles[i] = 0; world->w = w; world->h = h; world->wTile = wTile; world->hTile = hTile; } void freeWorld(World *world) free(world->tiles); free(world); void setTile(World *world, int x, int y, int type) { world->tiles[x+world->w*y] = type; } int getTile(World *world, int x, int y) return world->tiles[x+world->w*y];

16 Gestion du monde void drawWorld(World *world, SDL_Renderer* renderer)
hTile void drawWorld(World *world, SDL_Renderer* renderer) { SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); for(int i=0; i<world->w; i++) for(int j=0; j<world->h; j++) if(getTile(world, i, j)) drawRect(renderer, world->wTile*i, world->hTile*j, world->wTile, world->hTile); } wTile j i

17 Gestion des événements
Utilisation de la structure SDL_Event SDL_PollEvent : remplit un SDL_Event Traite le plus vieil événement non traité Renvoie 0 si tous les événements ont été traités Utilisation dans une boucle : SDL_Event event; while(SDL_PollEvent(&event)) { /* Traitement de l’événement */ }

18 Gestion des événements
SDL_Event est une structure Event.type donne le type d’événement : SDL_WINDOWEVENT : événement concernant la fenêtre SDL_MOUSEBUTTONDOWN/ SDL_MOUSEBUTTONUP : bouton de la souris appuyé/relâché SDL_KEYDOWN/SDL_KEYUP : touche du clavier enfoncée/relâchée

19 Gestion des événements
SDL_WINDOWEVENT : event.window.event donne le type d’événement (fermer la fenêtre, agrandissement, etc) SDL_MOUSEBUTTONDOWN/ SDL_MOUSEBUTTONUP event.button.button donne l’id du bouton enfoncé Clic gauche => 1, clic droit => 3 SDL_KEYDOWN/SDL_KEYUP event.key.keysym.sym donne le code de la touche appuyée Les codes des touches sont définies dans des macros (SDLK_SPACE, SDLK_RIGHT, etc)

20 Gestion des événements
void updateInput(int *exitGame, World *world, Player *player) { SDL_Event event; while(SDL_PollEvent(&event)) switch(event.type) case SDL_WINDOWEVENT: if(event.window.event == SDL_WINDOWEVENT_CLOSE) *exitGame = 1; break; case SDL_MOUSEBUTTONDOWN: if(event.button.button == 1) int tileId = getTile(world, event.button.x / world->wTile, event.button.y / world->hTile); setTile(world, event.button.x / world->wTile, event.button.y / world->hTile, 1-tileId); } break; } Gestion des événements

21 Gestion du personnage Variables importantes :
Player* initPlayer(float x, float y, float w, float h) { Player* player = malloc(sizeof(Player)); player->x = x; player->y = y; player->w = w; player->h = h; player->vx = 0; player->vy = 0; player->isOnGround = 0; player->walkDir = 0; return player; } void freePlayer(Player *player) free(player); Variables importantes : Position x et y Dimensions Vitesse x et y (vx et vy) Deux autres valeurs seront nécessaires : isOnGround, pour savoir si on peut sauter walkDir donne la direction appuyée (-1 à gauche, 1 à droite et 0 si pas de touche appuyée) typedef struct Player { float x, y, w, h, vx, vy; int isOnGround, walkDir; } Player;

22 Gestion du personnage Constantes à définir : Gravité
Accélération lors de la marche Vitesse de marche maximum Le coefficient de ralentissement (friction) Force des sauts #define MAX_FALL_SPEED 10 #define GRAVITY 0.5 #define ACCELERATION 1 #define MAX_WALK_SPEED 10 #define FRICTION 0.90 #define JUMP_STRENGTH 10

23 Gestion du personnage void updatePlayer(Player* player, World *world)
{ player->vx += player->walkDir*ACCELERATION; if(player->vx > MAX_WALK_SPEED) player->vx = MAX_WALK_SPEED; if(player->vx < -MAX_WALK_SPEED) player->vx = -MAX_WALK_SPEED; player->vx *= FRICTION; if(player->vy < MAX_FALL_SPEED) player->vy += GRAVITY; player->x += player->vx; player->y += player->vy; } void jump(Player *player) { if(player->isOnGround) player->vy -= JUMP_STRENGTH; } void drawPlayer(SDL_Renderer *renderer, Player* player) { SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); drawRect(renderer, (int)player->x, (int)player->y, (int)player->w, (int)player->h); }

24 Gestion des collisions
v v v v

25 Gestion des collisions
? v

26 Gestion des collisions
Solution : décomposition du mouvement vx vx v vx vx vx

27 Gestion des collisions
void updatePlayer(Player* player, World *world) { player->vx += player->walkDir*ACCELERATION; if(player->vx > MAX_WALK_SPEED) player->vx = MAX_WALK_SPEED; if(player->vx < -MAX_WALK_SPEED) player->vx = -MAX_WALK_SPEED; player->vx *= FRICTION; if(player->vy < MAX_FALL_SPEED) player->vy += GRAVITY; player->x += player->vx; checkCollisionsX(player, world); player->y += player->vy; checkCollisionsY(player, world); } void checkCollisionsX(Player *player, World* world) { int topY = (player->y+1)/world->hTile; int bottomY = (player->y+player->h-1)/world->hTile; int leftX = player->x/world->wTile; int rightX = (player->x+player->w)/world->wTile; for(int j=topY; j<=bottomY; j++) if(player->vx < 0 && getTile(world, leftX, j)) player->x = leftX*world->hTile+world->wTile; player->vx = 0; } if(player->vx > 0 && getTile(world, rightX, j)) player->x = rightX*world->hTile-player->w;

28 Gestion des collisions
void updatePlayer(Player* player, World *world) { player->vx += player->walkDir*ACCELERATION; if(player->vx > MAX_WALK_SPEED) player->vx = MAX_WALK_SPEED; if(player->vx < -MAX_WALK_SPEED) player->vx = -MAX_WALK_SPEED; player->vx *= FRICTION; if(player->vy < MAX_FALL_SPEED) player->vy += GRAVITY; player->x += player->vx; checkCollisionsX(player, world); player->y += player->vy; checkCollisionsY(player, world); } void checkCollisionsY(Player *player, World* world) { player->isOnGround = 0; int topY = player->y/world->hTile; int bottomY = (player->y+player->h)/world->hTile; int leftX = (player->x+1)/world->wTile; int rightX = (player->x+player->w-1)/world->wTile; for(int i=leftX; i<=rightX; i++) if(player->vy < 0 && getTile(world, i, topY)) player->y = topY*world->hTile+world->hTile; player->vy = 0; } if(player->vy > 0 && getTile(world, i, bottomY)) player->y = bottomY*world->hTile-player->h; player->isOnGround = 1;

29 Affichage d’images Chargement de bitmap : SDL_Surface* SDL_LoadBMP(char *path); Autres format : voir SDL_Image Générer une texture à partir de la SDL_Surface : SDL_CreateTextureFromSurface(SDL_Renderer* renderer, SDL_Surface *image)

30 Affichage d’images SDL_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Rect *src, SDL_Rect *dst, float rotation, SDL_Point *rotationCenter, int flip); SDL_FLIP_HORIZONTAL, SDL_FLIP_VERTICAL ou SDL_FLIP_NONE

31 Affichage d’images : les Sprites

32 Affichage d’images : les Sprites
src dst

33 Animation du personnage
#define MAX_WALK_SPEED 5 #define FRICTION 0.90 #define JUMP_STRENGTH 5 #define ANIM_SPEED 6 #define W_IMG 48 #define H_IMG 48 typedef struct Player { float x, y, w, h, vx, vy; int isOnGround, walkDir; SDL_Texture* texture; SDL_Surface* image; int animX, animY, animTime, animDir; } Player; animX animY

34 Animation du personnage
Player* initPlayer(SDL_Renderer* renderer, float x, float y, float w, float h) { Player* player = malloc(sizeof(Player)); player->x = x; player->y = y; player->w = w; player->h = h; player->vx = 0; player->vy = 0; player->isOnGround = 0; player->walkDir = 0; player->image = SDL_LoadBMP("img/player.bmp"); SDL_SetColorKey( player->image, SDL_TRUE, SDL_MapRGB(player->image->format, 255, 0, 255)); player->texture = SDL_CreateTextureFromSurface(renderer, player->image); player->animX = 0; player->animY = 0; player->animTime = 0; return player; } Couleur transparente void freePlayer(Player *player) { SDL_DestroyTexture(player->texture); SDL_FreeSurface(player->image); free(player); }

35 Animation du personnage au sol
void updatePlayer(Player* player, World *world) { /* Animation au sol */ if(player->isOnGround) player->animY = 0; if(player->walkDir == 0) player->animX = 6; } else player->animTime++; if(player->animTime > ANIM_SPEED) player->animTime = 0; player->animX++; if(player->animX >= 6) player->animX = 0; /* … */ 1 2 3 4 5 6

36 Animation du personnage au sol
/* … */ else { player->animY = 3; player->animTime++; if(player->animTime > ANIM_SPEED) player->animTime = 0; player->animX++; if(player->animX >= 3) player->animX = 0; } 1 2 3

37 Affichage du personnage
if(event.key.keysym.sym == SDLK_RIGHT) { player->animDir = 1; player->walkDir = 1; } else if(event.key.keysym.sym == SDLK_LEFT) player->animDir = -1; player->walkDir = -1; void drawPlayer(SDL_Renderer *renderer, Player* player) { SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_Rect srcrect = {player->animX*W_IMG, player->animY*H_IMG, W_IMG, H_IMG}; SDL_Rect dstrect = {(int)player->x, (int)player->y, (int)player->w, (int)player->h}; SDL_Point center = {0, 0}; if(player->animDir == -1) SDL_RenderCopyEx(renderer, player->texture, &srcrect, &dstrect, 0, &center, SDL_FLIP_HORIZONTAL); else SDL_RenderCopyEx(renderer, player->texture, &srcrect, &dstrect, 0, &center, SDL_FLIP_NONE); }


Télécharger ppt "Codage d’un jeu de plateforme avec SDL 2.0"

Présentations similaires


Annonces Google