Big Tuto SFML 2 / Action-RPG : Legends of Meruvia

Chapitre 3 : Ouvrons notre première fenêtre !

 

Tutoriel présenté par : Jérémie F. Bellanger (Jay81)
Date d'écriture : 29 novembre 2015
Date de révision : 25 février 2017

      Prologue

   Avant de commencer, je tiens à vous expliquer, si vous avez déjà suivi le Big Tuto C++/SFML : Rabidja, que celui-ci repart de son code source final, avant d'y ajouter ce qui sera nécessaire à notre Action-RPG et d'en retirer ce qui sera superflu. wink Le code source va donc être très ressemblant, par moments, et les premiers chapitres seront parfois, presque des copier/coller. Même si ce n'est pas très utile (et que ça remplit la base de données du site ! laugh), j'ai préféré le faire, afin que le cheminement du tuto soit le plus clair possible et que l'on puisse démarrer directement par ce tuto, sans avoir lu les précédents. cheeky

   Allez, on va enfin rentrer dans le vif du sujet ! Notre but va d'abord être d'ouvrir une fenêtre, pour notre jeu. Or on peut ouvrir une fenêtre avec un simple main() comprenant tout le code (comme on vient de le faire pour tester la bonne configuration de la SFML wink), mais comme notre but, à terme, n'est pas simplement de s'amuser à ouvrir des fenêtres (Ah bon ?! ), nous allons déjà mettre en forme l'architecture de notre programme pour qu'il soit plus clair et donc plus facilement modifiable après !


    On va donc y aller progressivement ensemble. Pour chaque partie du code, je vais vous donner le nom de la page à créer ou à modifier (en haut en gras). Ensuite je vous donnerai le code commenté, puis une explication, plus ou moins longue selon le besoin.

 

 

 Reprenons donc d'abord notre fichier main.cpp et copions-y le code suivant (sans oublier de supprimer le code de démo précédent, si ce n'est pas déjà fait cheeky !) :

 

Nom du fichier : main.cpp

//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 3 - www.meruvia.fr");
 
//On active la synchro verticale
window.setVerticalSyncEnabled(true);
 
//Instanciation des classes
Input input;
 
// Boucle infinie, principale, du jeu
while (window.isOpen())
{
 
// Gestion des inputs
input.gestionInputs(window);
 
window.display();
}
 
// On quitte
return 0;
}

 

    Comme vous pouvez le voir, pour l'instant, notre main() est très minimaliste , mais c'est normal, puisqu'on veut simplement ouvrir une fenêtre !

    Cependant, il contient déjà l'architecture de base de notre jeu. En effet, d'abord on appelle la SFML 2 pour créer notre fenêtre et lui donner un titre et ensuite on active la synchro verticale, pour éviter des saccades de l'écran, quand on fera défiler nos niveaux à fond la caisse ! laugh

    Ensuite, on instancie notre classe Input, que nous allons définir juste après, et qui servira à gérer les inputs (= entrées) du clavier, et plus tard du joystick.

    Après cette courte phase d'initialisation, on passe alors dans la boucle principale du jeu (while). Pour l'instant, on n'y fait pas grand chose. On teste l'état des inputs (donc du clavier) pour pouvoir quitter le programme, le cas échéant, puis on affiche notre fenêtre. cheeky

    Voilà, il n'y a pas grand chose à dire de plus, c'est vraiment très basique, et ça ne devrait pas vous poser trop de problème normalement .

    Passons maintenant au fichier d'en-tête (header) de notre fonction main().

 
Nom du fichier : main.h
//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"
 
using namespace std;
using namespace sf;
 
 
// Taille de la fenêtre : 800x480 pixels
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 480;
 

    Rien que du très classique ici : on inclut d'abord les libs dont on va avoir besoin par la suite (sans oublier la SFML, of course ! laugh).

    Puis, on indique les namespaces que l'on va utiliser pour éviter de rajouter std:: et sf:: partout (même si ça peut faire joli ! indecision).

    Et enfin, on définit la taille de notre fenêtre à l'aide de 2 constantes pour la largeur (SCREEN_WIDTH) et la hauteur (SCREEN_HEIGHT). Vous aurez d'ailleurs remarqué qu'on s'est déjà servi de ces deux constantes dans la fonction d'ouverture de notre fenêtre. wink

   Passons maintenant au fichier input.cpp, qui contiendra notre nouvelle classe Input dont le but sera de détecter les entrées du clavier (puis plus tard du joystick wink).

 
Nom du fichier : input.cpp
//Legends of Meruvia - C++ / SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
 
#include "input.h"
 
using namespace std;
using namespace sf;
 
