Day 12 - Démos rapides ← Précédent

Jour 13 - Jeu de platforme

C’est parti pour un tutorial assez dense, et il vaut mieux que vous ayez lu les autres tutoriaux/démos auparavant... Il est conseillé de lire les paragraphes sur les sprites, les backgrounds, les collisions, les animations et TOUS ceux concernant les maths avant de commencer...

Ceci vous apprendra les bases pour créer un jeu de plate-forme, avec Mario ! Eh oui, il est partout. Comme toujours, ce projet va se décomposer en plusieurs parties...

  1. Animer Mario, le faire bouger à l’écran, le faire sauter...
  2. Ajouter un background simple, avec scrolling, et faire bouger Mario dedans.
  3. Ajouter un background, avec un scrolling de paralaxe.

Etape 1 - Bouger, Sauter...

Ce sera assez simple, car nous allons réutiliser ce que nous avons déja vu... Je posterais le code complet ici. Pour le moment, j’ai décidé de couper le code en plusieurs sections. Je vais commencer avec les déclarations et la foncton “main”, avant de passer à la 2ème fonction :

Premièrement, prenons ce sympatique sprite de Mario:

Comme vous pouvez le voir, Il n’y a que 3 frames. Les 2 premières pour l’animation de la marche, et la 3ème pour le saut... Simple, mais efficace...

Maintenant, voici la première partie du code, basée sur les paragraphes Démos/Platforme:

// Inclusions, seulement un sprite
#include <PA9.h>
 
 
// Inclusion de PAGfxConverter
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"
 
 
typedef struct{
	s32 x, y;
	s32 vy; // utilisé pour le saut...
} mariotype;
 
mariotype mario;
 
#define GRAVITY 48
 
 
void MoveMario(void);
 
 
// Fonction principale
int main(void)	{
	// Initialisation de PAlib
	PA_Init();
	PA_InitVBL();
	
	PA_InitText(1, 0);
 
	PA_LoadSpritePal(0, 0, (void*)sprite0_Pal);	// Palette....	
 
	mario.x = 0<<8; mario.y = (192-32)<<8; // bas de l'écran... point fixe
	mario.vy = 0; // ne pas sauter
	PA_CreateSprite(0, 0,(void*)mario_Sprite, OBJ_SIZE_32X32,1, 0, mario.x>>8, mario.y>>8); // Sprite
	
	while(1)
	{
		MoveMario();
	
		PA_SetSpriteXY(0, 0, mario.x>>8, mario.y>>8);
	
		PA_WaitForVBL();
	}
	
	return 0;
}

Je ne m’attarderais pas sur le début, car ce ne sont que des inclusions normales, mais plutôt sur la structure du mouvement de Mario (utilisation d’un point fixe), et sur la macro concernant la gravité...

Ensuite, nous avons un petit void MoveMario(void);, qui est juste une fonction pour faire bouger Mario... Si le code n’est pas là, pourquoi l’avoir marqué?? Parce que cette fonction se trouve APRES la fonction “main”; il y a d’abord la déclaration de la fonction, puis main, puis la fonction.

Après l’initialisation normale, on initialise le texte pour l’écran du haut...

Après ça, on charge juste le sprite (sur l’écran du bas) et on initialise la position... Notez que nous utilisons un point fixe mathématique, c’est pourquoi le «8 est là... Et le »8 pour reconvertir en position normale, quand on place le sprite...

while(1)
{
	MoveMario();
	
	PA_SetSpriteXY(0, 0, mario.x>>8, mario.y>>8);
	
	PA_WaitForVBL();
}

Avant tout, la boucle principale ne fait pas grand-chose... Elle appelle une fonction (pour déplacer Mario), place le sprite à l’écran, et attend la synchronisation de l’écran... Rien de plus.

Maintenant nous allons taper la fonction MoveMario(), c’est-à-dire une grosse partie du code:

