Télécharger

Transcription

Télécharger
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
Écrit par Jay |
| Affichages : 2191
Note utilisateur:
/5
Mauvais
Très bien Note
Créons un jeu de plateformes de A à Z !
Tutoriel présenté par : Jérémie F. Bellanger
Dernière mise à jour : 30 octobre 2011
Difficulté :
Chapitre 19
Un ressort et une map animée !
Continuons d'améliorer notre petit jeu de plateformes, qui commence enfin à ressembler à quelque chose !
Nous allons maintenant programmer le ressort (pour qu'il envoie notre lapin valser en l'air !
occuperons d'animer la map en variant l'affichage de deux tilesets !
et ensuite nous nous
Résultat à la fin de ce chapitre : la map s'anime sous vos yeux ébahis et le ressort fonctionne !
Commençons par nous occuper de notre ressort !
Pour cela, il va nous falloir, une fois encore, modifier la fonction mapCollision() qui gère les collisions du joueur avec la map.
En effet, on va rajouter un nouveau test pour détecter les collisions avec la tile Ressort. Et, si c'est le cas, on fera simplement
sauter notre petit lapinou !
Nom du fichier : map.c
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
1/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
void mapCollision(GameObject *entity)
{
int i, x1, x2, y1, y2;
entity->onGround = 0;
if(entity->h > TILE_SIZE)
i = TILE_SIZE;
else
i = entity->h;
for (;
{
x1 = (entity->x + entity->dirX) / TILE_SIZE;
x2 = (entity->x + entity->dirX + entity->w - 1) / TILE_SIZE;
y1 = (entity->y) / TILE_SIZE;
y2 = (entity->y + i - 1) / TILE_SIZE;
if (x1 >= 0 && x2 < MAX_MAP_X && y1 >= 0 && y2 < MAX_MAP_Y)
{
//Si on a un mouvement à droite
if (entity->dirX > 0)
{
//Test de la tile Power-up : Etoile (= tile N°5)
if (map.tile[y1][x2] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y1][x2] = 0;
}
else if(map.tile[y2][x2] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y2][x2] = 0;
}
//On vérifie si les tiles recouvertes sont solides
if (map.tile[y1][x2] > BLANK_TILE || map.tile[y2][x2] > BLANK_TILE)
{
// Si c'est le cas, on place le joueur aussi près que possible
// de ces tiles, en mettant à jour ses coordonnées. Enfin, on réinitialise
//son vecteur déplacement (dirX).
entity->x = x2 * TILE_SIZE;
entity->x -= entity->w + 1;
entity->dirX = 0;
}
}
//Même chose à gauche
else if (entity->dirX < 0)
{
//Test de la tile Power-up : Etoile (= tile N°5)
if (map.tile[y1][x1] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y1][x1] = 0;
}
else if(map.tile[y2][x1] == 5)
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
2/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y2][x1] = 0;
}
if (map.tile[y1][x1] > BLANK_TILE || map.tile[y2][x1] > BLANK_TILE)
{
entity->x = (x1 + 1) * TILE_SIZE;
entity->dirX = 0;
}
}
}
//On sort de la boucle si on a testé toutes les tiles le long de la hauteur du sprite.
if (i == entity->h)
{
break;
}
//Sinon, on teste les tiles supérieures en se limitant à la heuteur du sprite.
i += TILE_SIZE;
if (i > entity->h)
{
i = entity->h;
}
}
//On recommence la même chose avec le mouvement vertical (axe des Y)
if(entity->w > TILE_SIZE)
i = TILE_SIZE;
else
i = entity->w;
for (;
{
x1 = (entity->x) / TILE_SIZE;
x2 = (entity->x + i) / TILE_SIZE;
y1 = (entity->y + entity->dirY) / TILE_SIZE;
y2 = (entity->y + entity->dirY + entity->h) / TILE_SIZE;
if (x1 >= 0 && x2 < MAX_MAP_X && y1 >= 0 && y2 < MAX_MAP_Y)
{
if (entity->dirY > 0)
{
/* Déplacement en bas */
//Test de la tile Power-up : Etoile (= tile N°5)
if (map.tile[y2][x1] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y2][x1] = 0;
}
else if(map.tile[y2][x2] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y2][x2] = 0;
}
/* Gestion du ressort */
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
3/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
if ((map.tile[y2][x1] == 7 ) || (map.tile[y2][x2] == 7 ))
{
//On met -20, pour lui faire faire un méga saut
entity->dirY = -20;
//On indique au jeu qu'il a atterri pour réinitialiser le double saut
entity->onGround = 1;
}
else if (map.tile[y2][x1] > BLANK_TILE || map.tile[y2][x2] > BLANK_TILE)
{
//Si la tile est solide, on y colle le joueur et
//on le déclare sur le sol (onGround).
entity->y = y2 * TILE_SIZE;
entity->y -= entity->h;
entity->dirY = 0;
entity->onGround = 1;
}
}
else if (entity->dirY < 0)
{
/* Déplacement vers le haut */
//Test de la tile Power-up : Etoile (= tile N°5)
if (map.tile[y1][x1] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y1][x1] = 0;
}
else if(map.tile[y1][x2] == 5)
{
//On appelle la fonction getItem()
getItem();
//On remplace la tile power-up par une tile transparente
map.tile[y1][x2] = 0;
}
if (map.tile[y1][x1] > BLANK_TILE || map.tile[y1][x2] > BLANK_TILE)
{
entity->y = (y1 + 1) * TILE_SIZE;
entity->dirY = 0;
}
}
}
//On teste la largeur du sprite (même technique que pour la hauteur précédemment)
if (i == entity->w)
{
break;
}
i += TILE_SIZE;
if (i > entity->w)
{
i = entity->w;
}
}
/* Maintenant, on applique les vecteurs de mouvement si le sprite n'est pas bloqué */
entity->x += entity->dirX;
entity->y += entity->dirY;
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
4/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
//Et on contraint son déplacement aux limites de l'écran, comme avant.
if (entity->x < 0)
{
entity->x = 0;
}
else if (entity->x + entity->w >= map.maxX)
{
entity->x = map.maxX - entity->w - 1;
}
//Maintenant, s'il sort de l'écran par le bas (chute dans un trou sans fond), on lance le timer
//qui gère sa mort et sa réinitialisation (plus tard on gèrera aussi les vies).
if (entity->y > map.maxY)
{
entity->timerMort = 60;
}
}
Bon, voilà, à peine trois lignes encore et le tour est joué !
On teste simplement si on a un ressort sous les pieds de notre super lapin, et si c'est le cas, on le fait sauter !
Attention toutefois à ne pas oublier le else après, sinon le jeu va tester que notre lapin est sur une tile solide et arrêter son saut !
Bon, il ne reste plus qu'à nous occuper de l'animation de la map maintenant !
Première chose, on va avoir besoin d'un second tileset ! Et comme je suis vraiment formidable
fois ! Enregistrez-le simplement dans le dossier graphics :
, je vous le donne encore une
tilesetB.png
Voilà, il ne reste maintenant plus qu'à charger notre tileset dans une nouvelle variable. Pour ça, on se rend dans notre fichier
structs.h et on va créer une nouvelle SDL_Surface pour notre second tileset. On va aussi créer un timer et une variable qui
contiendra le numéro du tileset à afficher pour gérer l'animation.
Nom du fichier : structs.h
/* Structure pour gérer la map à afficher (à compléter plus tard) */
typedef struct Map
{
SDL_Surface *background, *tileSet;
SDL_Surface *tileSetB;
/* Coordonnées de début, lorsqu'on doit dessiner la map */
int startX, startY;
/* Coordonnées max de fin de la map */
int maxX, maxY;
/* Tableau à double dimension représentant la map de tiles */
int tile[MAX_MAP_Y][MAX_MAP_X];
/* Timer et numéro du tileset à afficher pour animer la map */
int mapTimer, tileSetNumber;
} Map;
Maintenant que notre structure est à jour, on va charger notre nouveau tileset dans la fonction loadGame(), et initialiser notre
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
5/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
timer :
Nom du fichier init.c
void loadGame(void)
{
/* Charge l'image du fond et le tileset */
map.background = loadImage("graphics/background.png");
map.tileSet = loadImage("graphics/tileset.png");
map.tileSetB = loadImage("graphics/tilesetB.png");
//On initialise le timer
map.mapTimer = TIME_BETWEEN_2_FRAMES*3;
map.tileSetNumber = 0;
loadMap("map/map1.txt");
/* On initialise les variables du jeu */
jeu.vies = 3;
jeu.etoiles = 0;
/* On charge le HUD */
jeu.HUD_vie = loadImage("graphics/life.png");
jeu.HUD_etoiles = loadImage("graphics/stars.png");
}
Sans oublier de libérer le tileset à la fin, comme on l'a déjà vu !
Nom du fichier : init.c
void cleanup()
{
int i;
/* Libère l'image du background */
if (map.background != NULL)
{
SDL_FreeSurface(map.background);
}
/* Libère l'image des tilesets */
if (map.tileSet != NULL)
{
SDL_FreeSurface(map.tileSet);
}
if (map.tileSetB != NULL)
{
SDL_FreeSurface(map.tileSetB);
}
/* Libère le sprite du héros */
if (player.sprite != NULL)
{
SDL_FreeSurface(player.sprite);
}
/* Libère le sprite des monstres */
for(i = 0 ; i < MONSTRES_MAX ; i++)
{
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
6/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
if (monster[i].sprite != NULL)
{
SDL_FreeSurface(monster[i].sprite);
}
}
//Libère le HUD
if (jeu.HUD_etoiles != NULL)
{
SDL_FreeSurface(jeu.HUD_etoiles);
}
if (jeu.HUD_vie != NULL)
{
SDL_FreeSurface(jeu.HUD_vie);
}
/* Close the font */
closeFont(font);
/* Close SDL_TTF */
TTF_Quit();
/* Quitte la SDL */
SDL_Quit();
}
Voilà, notre nouveau tileset est désormais chargé et opérationnel ! Il ne reste plus qu"à l'afficher à l'aide d'un timer, en
alternance avec le premier. Un peu comme on avait fait pour animer nos sprites, quoi !
Pour cela, on va utiliser nos nouvelles variables dans la fonction drawMap() :
Nom du fichier map.c
void drawMap(void)
{
int x, y, mapX, x1, x2, mapY, y1, y2, xsource, ysource, a;
/* On initialise mapX à la 1ère colonne qu'on doit blitter.
Celle-ci correspond au x de la map (en pixels) divisés par la taille d'une tile (32)
pour obtenir la bonne colonne de notre map
Exemple : si x du début de la map = 1026, on fait 1026 / 32
et on sait qu'on doit commencer par afficher la 32eme colonne de tiles de notre map */
mapX = map.startX / TILE_SIZE;
/* Coordonnées de départ pour l'affichage de la map : permet
de déterminer à quels coordonnées blitter la 1ère colonne de tiles au pixel près
(par exemple, si la 1ère colonne n'est visible qu'en partie, on devra commencer à blitter
hors écran, donc avoir des coordonnées négatives - d'où le -1). */
x1 = (map.startX % TILE_SIZE) * -1;
/* Calcul des coordonnées de la fin de la map : jusqu'où doit-on blitter ?
Logiquement, on doit aller à x1 (départ) + SCREEN_WIDTH (la largeur de l'écran).
Mais si on a commencé à blitter en dehors de l'écran la première colonne, il
va falloir rajouter une autre colonne de tiles sinon on va avoir des pixels
blancs. C'est ce que fait : x1 == 0 ? 0 : TILE_SIZE qu'on pourrait traduire par:
if(x1 != 0)
x2 = x1 + SCREEN_WIDTH + TILE_SIZE , mais forcément, c'est plus long */
x2 = x1 + SCREEN_WIDTH + (x1 == 0 ? 0 : TILE_SIZE);
/* On fait exactement pareil pour calculer y */
mapY = map.startY / TILE_SIZE;
y1 = (map.startY % TILE_SIZE) * -1;
y2 = y1 + SCREEN_HEIGHT + (y1 == 0 ? 0 : TILE_SIZE);
//On met en place un timer pour animer la map (chapitre 19)
if(map.mapTimer <= 0)
{
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
7/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
if(map.tileSetNumber == 0)
{
map.tileSetNumber = 1;
map.mapTimer = TIME_BETWEEN_2_FRAMES*3;
}
else
{
map.tileSetNumber = 0;
map.mapTimer = TIME_BETWEEN_2_FRAMES*3;
}
}
else
map.mapTimer--;
/* Dessine la carte en commençant par startX et startY */
/* On dessine ligne par ligne en commençant par y1 (0) jusqu'à y2 (480)
A chaque fois, on rajoute TILE_SIZE (donc 32), car on descend d'une ligne
de tile (qui fait 32 pixels de hauteur) */
for (y = y1; y < y2; y += TILE_SIZE)
{
/* A chaque début de ligne, on réinitialise mapX qui contient la colonne
(0 au début puisqu'on ne scrolle pas) */
mapX = map.startX / TILE_SIZE;
/* A chaque colonne de tile, on dessine la bonne tile en allant
de x = 0 à x = 640 */
for (x = x1; x < x2; x += TILE_SIZE)
{
//Si la tile à dessiner n'est pas une tile vide
if (map.tile[mapY][mapX] != 0)
{
/*On teste si c'est une tile monstre (tile numéro 10) */
if (map.tile[mapY][mapX] == 10)
{
//On initialise un monstre en envoyant les coordonnées de la tile
initializeMonster(mapX * TILE_SIZE, mapY * TILE_SIZE);
//Et on efface cette tile de notre tableau pour éviter un spawn de monstres
//infini !
map.tile[mapY][mapX] = 0;
}
}
/* Suivant le numéro de notre tile, on découpe le tileset (a = le numéro
de la tile */
a = map.tile[mapY][mapX];
/* Calcul pour obtenir son y (pour un tileset de 10 tiles
par ligne, d'où le 10 */
ysource = a / 10 * TILE_SIZE;
/* Et son x */
xsource = a % 10 * TILE_SIZE;
/* Fonction qui blitte la bonne tile au bon endroit suivant le timer */
if(map.tileSetNumber == 0)
drawTile(map.tileSet, x, y, xsource, ysource);
else
drawTile(map.tileSetB, x, y, xsource, ysource);
mapX++;
}
mapY++;
}
}
Voilà, donc suivant la valeur du timer, on passe du tileset 0 au 1 et on l'affiche.
Notez que j'ai utilisé une tempo 3 fois plus lente pour l'animation de la map que pour celle des persos. C'est une question de
goût. Vous pouvez la changer en modifiant TIME_BETWEEN_2_FRAMES * 3. Vous pouvez aussi créer une nouvelle def, si
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
8/9
7/9/2014
Big Tuto SDL 1.2 - Chapitre 19 : Un ressort et une map animée
vous le souhaitez.
Bon, il ne reste plus maintenant qu'à compiler et tadaaa ! Notre map s'anime et le ressort envoie notre lapin vers d'autres cieux !
On commence vraiment à avoir un bon petit jeu quand même !
Bon, allez, et si maintenant on rajoutait quelques sons pour faire mieux ? Cool, non ?
Mais on verra ça dans le prochain chapitre !
Télécharger le projet Code::Blocks - chapitre 19 !
http://www.meruvia.fr/index.php/big-tuto-sdl-1/60-big-tuto-chapitre-19-un-ressort-et-une-map-animee?tmpl=component&print=1&page=
9/9

Documents pareils

Big Tuto SDL 2 - Chapitre 7 : Apprenons à utiliser le level editor Big

Big Tuto SDL 2 - Chapitre 7 : Apprenons à utiliser le level editor Big - en marron, on trouve les tiles solides : placées sur la couche Action, le joueur et les monstres marcheront dessus et se cogneront dedans. C'est avec elles qu'on créera le sol et les murs. Attent...

Plus en détail