//Constructeur
Input::Input()
{
button.left = button.right = button.up = button.down = button.run =
button.attack = button.enter = button.magie = false;
}
 
 
//Accesseur
Input::Button Input::getButton(void) const { return button; }
 
 
//Mutateur
void Input::setButton(int bouton, bool etat)
{
switch (bouton)
{
case up:
button.up = etat;
break;
 
case down:
button.down = etat;
break;
 
case right:
button.right = etat;
break;
 
case left:
button.left = etat;
break;
 
case attack:
button.attack = etat;
break;
 
case run:
button.run = etat;
break;
 
case magic:
button.magie = etat;
break;
 
case enter:
button.enter = etat;
break;
}
}
 
 
//Fonctions
void Input::gestionInputs(RenderWindow &window)
{
//Pour l'instant, on ne gère que le clavier.
//On gèrera les joysticks plus tard, s'il y en a
//un de branché.
//Pour l'instant, cette fonction n'est donc pas indispensable.
getInput(window);
}
 
 
void Input::getInput(RenderWindow &window)
{
 
// Tant qu'il y a des évènements à traiter...
while (window.pollEvent(event))
{
// on regarde le type de l'évènement...
switch (event.type)
{
// On ferme la fenêtre
case Event::Closed:
window.close();
break;
 
// Touche pressée
case Event::KeyPressed:
switch (event.key.code) // La touche qui a été pressée
{
case Keyboard::Escape: // Echap
window.close();
break;
 
case Keyboard::X:
button.run = true;
break;
 
case Keyboard::C:
button.magie = true;
break;
 
case Keyboard::V:
button.attack = true;
break;
 
case Keyboard::Left:
button.left = true;
break;
 
case Keyboard::Right:
button.right = true;
break;
 
case Keyboard::Down:
button.down = true;
break;
 
case Keyboard::Up:
button.up = true;
break;
 
case Keyboard::Return:
button.enter = true;
break;
 
default:
break;
}
break;
 
// Touche relâchée
case Event::KeyReleased:
switch (event.key.code)
{
case Keyboard::X:
button.run = false;
break;
 
case Keyboard::C:
button.magie = false;
break;
 
case Keyboard::V:
button.attack = false;
break;
 
case Keyboard::Left:
button.left = false;
break;
 
case Keyboard::Right:
button.right = false;
break;
 
case Keyboard::Down:
button.down = false;
break;
 
case Keyboard::Up:
button.up = false;
break;
 
 
case Keyboard::Return:
button.enter = false;
break;
 
default:
break;
}
break;
 
// on ne traite pas les autres types d'évènements
default:
break;
}
}
}

    Commençons par le constructeur de la classe, qui se contente d'initialiser notre structure Button, qui contiendra simplement un booléen pour chaque type d'entrée valide (right, left, enter, attack, magie, etc.) et qui nous dira donc si le bouton correspondant a été pressé ou non. Nous déclarerons cette structure et la variable correspondante dans notre header ci-dessous.

    Vient ensuite un bête accesseur, qui renvoie la struct button puis un mutateur qui nous permettra de changer la valeur (true ou false) de chaque entrée de notre structure, en-dehors de la classe Inputwink

    Vous remarquerez ensuite 2 fonctions : la première - gestionInputs() - renvoie pour l'instant simplement à la deuxième, mais elle va se complexifier plus tard, quand nous rajouterons les joysticks (sinon, elle serait inutile ! cheeky).

 

   La seconde - getInput() - est assez longue mais néanmoins très simple : elle enregistre tous les events (événements), c'est-à-dire ici les entrées clavier (on verra plus tard comment rajouter d'autres events pour le joystick). Ensuite, elle traite ces événements dans une boucle (while) jusqu'à ce qu'il n'y en ait plus. Là, il y a 3 grands cas traités dans un switch : ou on veut quitter en cliquant sur la croix, ou on appuie sur une touche, ou on la relâche. Si on appuie ou on relâche une touche, on met la valeur correspondante de notre structure bouton à true ou à false, selon qu'elle est pressée ou pas.


    Ainsi, par exemple, tant que la touche C sera enfoncée, button.jump vaudra true et quand on la relâchera, elle vaudra false. L'utilisation qu'on en fera se trouvera plus tard dans la classe Player qui s'occupera de déplacer notre héros en fonction des touches du clavier (notamment). wink

   Passons maintenant au fichier d'en-tête input.h :


Nom du fichier : input.h
//Legends of Meruvia - C++ / SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#ifndef INPUT_H
#define INPUT_H
 
#include <SFML/Graphics.hpp>
 
 
class Input
{
//Structures
struct Button { bool left, right, up, down, attack, run, enter, magie; };
 
public:
 
//Constructeur
Input();
 
//Accesseur
Button getButton(void) const;
 
//Mutateur
void setButton(int bouton, bool etat);
 
//Fonctions
void gestionInputs(sf::RenderWindow &window);
void getInput(sf::RenderWindow &window);
 
 
private:
 
//Variables de la classe en accès privé
sf::Event event;
Button button;
 
//Enum pour les boutons
enum { up, down, right, left, attack, run, enter, magic };
};
#endif
   

    Et voilà, on déclare ici notre classe Input : on crée notre struct Button, puis on indique les prototypes de notre constructeur, de nos accesseurs / mutateurs et de nos deux fonctions.

    Ensuite, en privé (les variables ne seront donc accessibles que depuis l'intérieur de la classe, sauf en passant par un accesseur / mutateur), on initialise une variable SFML event pour stocker les inputs et une structure button.

    Enfin, pour pouvoir retrouver plus facilement nos boutons à l'aide de noms explicites (dans le switch), on crée une enumwink

    Et voilà, on a maintenant l'architecture de base de notre jeu !!! Il ne reste plus qu'à compiler, et Tadaaaaam ! On a notre magnifique fenêtre noire !!! angel

 


    Ouah ! Le magnifique monochrome noir ! J'ai bien fait de me mettre à la programmation, moi ! laugh 
Mais non, rassurez-vous, ça ne fait que commencer !!!  cheeky

 
 

Connexion

CoalaWeb Traffic

Today193
Yesterday178
This week693
This month4367
Total1743574

25/04/24