void MoveMario(void){
	if(Pad.Newpress.Right) {
		PA_StartSpriteAnim(0, 0, 0, 1, 6);
                PA_SetSpriteAnim(0, 0, 1);	
		PA_SetSpriteHflip(0, 0, 0);
	}
	else if(Pad.Newpress.Left) {
		PA_StartSpriteAnim(0, 0, 0, 1, 6);
                PA_SetSpriteAnim(0, 0, 1);	
		PA_SetSpriteHflip(0, 0, 1);
	}
	
	if ((Pad.Newpress.A) && (mario.vy == 0)){  // Si la touche A est pressée et que Mario est à terre
		mario.vy = -1000; // Début du saut
	}
 
	// Code du mouvement
	mario.x += (Pad.Held.Right - Pad.Held.Left)<<8;	 // le point fixe...
	
	// Et la gravité s'incruste...:)
	mario.vy += GRAVITY;
	mario.y += mario.vy;
	if (mario.y >= (192-32)<<8) {
		mario.y = (192-32)<<8;
		mario.vy = 0;
	}
	
	if (mario.vy != 0) PA_SetSpriteAnim(0, 0, 2); // Si la vitesse n'est pas nul, vérification que le sprite est celui du saut!
	else if(!((Pad.Held.Left)||(Pad.Held.Right))) PA_SetSpriteAnim(0, 0, 0);// L'image n'est ni dans les air ni en marche
}

Ça devrait vous être familier, puisqu’une partie du code est copiée des exemples d’Animation dans PaLib...

if(Pad.Newpress.Right) {
	PA_StartSpriteAnim(0, 0, 0, 1, 6);
        PA_SetSpriteAnim(0, 0, 1);	
	PA_SetSpriteHflip(0, 0, 0);
}

Ça veut tout simplement dire que si on appuie sur “Droit” pour la première fois, le sprite de devrait pas être “flippé” et l’animation devrait débuter, de la frame 0 à 1 (puisque l’animation de marche n’a que 2 frames), à une vitesse de 6 frames par seconde. 6fps cest vraiment lent, mais avec seulement 2 frames, c’est très bien.

PA_SetSpriteAnim(0,0,1);

Cette ligne permet à notre Mario de commencer à marcher des que l’on appuie sur une direction. (frame 1 au lieu de 0) Sinon Mario va donner l’impression de glisser sur le sol (surtout si on appuie de manière répété sur les touches) car dans la première image de l’animation Mario est en attente.

Si on n’a pas appuyé sur Droit, ça vérifie si on a pressé Gauche, dans ce cas, c’est pratiquement la même chose, mais cette fois, le sprite doit être “flippé” pour qu’il regarde dans la bonne direction..

Voila la première partie du code de saut/gravité

	if ((Pad.Newpress.A) && (mario.vy == 0)){ 
	mario.vy = -1000; // Commence à sauter
}

Lorsque vous pressez A, la vitesse vertical est fixée à son maximum (vous pouvez choisir de mettre plus si vous le souhaitez), alors mario saute... Pourquoi avons-nous besoin d’ajouter la condition mario.vy == 0 ? Si nous ne le faisions pas, vous pourriez pressez A autant de fois que vous le voulez, et le faire grimper encore et encore !! Avec ceci, vous ne pouvez pas démarrer un saut à moins d’être par terre...

Afin de bouger mario à gauche et à droite, il y a : ‘mario.x += (Pad.Held.Right - Pad.Held.Left)«8;’ ... A quoi sert le ‘«8’ ? Souvenez-vous que nous travaillons avec les nombres en points fixes, donc nous voulons juste avoir un mouvement de 1/256 pixel par tour ! Notez qu’avec ce code, vous pouvez changer de direction et bouger même dans les airs...

Viens ensuite la seconde partie du code de la gravité :

mario.vy += GRAVITY;
mario.y += mario.vy;
if (mario.y >= (192-32)<<8) {
	mario.y = (192-32)<<8;
	mario.vy = 0;
}

C’est comme nous l’avons déjà vu... A chaque frame, vous changez la vitesse selon la valeur de la gravité, et ainsi bougez le sprite selon la vitesse... Si le sprite sort de l’écran, vous devez changer sa position et fixer sa vitesse à 0....

