Codage d’un jeu de plateforme avec SDL 2.0

Slides:



Advertisements
Présentations similaires
Interactivité et Lingo Interactivité - spécifier le déroulement en fonction des actions de l’usager Ex: Déroulement si l’usager clique Choix dans une liste.
Advertisements

ENT ENVOLE – Mes Dossiers Académie de la Réunion.
Créer un diaporama à l'aide d' Open Office Impress (2/2) Collège Victor Hugo (Carmaux - 81)
22/10/2011 Inkscape Le dessin vectoriel à portée de tous INKSCAPE Aru2L 22 octobre 2011.
200 lancers de dé Avec un tableur Avec un dé et un gobelet.
Le Smartpen Echo EMPRUNTER UN SMARTPEN DE LA BIBLIOTHÈQUE DE L’UQTR.
Guide de l'enseignant SolidWorks, leçon 1 Nom de l'établissement Nom de l'enseignant Date.
1 Programmation en C++ C++ de base ● Programme C++ ● Variables, objets, types ● Fonctions ● Namespace ● Tests ● Boucles ● Pointeurs, références.
1 Programmation en C++ C++ de base ● Programme C++ ● Variables, objets, types ● Types et opérations fondamentales ● Tests ● Boucles ● Pointeurs, références.
Utilisation du logiciel EduStat © Distribution de fréquences simples Les compilations.
Ooo.hg.free.fr visiteurs depuis 2005 Concevoir gratuitement et librement tous ses documents et activités d'Histoire Géographie avec OpenOffice.
1 Programmation en C++ IO en C++/SL ● Standard Library ● Types, objets pour IO ● L'entrée de clavier ● Sortie à l'écran ● Fichiers.
Chapitre 1 : Cinématique Objectif cinématique : étudier le mouvement des solides sans s’occuper des causes du mouvement  parle de position, trajectoire,
Interface sur laquelle on arrive lorsqu’on atteint le site Tous les champs ci- dessous sont supprimés Liste des clients disponibles Liste des serveurs.
1. 2 Boite à outils Qt ● Boite à outils C++ pour le développement multi-plateforme d'application en environnement graphique (GUI) – des fonctions GUI.
Réaliser un CD lecteur de salon (photos ou vidéos) pouvant être lu
Premiers pas avec PowerPoint
Synthèse TP 2 Codeblock 1 Les objectifs de ce tp sont :
Mener une activité.
Micro Informatique au Cellier
Leçon 4: Comprendre les graphiques
POWERPOINT 2013.
Cycle 3 Cycle 4 Pilotage du robot mBot Site scratch :
Utilisation de Windows
Initiation à la représentation d’une maison
Langage C Structure d'un programme Types Lire Ecrire Tester
LES TABLEAUX EN JAVA.
Session 1 6 mars 2017 Plateforme ICONICS Justine Guégan
Ajouter le code dans une page html
Collecte de données CAPI
Références.
Visite guidée - session 2
Section 1.1 : Unités du système international (SI)
Arguments de la ligne de commande
Pour cette découverte de S cratch !
Principes de programmation (suite)
Algorithmique & Langage C
5e CH2  Le diaporama.
Premiers pas sous Windows XP
  EXCEL FORMATION d'introduction.
GRAPHISME PAR ORDINATEUR
Codage Indenter le code Limiter la portée des variables Traiter les erreurs en premier Utiliser le switch au delà de 3 tests en cascades Ne jamais utiliser.
GRAPHISME PAR ORDINATEUR
Création Et Modification De La Structure De La Base De Données
Programmation en C++ C++ de base
SOLUTION DE VIDEOSURVEILLANCE SUR IP
SolidWorks : CREATION de VOLUMES
Gilles BADUFLE À partir d’un PPT modifié du C.A.H.M.
Programmation Android Première application Android
Utiliser PowerPoint dans le cadre des TPE
Présentation générale
Des calculs associés avec l’énergie
Le programme informatique L’algorithme Le codage
Logiciel de présentation
PRO1026 Programmation et enseignement
Sommaire : Les capteurs de force. Les capteurs à jauges de contraintes
Donnez votre avis ! Depuis votre smartphone, sur :
Les différents modes de démarrage de Windows
Le langage C# : Partie 1.
Sur la base d’exemples, ce diaporama recense l’ensemble des
Smart Graphic Layout SUJET déclaration
LE TORSEUR STATIQUE 1) Définition 2) Notation 3) Deux cas particuliers
STS Web Services libres Gérer les services libres
Python Nicolas THIBAULT
PROGRAMMATION SOUS R. PRESENTE PAR : ACHETTOU ISMAIL LAARICH TARIQ ENCADRE PAR : Pr. EXPOSÉ SUR LA PROGRAMMATION SUR R 2.
POINTS FORTS J’ai besoin svp : Création des masques
Les données structurées et leur traitement
Principales différences entre les systèmes d’exploitation MAC OS et Windows Nouveau : on insiste sur la partie formation.
Principales différences entre les systèmes d’exploitation Linux UBUNTU et Windows Nouveau : on insiste sur la partie formation 1.
Introduction à la programmation orientée objet Module 1:Position du problème Michel Poriaux HEPH Condorcet.
Transcription de la présentation:

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

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

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

Installation de la SDL Suivre le tutoriel de developpez.com (http://alexandre- 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)

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

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;

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);

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

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);

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); }

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

Affichage du monde Monde = quadrillages avec cases remplies ou non

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

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

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];

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

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 */ }

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

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)

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

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;

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

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); }

Gestion des collisions v v v v

Gestion des collisions ? v

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

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;

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;

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)

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

Affichage d’images : les Sprites

Affichage d’images : les Sprites src dst

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

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); }

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

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

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); }