
Big Tuto SFML 2 / Action-RPG : Legends of Meruvia
Chapitre 17 : Ajoutons des menus de base !
Tutoriel présenté par : Jérémie F. Bellanger (Jay81)
Date d'écriture : 8 juillet 2016
Date de révision : -
Prologue
Et voilà, plus que deux chapitres et, comme vous allez vite vous en rendre compte, si vous avez déjà lu le Big Tuto Rabidja, cela va presque être du copier / coller à quelques modifications près ! 
Mais cela me donne une idée ! ![]()
Si vous avez déjà bien compris comment on a créé des menus dans Rabidja, vous pouvez essayer de les adapter ici, tout seuls ! Cela ferait un bon entraînement ! ![]()
Et puis, bon, si vous n'y arrivez pas ou que vous avez un doute, voilà la soluce ! ![]()
Nouveau fichier
Avant de commencer, vérifiez bien que vous avez ce magnifique écran-titre dans votre projet. ![]()
Il devrait se trouver dans le dossier graphics sous le nom title.png. ![]()

title.png
Le code
Pour éviter de mélanger les menus avec le reste du jeu, on va commencer par créer une nouvelle classe Menus, dont voilà le header :
Fichier : menus.h : Créer le fichier et y copier :
|
//Legends of Meruvia - C++ / SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#ifndef MENUS_H
#define MENUS_H
#include <SFML/Graphics.hpp>
#include <iostream>
class Input;
class Map;
class Player;
class Menus
{
public:
//Constructeur
Menus();
//Accesseurs
bool getOnMenu(void) const;
int getMenuType(void) const;
//Mutateurs
void setOnMenu(bool valeur, int type);
//Fonctions
void updateStartMenu(Input &input, Map &map, Player &player);
void drawStartMenu(sf::RenderWindow &window, Map &map);
void updatePauseMenu(Input &input);
void drawPauseMenu(sf::RenderWindow &window, Map &map);
private:
//Variables de la classe en accès privé
bool onMenu;
int menuType, choice;
int tempo;
//Ecran-titre
sf::Texture titleScreenTexture;
sf::Sprite titleScreen;
//Une enum pour la gestion du menu.
const enum { START, PAUSE };
//Enum pour les boutons
const enum{ up, down, right, left, attack, jump, enter };
/******************/
/* Constantes */
/******************/
//Timer (compte à rebours) entre la prise en compte de 2 appuis
//successifs sur la même touche
const int TIMER = 12;
};
#endif
|
Pour pouvoir rajouter des menus à notre jeu, il faut en fait que celui-ci gère plusieurs états. Le premier état, celui que nous avons pour l'instant est l'état "inGame", ou "en jeu" (même si on n'aura pas besoin de variable pour l'indiquer, en fait
). Ce qui veut dire que le programme exécute le jeu normalement. Nous allons lui rajouter un deuxième état : "onMenu", soit "dans un menu", à l'aide d'une nouvelle variable (un booléen), et nous enregistrerons le type de menu à afficher dans une autre variable grâce à une nouvelle énum que l'on va ajouter en constante.
Voici un récapitulatif de nos nouvelles variables :
Logiquement, le début de notre fichier va donc contenir une fonction :
Et ensuite, pour gérer chacun de nos menus, on aura besoin de 2 fonctions classiques : update() pour le mettre à jour et draw() pour le dessiner. ![]()
Mais que vont faire nos menus exactement ? ![]()
Notre menu Start va afficher l'écran-titre de notre jeu, et proposer deux options : Start et Quit (oui, je sais, c'est super simpliste. Vous ferez des super menus compliqués plus tard, quand vous aurez compris les bases !
).
Notre menu Pause s'affichera si on presse Enter (ou Start sur le gamepad) : il stoppera le jeu et proposera soit de continuer, soit de quitter la partie.
Voilà pour la théorie, alors place au code ! ![]()
Fichier : menus.cpp : Créer le fichier et y copier :
|
//Legends of Meruvia - C++ / SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#include "menus.h"
#include "input.h"
#include "map.h"
#include "player.h"
using namespace std;
using namespace sf;
//Constructeur
Menus::Menus()
{
//Chargement de la spritesheet de Rabidja
if (!titleScreenTexture.loadFromFile("graphics/title.png"))
{
// Erreur
cout << "Erreur durant le chargement de l'image de l'écran-titre." << endl;
}
else
titleScreen.setTexture(titleScreenTexture);
onMenu = true;
menuType = START;
choice = 0;
tempo = TIMER;
}
//Accesseurs
bool Menus::getOnMenu(void) const { return onMenu; }
int Menus::getMenuType(void) const { return menuType; }
//Mutateur
void Menus::setOnMenu(bool valeur, int type)
{
onMenu = valeur;
menuType = type;
}
//Fonctions
void Menus::updateStartMenu(Input &input, Map &map, Player &player)
{
//Si on appuie sur BAS
if (input.getButton().down)
{
input.setButton(down, false);
//Si choice = O (il est sur start), on le met à 1 (quit)
if (choice == 0)
choice++;
}
//Si on appuie sur HAUT
else if (input.getButton().up)
{
input.setButton(up, false);
//Si choice = 1 (il est sur Quit), on le met à 0 (Start)
if (choice == 1)
choice--;
}
//Si on appuie sur Enter ou A (manette Xbox 360) et qu'on est sur Start, on recharge le jeu et on quitte l'état menu
if (input.getButton().enter || input.getButton().attack)
{
if (choice == 0)
{
//On commence au premier niveau
map.setLevel(1);
map.changeLevel();
/* On réinitialise les variables du jeu */
player.initialize(map);
player.setGold(100);
onMenu = false;
}
//Sinon, on quitte le jeu
else if (choice == 1)
{
exit(0);
}
input.setButton(enter, false);
input.setButton(attack, false);
}
//On décrémente notre compte à rebours (Timer)
tempo--;
}
void Menus::updatePauseMenu(Input &input)
{
//Si on appuie sur BAS
if (input.getButton().down)
{
//Si choice = O (il est sur start), on le met à 1 (quit)
if (choice == 0)
choice++;
input.setButton(down, false);
}
//Si on appuie sur HAUT
if (input.getButton().up)
{
//Si choice = 1 (il est sur Quit), on le met à 0 (Start)
if (choice == 1)
choice--;
input.setButton(up, false);
}
//Si on appuie sur Enter ou A (manette Xbox 360) et qu'on est sur Start, on recharge le jeu et on quitte l'état menu
if (input.getButton().enter || input.getButton().attack)
{
if (choice == 0)
{
//Si on appuie sur Enter on quitte l'état menu
onMenu = false;
}
//Sinon, on quitte le jeu
else if (choice == 1)
{
choice = 0;
menuType = START;
}
input.setButton(enter, false);
input.setButton(attack, false);
}
}
void Menus::drawStartMenu(RenderWindow &window, Map &map)
{
//On affiche l'écran-titre
window.draw(titleScreen);
//Si l'option n'est pas en surbrillance, on l'affiche normalement
if (choice != 0)
{
//Ombrage en noir
map.drawText(window, "NEW GAME", 28, 395, 252, Color::Black);
map.drawText(window, "NEW GAME", 28, 393, 250, Color::White);
}
if (choice != 1)
{
//Ombrage en noir
map.drawText(window, "QUIT", 28, 425, 292, Color::Black);
map.drawText(window, "QUIT", 28, 422, 290, Color::White);
}
//Si l'option est en surbrillance, on change la couleur
if (choice == 0)
{
map.drawText(window, "NEW GAME", 28, 395, 252, Color::Black);
map.drawText(window, "NEW GAME", 28, 393, 250, Color::Yellow);
}
else if (choice == 1)
{
//Ombrage en noir
map.drawText(window, "QUIT", 28, 425, 292, Color::Black);
map.drawText(window, "QUIT", 28, 422, 290, Color::Yellow);
}
}
void Menus::drawPauseMenu(RenderWindow &window, Map &map)
{
//On écrit PAUSE
map.drawText(window, "** PAUSE **", 28, 332, 200, Color::Black);
map.drawText(window, "** PAUSE **", 28, 330, 198, Color::White);
//Si l'option n'est pas en surbrillance, on l'affiche normalement
if (choice != 0)
{
//Ombrage en noir
map.drawText(window, "Continue", 28, 346, 252, Color::Black);
map.drawText(window, "Continue", 28, 344, 250, Color::White);
}
if (choice != 1)
{
//Ombrage en noir
map.drawText(window, "Exit", 28, 378, 292, Color::Black);
map.drawText(window, "Exit", 28, 376, 290, Color::White);
}
//Si l'option est en surbrillance, on change la couleur
if (choice == 0)
{
//Ombrage en noir
map.drawText(window, "Continue", 28, 346, 252, Color::Black);
map.drawText(window, "Continue", 28, 344, 250, Color::Yellow);
}
else if (choice == 1)
{
//Ombrage en noir
map.drawText(window, "Exit", 28, 378, 292, Color::Black);
map.drawText(window, "Exit", 28, 376, 290, Color::Yellow);
}
}
|
Comme vous pouvez le voir, le code n'est pas très compliqué. ![]()
Pour updateStartMenu(), la première ligne permet de lancer le jeu, tandis que la seconde permet de quitter proprement (c'est plus pro qu'avec la touche Escape
).
Le code d'updatePauseMenu() reprend grosso modo celui de l'écran-titre avec deux possibilités : soit on reprend le jeu, soit on retourne à l'écran-titre en changeant simplement le menuType. ![]()
Vous remarquerez aussi qu'on remet systématiquement les inputs à false, pour une raison simple : sinon on valide tous les menus à la suite, et on passe de l'un à l'autre en un éclair (vous pouvez essayer, pour voir, si vous êtes joueur !
). Grâce à cette technique, le joueur sera obligé de lâcher le bouton et de réappuyer s'il veut valider une seconde fois.
Fichier : main.h : Modifier le code :
|
//Legends of Meruvia - C++ / SFML 2 //Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#include <cstdlib> #include <iostream> #include <SFML/Graphics.hpp>
#include "input.h" #include "map.h" #include "player.h" #include "monster.h" #include "sounds.h" #include "magic.h" #include "menus.h"
using namespace std; using namespace sf;
//Fonctions void update(Input &input, Map &map, Player &player, Monster monster[], Sounds &sounds, Magic magic[], Menus &menus); void draw(sf::RenderWindow &window, Map &map, Player &player, Monster monster[], Magic magic[], Menus &menus);
// Taille de la fenêtre : 800x480 pixels const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 480;
//Nombre max de monstres à l'écran const int MONSTRES_MAX = 50;
//Nombre max de projectiles magiques à l'écran const int MAGIC_MAX = 6; const int TIME_BETWEEN_2_SHOTS = 30; const int MOONWALK_TIMER = 8;
//Directions const int DOWN = 0; const int UP = 1; const int RIGHT = 2; const int LEFT = 3;
//Une enum pour la gestion du menu. const enum { START, PAUSE }; |
Ici, on ne change pas grand chose, on ajoute simplement :
- #include "menus.h" en haut du fichier,
- notre constante enum pour les menus,
- et on met à jour les prototypes de update() et draw().
Fichier : main.cpp : Modifier le code :
|
//Legends of Meruvia - C++ / SFML 2.3.2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#include "main.h"
int main(int argc, char *argv[])
{
// Création d'une fenêtre en SFML
RenderWindow window(VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32),
"Meruvia - Big Tuto A-RPG/SFML2 - Chapitre 17 - www.meruvia.fr");
//On active la synchro verticale
window.setVerticalSyncEnabled(true);
//Instanciation des classes
Input input;
Map map;
Player player;
Sounds sounds;
Menus menus;
//On instancie autant de classes que de monstres gérables
Monster monster[MONSTRES_MAX];
//On instancie autant de classes que de projectiles magiques gérables
Magic magic[MAGIC_MAX];
//On lance la musique en boucle
sounds.PlayMusic(true);
//On commence au premier niveau
map.setLevel(1);
map.changeLevel();
//On initialise le player
player.initialize(map);
player.setGold(100);
//On commence par le menu start
menus.setOnMenu(true, START);
// Boucle infinie, principale, du jeu
while (window.isOpen())
{
// Gestion des inputs
input.gestionInputs(window);
//Updates
update(input, map, player, monster, sounds, magic, menus);
// Dessin - draw
draw(window, map, player, monster, magic, menus);
window.display();
}
// On quitte
return 0;
}
//Fonction de mise à jour du jeu : gère la logique du jeu
void update(Input &input, Map &map, Player &player, Monster monster[], Sounds &sounds, Magic magic[], Menus &menus)
{
//Si on n'est pas dans un menu
if (!menus.getOnMenu())
{
//On met à jour le player
player.update(input, map, magic, menus);
//On met à jour les monstres un par un
for (int i = 0; i < map.getNombreMonstres(); i++)
{
if (monster[i].update(i, map, player, monster, sounds) == 2)
{
//Si l'update du monstre renvoie 2, c'est qu'il doit mourir :
//on copie à sa place le dernier monstre avant de retirer un monstre
monster[i].copy(monster[map.getNombreMonstres() - 1]);
map.setNombreMonstres(map.getNombreMonstres() - 1);
}
}
//On met à jour les projectiles magiques un par un
for (int i = 0; i < player.getMagic(); i++)
{
if (magic[i].update(player, map) == 1)
{
//On supprime le projectile magique s'il sort de l'écran
magic[i].copy(magic[player.getMagic() - 1]);
player.setMagic(player.getMagic() - 1);
}
else
{
//On teste les collisions avec tous les monstres
for (int j = 0; j < map.getNombreMonstres(); j++)
{
if (magic[i].checkCollisions(monster[j]) == 1)
{
//Si la fonction renvoie 2, c'est qu'il y a contact avec le monstre
//Celui-ci doit être blessé et il faut supprimer le projectile magique.
//Et on blesse le monstre s'il n'est pas invincible
if (monster[j].getInvincibleTimer() == 0)
{
monster[j].setLife(monster[j].getLife() - 1);
monster[j].setInvincibleTimer(TIME_BETWEEN_2_SHOTS);
}
//Si le monstre est mort
if (monster[j].getLife() <= 0)
{
//On copie à sa place le dernier monstre avant de retirer un monstre
monster[j].copy(monster[map.getNombreMonstres() - 1]);
map.setNombreMonstres(map.getNombreMonstres() - 1);
}
else
{
//On le déclare touché, pour qu'il recule en arrière
monster[j].setisHurt(MOONWALK_TIMER);
//On détermine sa direction de recul, par rapport au placement
//de l'ennemi
if (magic[i].getDirection() == DOWN)
monster[j].setHurtDirection(DOWN);
else if (magic[i].getDirection() == UP)
monster[j].setHurtDirection(UP);
else if (magic[i].getDirection() == RIGHT)
monster[j].setHurtDirection(RIGHT);
else if (magic[i].getDirection() == LEFT)
monster[j].setHurtDirection(LEFT);
}
//On supprime le projectile magique
magic[i].copy(magic[player.getMagic() - 1]);
player.setMagic(player.getMagic() - 1);
//On joue le sound Fx
sounds.PlaySoundFx(sounds.DESTROY);
}
}
}
}
}
else
{
if (menus.getMenuType() == START)
menus.updateStartMenu(input, map, player);
else if (menus.getMenuType() == PAUSE)
menus.updatePauseMenu(input);
}
}
//Fonction de dessin du jeu : dessine tous les éléments
void draw(RenderWindow &window, Map &map, Player &player, Monster monster[], Magic magic[], Menus &menus)
{
//On efface tout
window.clear();
//Si on n'est pas dans un menu, ou si on est en pause, on affiche le jeu
if (!menus.getOnMenu() || (menus.getOnMenu() && menus.getMenuType() == PAUSE))
{
// Affiche la map de tiles : layer 2 (couche du fond)
map.draw(2, window, monster);
// Affiche la map de tiles : layer 1 (couche active : sol, etc.)
map.draw(1, window, monster);
// Affiche le joueur
player.draw(map, window);
//On affiche les monstres un par un
for (int i = 0; i < map.getNombreMonstres(); i++)
{
monster[i].draw(map, window);
}
//On affiche les projectiles magiques un par un
for (int i = 0; i < player.getMagic(); i++)
{
magic[i].draw(map, window);
}
// Affiche la map de tiles : layer 3 (couche en foreground / devant)
map.draw(3, window, monster);
//Affichage du HUD
map.drawHud(player, window);
//Affichage du menu PAUSE le cas échéant
if (menus.getOnMenu() && menus.getMenuType() == PAUSE)
menus.drawPauseMenu(window, map);
}
//Sinon, on affiche l'écran-titre
else if (menus.getOnMenu() && menus.getMenuType() == START)
menus.drawStartMenu(window, map);
}
|
Passons maintenant à notre fonction player.update(), dans laquelle on va gérer l'appui sur la touche Enter (ou start) pour ouvrir le menu de Pause ! ![]()
Par souci de commodité, je vous ai remis toute la fonction player.update() ci-dessous :
Fichier : player.cpp : Modifier le code :
|
//Legends of Meruvia - C++ / SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#include "player.h"
#include "map.h"
#include "input.h"
#include "sounds.h"
#include "magic.h"
#include "menus.h"
//Code coupé...
void Player::update(Input &input, Map &map, Magic magic[], Menus &menus)
{
//On rajoute un timer au cas où notre héros mourrait lamentablement en tombant dans un trou...
//Si le timer vaut 0, c'est que tout va bien, sinon, on le décrémente jusqu'à 0, et là,
//on réinitialise.
//C'est pour ça qu'on ne gère le joueur que si ce timer vaut 0.
if (timerMort == 0)
{
//On gère le timer de l'invincibilité
if (invincibleTimer > 0)
invincibleTimer--;
//On réinitialise nos vecteurs de déplacement, pour éviter que le perso
//ne fonce de plus en plus vite pour atteindre la vitesse de la lumière ! ;)
//Essayez de le désactiver pour voir !
dirX = 0;
dirY = 0;
//Gestion de la course en appuyant sur la touche courir
if (input.getButton().run)
isrunning = 1;
else
isrunning = 0;
//Voilà, au lieu de changer directement les coordonnées du joueur, on passe par un vecteur
//qui sera utilisé par la fonction mapCollision(), qui regardera si on peut ou pas déplacer
//le joueur selon ce vecteur et changera les coordonnées du player en fonction.
if (input.getButton().left == true)
{
dirX -= PLAYER_SPEED + isrunning;
//Et on indique qu'il va à gauche (pour le flip
//de l'affichage, rappelez-vous).
direction = LEFT;
//Si ce n'était pas son état auparavant :
if (etat != WALK)
{
//On enregistre l'anim' de la marche et on l'initialise à 0
etat = WALK;
frameNumber = 0;
frameTimer = TIME_BETWEEN_2_FRAMES_PLAYER;
frameMax = 8;
}
}
//Si on détecte un appui sur la touche fléchée droite
else if (input.getButton().right == true)
{
//On augmente les coordonnées en x du joueur
dirX += PLAYER_SPEED + isrunning;
//Et on indique qu'il va à droite (pour le flip
//de l'affichage, rappelez-vous).
direction = RIGHT;
//Si ce n'était pas son état auparavant
if (etat != WALK)
{
//On enregistre l'anim' de la marche et on l'initialise à 0
etat = WALK;
frameNumber = 0;
frameTimer = TIME_BETWEEN_2_FRAMES_PLAYER;
frameMax = 8;
}
}
//Si on détecte un appui sur la touche fléchée haut
else if (input.getButton().up == true)
{
//On augmente les coordonnées en x du joueur
dirY -= PLAYER_SPEED + isrunning;
//Et on indique qu'il va à droite (pour le flip
//de l'affichage, rappelez-vous).
direction = UP;
//Si ce n'était pas son état auparavant
if (etat != WALK)
{
//On enregistre l'anim' de la marche et on l'initialise à 0
etat = WALK;
frameNumber = 0;
frameTimer = TIME_BETWEEN_2_FRAMES_PLAYER;
frameMax = 8;
}
}
//Si on détecte un appui sur la touche fléchée bas
else if (input.getButton().down == true)
{
//On augmente les coordonnées en x du joueur
dirY += PLAYER_SPEED + isrunning;
//Et on indique qu'il va à droite (pour le flip
//de l'affichage, rappelez-vous).
direction = DOWN;
//Si ce n'était pas son état auparavant
if (etat != WALK)
{
//On enregistre l'anim' de la marche et on l'initialise à 0
etat = WALK;
frameNumber = 0;
frameTimer = TIME_BETWEEN_2_FRAMES_PLAYER;
frameMax = 8;
}
}
//Si on n'appuie sur rien, on charge l'animation marquant l'inactivité (Idle)
else if (input.getButton().right == false && input.getButton().left == false &&
input.getButton().up == false && input.getButton().down == false)
{
//On teste si le joueur n'était pas déjà inactif, pour ne pas recharger l'animation
//à chaque tour de boucle
if (etat != IDLE)
{
//On enregistre l'anim' de l'inactivité et on l'initialise à 0
etat = IDLE;
frameNumber = 0;
frameTimer = TIME_BETWEEN_2_FRAMES_PLAYER;
frameMax = 8;
}
}
//On gère la magie
if (input.getButton().magie)
{
//Si on le peut, on crée un nouveau shuriken
if (magicNumber < MAGIC_MAX && MP > 15)
{
magic[magicNumber].initialize(direction, x, y);
magicNumber++;
MP -= 15;
}
input.setButton(magie, false);
}
if (MP < MPmax)
MP += regainTime;
//On gère l'attaque
if (input.getButton().attack)
{
isAttacking = 1;
input.setButton(attack, false);
}
//Si on appuie sur Enter
if (input.getButton().enter)
{
//On met le jeu en pause
menus.setOnMenu(true, PAUSE);
input.setButton(enter, false);
}
//On rajoute notre fonction de détection des collisions qui va mettre à
//jour les coordonnées de notre héros.
mapCollision(map);
//On gère le scrolling (fonction ci-dessous)
centerScrolling(map);
}
//Gestion de la mort :
//Si timerMort est différent de 0, c'est qu'il faut réinitialiser le joueur.
//On ignore alors ce qui précède et on joue cette boucle (un wait en fait) jusqu'à ce que
// timerMort == 1. A ce moment-là, on le décrémente encore -> il vaut 0 et on réinitialise
//le jeu avec notre bonne vieille fonction d'initialisation ;) !
if (timerMort > 0)
{
timerMort--;
if (timerMort == 0)
{
// Si on est mort, on réinitialise le niveau
map.changeLevel();
initialize(map);
}
}
}
|
Concrètement, voilà ce qui a changé :
Fichier : player.h : Modifier le code :
|
//Legends of Meruvia - C++ / SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#ifndef PLAYER_H
#define PLAYER_H
#include <SFML/Graphics.hpp>
#include <iostream>
class Map;
class Input;
class Sounds;
class Magic;
class Menus;
class Player
{
public:
//Structures
struct POINT { int x, y; };
//Constructeur
Player();
//Accesseurs
int getX(void) const;
int getY(void) const;
int getW(void) const;
int getH(void) const;
float getDirX(void) const;
float getDirY(void) const;
int getOnGround(void) const;
int getLife(void) const;
int getGold(void) const;
int getDirection(void) const;
int getMagic(void) const;
int getNombreExplosions(void) const;
float getMP(void) const;
float getMPmax(void) const;
//Mutateurs
void setX(int valeur);
void setY(int valeur);
void setW(int valeur);
void setH(int valeur);
void setDirX(float valeur);
void setDirY(float valeur);
void setOnGround(bool valeur);
void setTimerMort(int valeur);
void setGold(int valeur);
void setCheckpoint(bool valeur);
void setMagic(int valeur);
void setNombreExplosions(int valeur);
//Fonctions
void initialize(Map &map);
void reinitialize(Map &map);
void draw(Map &map, sf::RenderWindow &window);
void update(Input &input, Map &map, Magic magic[], Menus &menus);
void centerScrolling(Map &map);
void mapCollision(Map &map);
void drawSword(Map &map, sf::RenderWindow &window);
void killPlayer(Sounds &sounds);
void playerHurts(Sounds &sounds);
bool getCollisionWithSword(int Ax, int Ay, int Aw, int Ah);
private:
//Variables de la classe en accès privé
// Points de vie/santé + chrono d'invicibilité
int life, invincibleTimer;
//Magie
float MP, regainTime;
int MPmax;
int gold;
// Coordonnées du sprite
int x, y;
// Largeur, hauteur du sprite
int h, w;
// Checkpoint pour le héros (actif ou non)
bool checkpointActif;
// + coordonnées de respawn (réapparition)
int respawnX, respawnY;
// Variables utiles pour l'animation :
// Numéro de la frame (= image) en cours + timer
int frameNumber, frameTimer, frameMax;
// Nombre max de frames, état du sprite et direction
// dans laquelle il se déplace (gauche / droite)
int etat, direction;
int isrunning;
int isAttacking;
// Variables utiles pour la gestion des collisions :
//Est-il sur le sol, chrono une fois mort
int timerMort;
//Vecteurs de déplacement temporaires avant détection
//des collisions avec la map
float dirX, dirY;
//Sauvegarde des coordonnées de départ
int saveX, saveY;
//Spritesheet du héros
sf::Texture heroTexture;
sf::Sprite hero;
sf::Texture swordTexture;
sf::Sprite sword;
//Gestion de l'épée
int swordX, swordY;
int swordTimer;
int swordRotation;
//Gestion de la magie (boules de feu)
int magicNumber;
//Nombre d'explosions à l'écran
int nombreExplosions;
//Numéro de la warp spéciale empruntée
int numberSPE;
/******************/
/* Constantes */
/******************/
/* Taille maxi de la map : 400 x 150 tiles */
const int MAX_MAP_X = 400;
const int MAX_MAP_Y = 150;
/* Taille d'une tile (32 x 32 pixels) */
const int TILE_SIZE = 32;
/* Constantes pour l'animation */
const int TIME_BETWEEN_2_FRAMES_PLAYER = 3;
const float TIME_BETWEEN_2_FRAMES_SWORD = 1;
/* Taille du sprite de notre héros (largeur = width et hauteur = heigth) */
const int PLAYER_WIDTH = 40;
const int PLAYER_HEIGTH = 48;
//Vitesse de déplacement en pixels du sprite
const int PLAYER_SPEED = 3;
//Valeurs attribuées aux états/directions
const int IDLE = 0;
const int WALK = 1;
const int DEAD = 4;
const int DOWN = 0;
const int UP = 1;
const int RIGHT = 2;
const int LEFT = 3;
// Taille de la fenêtre : 800x480 pixels
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 480;
//Constantes pour les limites de la caméra avant scrolling
const int LIMITE_X = 400;
const int LIMITE_Y = 220;
const int LIMITE_W = 100;
const int LIMITE_H = 80;
//Enum pour les boutons
const enum{ up, down, right, left, attack, run, enter, magie };
//Nombre max de levels
const int LEVEL_MAX = 2;
//Une enum pour la gestion du menu.
const enum { START, PAUSE };
//Nombre max de shurikens à l'écran
const int MAGIC_MAX = 6;
/*************************/
/* VALEURS DES TILES */
/************************/
const int MUR = 1;
const int SPE1 = 10;
const int SPE2 = 11;
const int SPE3 = 12;
const int SPE4 = 13;
const int SPE5 = 14;
const int SPE6 = 15;
const int SPE7 = 16;
const int SPE8 = 17;
const int SPE9 = 18;
const int SPE10 = 19;
};
#endif
|

@ bientôt pour le chapitre 18 ! ![]()
Jay

English
Français 