La dernière partie du code (wow, c’était vraiment court !) permet de changer l’animation si vous êtes en train de sauter, et la stoppe si vous n’êtes pas en train de marcher :

if (mario.vy != 0) PA_SetSpriteAnim(0, 0, 2); 
else if(!((Pad.Held.Left)||(Pad.Held.Right))) PA_SetSpriteAnim(0, 0, 0);

Premièrement, si votre vitesse n’est pas nulle (que vous montiez ou descendez... donc quand vous êtes en l’air...), cela fixe l’animation à la dernière frame (frame 2), qui est la frame avec mario et yoshi dans les air... Si vous n’êtes pas en train de sauter, et pas en train de vous déplacer à droite ou à gauche, alors ceci fixe juste l’animation à 0 (la frame normal d’arrêt)

Et c’est tout pour la pour la partie 1 !! Revenez bientot pour la suite, plus intéressante mais une partie plus difficile, avec un système de collisions de tiles simple...

Step 2 - Basic Tile Collisions

Maintenant que notre petit mario peut se déplacer, nous allons ajouter un background, ainsi que les collisions avec lui... Voici les 2 backgrounds que j’ai ajoutés (1 pour les collisions, et l’autre pour l’arrière plan)

Comme vous pouvez le voir, ils sont exactement à la taille de l’écran de la DS, parce que nous n’allons pas faire de scrolling...

Je posterai le code complet, encore une fois, mais je vais expliquer pas à pas plusieurs parties :

// Includes, only one sprite
#include <PA9.h>
 
 
// PAGfxConverter Include
#include "gfx/all_gfx.c"
#include "gfx/all_gfx.h"
 
 
typedef struct{
	s32 x, y;
	s32 vy; // used for jumping...
	s32 flip;
} mariotype;
 
mariotype mario;
 
#define GRAVITY 48
#define MARIO_SPEED 512
 
 
void MoveMario(void);
void CheckCollisions(void);
u8 GetTile(s16 x, s16 y);
u8 LeftCollision(void);
u8 RightCollision(void);
u8 DownCollision(void);
u8 TouchingGround(void);
 

C’est le code qui précède la fonction main(). Comme vous pouvez le voir, j’ai ajouté la variable ‘flip’ dans une structure, qui sera utilisée plus tard. Il y a également quelques nouvelles fonctions déclarées, qui ont des noms simples, je parie que vous pouvez deviner ce que fait chacune d’elle... Quelques unes n’ont pas été déclarées comme ‘void’, mais comme ‘u8’, ce qui signifie qu’elles retourneront une valeur....

Regardons maintenant le code du main :

// Fonction Main
int main(void)	{
	// PAlib init
	PA_Init();
	PA_InitVBL();
	
	PA_InitText(1, 0);
 
	PA_LoadSpritePal(0, 0, (void*)sprite0_Pal);	// Palette....	
	
	PA_LoadPAGfxLargeBg(0, 1, mario_world); // plateformes...
	PA_LoadPAGfxLargeBg(0, 3, back); // back
	
	mario.x = 0<<8; mario.y = (128-32)<<8; // Bas de l'écran... point fixe
	mario.vy = 0; // ne saute pas
	mario.flip = 0;
	PA_CreateSprite(0, 0,(void*)mario_Sprite, OBJ_SIZE_32X32,1, 0, mario.x>>8, mario.y>>8); // Sprite
	
	while(1)
	{
		MoveMario();
	
		PA_SetSpriteXY(0, 0, mario.x>>8, mario.y>>8);
		
		PA_OutputText(1, 2, 9, "X : %d   ", mario.x >> 8);
		PA_OutputText(1, 2, 10, "Y : %d   ", mario.y >> 8);	
	
		PA_WaitForVBL();
	}
	
	return 0;
}

Je n’ai pas changé grand chose dans ce code. Il contient seulement 2 chargements de background supplémentaires :

  • PA_LoadPAGfxLargeBg(0, 1, mario_world); charge le background où l’on effectuera les collisions... J’ai utilisé un LargeBg parce que nous aurons besoin d’avoir plus de 512 pixels de large lorsque nous voudrons faire du scrolling...
  • PA_LoadPAGfxLargeBg(0, 3, back); est l’arrière plan, avec quelques nuages. Il se situe à la position 4, parce que rien ne peut se trouver derrière lui.

Pourquoi n’ai-je pas utilisé le background 0 pour mario_world ? Parce que nous en aurons besoin pour afficher le score, les pièces, etc ...

Dernier petit changement : J’ai ajouté 2 petits textes pour afficher la position de mario ...

Et maintenant, la fonction MoveMario() :

void MoveMario(void){
	if(Pad.Newpress.Right) {
		PA_StartSpriteAnim(0, 0, 0, 1, 6);
                PA_SetSpriteAnim(0, 0, 1);	
		PA_SetSpriteHflip(0, 0, 0);
		mario.flip = 0;
	}
	else if(Pad.Newpress.Left) {
		PA_StartSpriteAnim(0, 0, 0, 1, 6);
                PA_SetSpriteAnim(0, 0, 1);
		PA_SetSpriteHflip(0, 0, 1);
		mario.flip = 1;
	}
	
	if ((Pad.Newpress.A) && (TouchingGround())){  // Si A est pressé, et que mario n'est pas dans les airs
		mario.vy = -1200; // Start jumping
	}
 
	// Moving Code
	mario.x += (Pad.Held.Right - Pad.Held.Left)*MARIO_SPEED;	 // en point fixe
	
	// Add gravity
	mario.vy += GRAVITY;
	mario.y += mario.vy;
	
	CheckCollisions();
	
	if (!TouchingGround()) PA_SetSpriteAnim(0, 0, 2); // Pas sur le sol
	else if(!((Pad.Held.Left)||(Pad.Held.Right))) PA_SetSpriteAnim(0, 0, 0);// Image s'il n'est pas dans les air, et qu'il ne marche pas
}

Pas grand chose n’a changé, excepté :

  • if (Pad.Newpress.A) && (TouchingGround){ Maintenant, mario saute lorsque nous avons vérifié qu’il touche le sol.... En utilisant une nouvelle fonction, que nous verrons plus loin.
  • mario.x += (Pad.Held.Right - Pad.Held.Left)*MARIO_SPEED; J’ai décidé qu’il ne se déplaçait pas assez vite, alors j’ai ajouté une macro MARIO_SPEED, et j’ai fait en sorte qu’il se déplace de 2 pixels par frame, ce qui semble meilleur.
  • CheckCollisions(); est la nouvelle fonction de détection des collisions... nous la verrons juste après
  • if (!TouchingGround()) PA_SetSpriteAnim(0, 0, 2); est la commande qui montre mario en train de sauter... Plutôt que d’utiliser la vitesse comme précédemment, on vérifie maintenant si mario touche le sol ou non....

C’est tout pour ces fonctions, pas plus, comme je l’avais dit. Mais maintenant, toutes les fonctions restantes sont nouvelles, je les détaillerai toutes 1 par 1...

u8 GetTile(s16 x, s16 y){
	if (x < 0) return 1; // Say it was a collision...
	return mario_world_Map[((y>>3)*32) + (x>>3)];
}

Cette fonction très simple retourne le numéro du tile qui se situe à la position en pixels donnée en paramètre... Pourquoi n’ai-je mis que çà dans cette fonction ? Parce que lorsque nous ajouterons le scrolling, nous aurons juste besoin de changer cette fonction, et tout sera mis à jour... C’est simple, non ? Comment fait-elle pour trouver le bon tile ?

  • Elle vérifie déjà que ‘x’ possède une valeur valable (>0), et sinon elle retourne 0 (pas de tile).
  • Ensuite, elle lit le tile directement sur la carte du background...
    • (x»3) est la position du tile. X est divisé par 8 (équivalent de »3) parce qu’un tile est large de 8 pixels...
    • (y»3)*32 est composé de :
    • (y»3) pour récupérer la hauteur du tile, tout comme x»3, parce que les tiles ont une hauteur de 8 pixels
    • *32, parce que le background possède une largeur de 32 tiles, alors pour descendre d’un tile, vous devez ajouter 32 tiles... Nous devrons changer çà lorsque nous ajouterons le scrolling, pour que cela fonctionne avec des cartes plus grandes ....

Donc cette fonction retourne le numéro du tile... S’il n’y a pas de tile (un tile transparent), le numéro retourné sera 0... dans cette exemple, nous aurons une collision pour tous les numéros (de tiles) sauf 0. Ce qui signifie que vous aurez une collision avec tout. Si vous avez besoin d’autres collisions, comme passer à travers certains murs, vous devrez adapter le code à vos besoins (ceci est juste un code de base pour les débutants...)

u8 LeftCollision(void){
	return GetTile((mario.x>>8)+2, (mario.y>>8)+8+(mario.flip*13));
}
 
u8 RightCollision(void){
	return (GetTile((mario.x>>8)+29, (mario.y>>8)+8 + ((!mario.flip)*13)));
}

Ces 2 fonctions seront utilisées pour vérifier qu’il y a une collision à gauche ou à droite. La première chose, c’est qu’elles utilisent la fonction GetTile() que nous avons déjà vue, en lui passant la position normale de mario, en point non fixe, en d’autres termes ces coordonnées.

  • Pour la collision à gauche, elle vérifie aussi bien la position (de mario) en (2,8) qu’en (2,21), dépendant que le sprite soit tourné ou non... Pourquoi cela ? Parce que s’il est flippé (ie ‘retourné’), la collision sera effectué aussi bien avec le nez qu’avec le dos (il y a un espace sous le nez). Donc, s’il est “flippé” (ie ‘retourné’), la position vertical changera pour tester la collision à un endroit différent...
  • Pour la collision à droite, c’est la même chose, mais avec x = 29 au lieu de 2... et c’est la même chose pour le nez...

Pourquoi devons-nous tester x=2 ou 29, et pas x = 0 et x = 31 ? Parce si vous regardez le sprite de mario, en haut de la page, vous verrez qu’il y a 2 pixels vides de chaque côté... Donc nous devons seulement tester la collision là où se situe le dessin...

u8 DownCollision(void){
	return (mario.vy >= 0 && GetTile((mario.x>>8)+10 + (mario.flip*11), (mario.y>>8)+31));
}

Celui-ci teste si mario est en train de toucher un étage ou non. Si c’est le cas, nous devrons le remonter un petit peu... Ici, il y a encore le mario.flip !! Pourquoi cette fois-ci ? Parce que, regardez les pieds du sprite, ce qui déterminera la collision... Ils ne sont pas centrés ! Ce qui signifie qu’en fonction du coté où il regarde, ses pieds seront un peu plus à gauche ou à droite. C’est pris en compte en changeant la position actuelle de 10 à 21 s’il est flippé....

u8 TouchingGround(void){
	return GetTile((mario.x>>8)+10 + (mario.flip*11), (mario.y>>8)+32);
}

C’est la dernière vérification de collision. C’est exactement le même code que précédemment, mais 1 pixel plus bas (+32 au lieu de +31). Ça vérifie si le sol se trouve sous les pieds de yoshi...

Maintenant voici l’actuelle fonction CheckCollisions, qui utilisera toutes les fonctions dont nous avons parlé et ajustera les positions/vitesses...

void CheckCollisions(void){
 
	while(LeftCollision()){ // Collision sur la gauche du sprite...
		mario.x+= 256; // Déplacement d'un 1 pixel...
	}
	while(RightCollision()){ // Collision sur la droite du sprite...
		mario.x-= 256; // Déplacement d'un 1 pixel...
	}
	
	while(DownCollision()){ // Collision en bas du sprite...
		mario.y -= 128; // Déplacement de 1/2 pixel...
		mario.vy = 0; // Un étage est atteint...
	}
	if(TouchingGround()) mario.vy = 0;
 
}

Rien de plus à ajouter, en fait ! Tant que la sprite est touchée à gauche, déplacement à droite. Et tant qu’elle touche à droite, déplacement à gauche... Ça semble logique...

Pour la collision avec un étage, j’ai fait le déplacement d’1/2 pixel, juste pour le fun, lol... Si vous touchez un étage, alors la vitesse verticale devra être fixée à 0...

Il y a 2 parties différentes au niveau de la vérification du sol :

  • Une qui vérifie si vous êtes DANS le sol, et déplace mario et yoshi en conséquence (tant qu’il y est...)
  • Une qui regarde s’il y a un sol sous les pieds de yoshi, et mets ainsi la vitesse à 0 si c’est le cas...

Et c’est tout !

Maintenant que ça fonctionne, nous devons juste ajouter le scrolling (et un parallax scrolling, pour un meilleur effet), puis voir le résultat :-P Encore une fois, c’est un système de colision de tile basique, car il traite toutes les tiles de la même façon. Vous pourriez avoir une vérification différente, et ainsi faire en sorte que le joueur réagisse différemment à chaque type de tile...

Voici ce que j’ai obtenu en dualis r12 (r11 ne fonctionne pas avec la LargeMaps) :

Step 3 - Défilement de l'arrière plan

Maintenant que tout fonctionne, nous allons ajouter un défilement à l’arrière plan (défilement Parallax) pour donner une bonne impression de profondeur lorsqu’il y a défilement. Les 3 arrières plans qui seront utilisés sont :

Comme vous pouvez le remarquer, les trois images n’ont pas la même taille. Pourquoi ? Parce qu’elles ne vont pas défiler à la même vitesse ! Le premier plan (première image) défilera à une vitesse normale, c’est pourquoi il est plus grand et fait 1024px de largeur. Le second plan, défilera un peu plus doucement, et le plan contenant les nuages, défilera à une vitesse à peu près équivalente à 1/4 de la vitesse du premier plan, c’est pourquoi ce dernier plan n’a pas besoin d’être très long.

Je posterai le texte de PAGfx.ini une seule fois :

#TranspColor Magenta
 
#Sprites : 
mario.png 256colors sprite0
 
#Backgrounds : 
mario_world.png LargeMap
hills.png LargeMap
back.png LargeMap

Comme vous pouvez le voir, la couleur transparente est le magenta... Dans l’arrière plan des plateformes et des montagnes, il y a beaucoup de magenta qui deviendra transparent... Le dernier (les nuages), cependant, ne possède pas de magenta.. Comme il se situe derrière, vous ne voulez pas qu’il soit transparent... Tous les arrières plans sont déclarés comme LargeMap, parce qu’ils ont besoin d’être plus larges que 512 pixels ...

Pour cette troisième partie, je posterai seulement des bouts de codes, parce qu’il y a très peu de changement...

Concernant la structure de mario, j’ai juste ajouté un paramètre de défilement :

typedef struct{
	s32 x, y;
	s32 vy; // used for jumping...
	s32 flip;
	s32 scrollx; // Scroll value...
} mariotype;

Rien de plus à dire à propos de çà je crois. Il démarre à 0...

Ensuite, nous avons besoin de charger les arrières plans, chacun à un niveau différent :

PA_LoadPAGfxLargeBg(0, 1, mario_world); // plateforme...
PA_LoadPAGfxLargeBg(0, 2, hills); // montagne
PA_LoadPAGfxLargeBg(0, 3, back); // dernier / nuages

Maintenant que les arrières plans sont chargés, nous devons initialiser le défilement parallax... Si vous n’êtes pas sûr de ce que c’est, allez voir le tutorial sur les arrières plans et relisez la partie sur le défilement parallax... Le code est simple :

PA_InitParallaxX(0, 0, 256, 128, 64);
  • Ceci signifie que nous démarrons le défilement parallax sur l’écran 0, et qu’on ne l’active pas (0) sur le premier arrière plan (qui pourrait/devrait être utilisé pour le score et tout çà... )
  • Pour le premier arrière plan, il possède une vitesse de 256, ce qui signifie une vitesse normale...
  • Pour le deuxième arrière plan, il possède une vitesse de 128, donc çà sera seulement la moitié de la vitesse normale...
  • Pour le troisième arrière plan, la vitesse est 64, soit 1/4 de la vitesse normale...

Voici venir le seul code ajouté pour le défilement, lorsque mario atteint un bord :

MoveMario();
 
if ((((mario.x-mario.scrollx)>>8) > 160) && ((mario.x>>8) < 1024-128)){ // Scroll more...
	mario.scrollx = mario.x - (160<<8);		
}
else if ((((mario.x-mario.scrollx)>>8) < 64) && ((mario.x>>8) > 64)){
	mario.scrollx = mario.x - (64<<8);		
}
		
PA_ParallaxScrollX(0, mario.scrollx>>8);
	
PA_SetSpriteXY(0, 0, (mario.x-mario.scrollx)>>8, mario.y>>8);

Je l’ai ajouté après MoveMario, donc il possède la dernière position de la sprite...

Comme vous pouvez le remarquer, quand est-ce qu’il défile sur la droite ? Lorsque la position de mario sur l’écran est plus loin que 160 pixel, mais seulement si il n’a pas atteint la fin du niveau (1024-128 parce qu’on stoppe le défilement avant la fin...)

Et comment récupères-t-on la bonne valeur de défilement (en point fixé) ? mario.scrollx = mario.x - (160«8); Cela signifie que nous défilons assez pour positionner le sprite à une valeur maximum de x = 160... (excepté, encore une fois, si vous êtes à la fin du niveau)

La même chose est appliqué à l’autre direction, il y a défilement seulement si le sprite est à plus de 64 pixels du début, et le sprite n’est jamais placé avant les 64 pixels si possible...

PA_ParallaxScrollX(0, mario.scrollx>>8);

Ceci fait défiler les arrières plans par la valeur de défilement défini, on utilise » 8 parce que nous sommes en valeurs de point fixés, et le défilement parallax prends des valeurs normales...

Un autre changement est la position du sprite :

PA_SetSpriteXY(0, 0, (mario.x-mario.scrollx)>>8, mario.y>>8);

Ici, nous supprimons la valeur du défilement avant de positionner le sprite ... Cela veut dire que si mario.x est à 512, il sera placé avant l’écran pour concorder avec la valeur du défilement... n’est-pas propre ?

La dernière modification se situe dans la fonction GetTile() :

u8 GetTile(s16 x, s16 y){
	if (x < 0) return 1; // Say it was a collision...
	return mario_world_Map[((y>>3)*128) + (x>>3)];
}

J’ai changé le nombre de tiles horizontal de 32 (256 pixels) à 128 (1024 pixels de large), pour que cela fonctionne à nouveau...

Et c’est tout !!

Noté que pour avoir plus de collisions prises en compte, nous devrions utiliser une carte de collision, qui est une carte que vous feriez comme n’importe quelle carte dans un éditeur, mais que vous ne pourriez pas voir sur l’écran...

FAQ

  • Q1 Pourquoi est-ce que la position de mario est ((192-32)«8) ?
  • R1
    • La taille d’un écran de DS est de 192 pixels. (Voir jour 5).
    • Le background utilisé (Background) possède une montagne en bas de 32 pixels de haut
    • Au départ, la position de mario en x est 0 ce qui explique, d’après le background, qu’on le place en 192-32 pixels en ce qui concerne sa coordonnée y
  • Q2 A quoi servent tous ces “»8” et “«8” ?
  • R2 : Mollusk m’a expliqué que “»8” sert à récuperer la valeur entière (0.5,1,2,3,...) issue d’un point fixe defini par “«8” (128,256,512,768,...). Ce qui permet de varier la vitesse de déplacement de 1Px / (n Frames). (Edit: Edda)

Les “«n” et “»n” sont des décalages à gauche et à droite des bits. ainsi si c = 1 «3, cela correspond à faire c=1 puis un décalage des bits de c vers la gauche (un décalage de 1 multplie par 2) on a donc c = 8 (Edit: Skoual)

Prochain → Jour 14 - Carré rouge

 
day13.txt · Dernière modification: 24/06/2008 23:05 par 90.28.54.82
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki