Big Tuto SFML 2 : Rabidja v. 3.0
Chapitre 4 : Avec un background, c'est mieux !
Tutoriel présenté par : Jérémie F. Bellanger (Jay81)
Date d'écriture : 13 février 2015
Date de révision : 19 mars 2016
Prologue
Eh, voilà ! Quelle magnificence ! Quelle fenêtre ! Mes aïeux !
Que... quoi ?! Vous trouvez que le monochrome noir, c'est moche ! Mince alors ! Moi, qui espérais m'arrêter ici !
Non, je plaisante ! Bien sûr qu'on va la remplir notre bonne vieille fenêtre ! Et pour vous montrer ma détermination, on va tout de suite se lancer dans l'affichage du background !
Mais c'est quoi le background ?
Non, ne me dites pas que vous êtes nul en anglais, à ce point là !?! Ah, ça me rassure ! Eh bien ça va tout simplement être le décor de fond de notre map, qui va rester statique.
Pour cela, il va donc nous falloir apprendre à charger, puis décharger une image à partir d'un fichier, et à l'afficher ! Non, ça ne va pas être bien dur.
Alors, on y va ! Banzaï !
Quoi ? Stop ?
Ah oui, j'allais oublier ! Comment peut-on afficher un background si on n'en a pas ?
Deux solutions s'offrent à vous : soit vous dessinez le vôtre (format 800 x 480 pixels, la taille de notre fenêtre), soit vous prenez celui-là et vous le copiez dans le répertoire de votre projet dans le dossier graphics, sous le nom background.png (c'est important de respecter ce nom pour pouvoir le charger dans notre programme ensuite):
background.png (faites en clic droit pour sauvegarder l'image )
Mais, il est plus grand que 800 x 480, ce background ?!?
Eh oui, mon cher Watson ! En effet, il est 2 fois plus long, car il peut aussi se mettre en boucle et défiler en parallaxe avec la map pour donner une impression de profondeur, fort sympathique !
Mais, on verra tout ça plus loin. Pour l'instant, on va se contenter de l'afficher tel quel, et on n'en verra donc que la moitié (mais est-ce la meilleure moitié ? - Bon, faut arrêter de se poser des questions là ! )
Le code
Nous allons commencer par créer une nouvelle classe Map qui s'occupera d'afficher... notre map ! Et donc aussi, son background.
Mais c'est quoi une map ?
Cela veut dire carte, en anglais, et cela représentera ici nos niveaux, car comme sur une carte, nous aurons différents éléments placés à diverses coordonnées bien précises.
Faites donc un clic droit sur le nom de votre projet -> Ajouter -> classe et on est parti ! On commence par le header, cette fois :
Fichier : map.h
//Rabidja 3 - nouvelle version convertie en SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#ifndef MAP_H
#define MAP_H
#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
class Map
{
public:
//Constructeur
Map();
//Fonctions
void drawBackground(sf::RenderWindow &window);
private:
//Variables de la classe en accès privé
//Background
sf::Texture backgroundTexture;
sf::Sprite background;
};
#endif
|
Bon, alors, comme vous le voyez, notre classe est encore embryonnaire (elle va bien se complexifier par la suite, croyez-moi ! ).
On inclue d'abord les libs dont nous allons avoir besoin. Je les ai toutes ajoutées dès maintenant, même si certaines d'entre elles ne nous seront utiles que plus tard. Mais comme ça, ce sera fait !
On a ensuite simplement notre constructeur, et notre fonction de dessin du background, ainsi que les variables nécessaires à la SFML pour stocker le fichier image.
Notez que la SFML a besoin de 2 variables : une texture qui contient en mémoire le fichier image et un sprite qui pointe en fait sur la texture (tout en offrant la possibilité de la découper, de faire des rotations, des zooms, etc.).
Passons maintenant au code des fonctions dans le fichier map.cpp :
Fichier : map.cpp
//Rabidja 3 - nouvelle version intégralement en SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
#include "map.h"
using namespace std;
using namespace sf;
//Constructeur
Map::Map()
{
//Chargement des ressources graphiques
//Chargement du background
if (!backgroundTexture.loadFromFile("graphics/background.png"))
{
// Erreur
cout << "Erreur durant le chargement de l'image de background." << endl;
}
else
background.setTexture(backgroundTexture);
}
//Fonctions
void Map::drawBackground(RenderWindow &window)
{
window.draw(background);
}
|
Voilà, le code n'est pas bien compliqué.
Le constructeur charge le fichier background au sein de la classe. Comme la SFML gère elle-même la mémoire, on a juste besoin de charger les images, elle les déchargera automatiquement quand la classe sera détruite, soit en quittant le jeu.
Notez ainsi qu'on ne peut pas charger une texture dans une fonction externe comme en SDL2, sans quoi, la texture chargée serait détruite à la fin de la fonction et notre sprite afficherait donc un carré blanc. C'est une erreur courante. Mais si on respecte une architecture classique en POO et qu'on charge les ressources nécessaires au sein de la classe correspondante, on ne risque pas ce genre de problème.
La fonction d'affichage du background, quant à elle, ne pourrait pas être plus simple !
Tile, sprite ? Kézako ?
En général, un sprite est un élément mobile du jeu qui interagit avec d'autres sprites (par exemple : le héros, les monstres, les power-ups, etc.). Au contraire, une tile est un élément statique du décor représentant une petite partie du niveau (nos tiles feront par exemple 32x32 pixels, ce qui est une taille standard dans l'industrie du jeu vidéo ). Pour plus d'infos sur le tilemapping, je vous invite à lire cet autre tuto.
Reprenons désormais notre fichier main.h.
Pour que le main() reconnaisse notre nouvelle classe Map, il faut simplement lui ajouter #include "map.h", comme on peut le voir ci-dessous :
Fichier : main.h
//Rabidja 3 - nouvelle version convertie en 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"
using namespace std;
using namespace sf;
// Taille de la fenêtre : 800x480 pixels
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 480;
|
Bien, revenons maintenant à notre main().
On va y rajouter 2 choses :
- on va instancier notre nouvelle classe Map au début,
- puis, dans la boucle principale, on va rajouter un appel à notre fonction de dessin du background, pour l'afficher :
Fichier : main.cpp
//Rabidja 3 - nouvelle version convertie en SFML 2
//Copyright / Droits d'auteur : www.meruvia.fr - Jérémie F. Bellanger
//Big Tuto C++/SFML 2.2 - Février 2015 - Mise à jour 1.2
#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),
"Rabidja 3.0 - Chapitre 4 : Background - Big Tuto SFML2 - www.meruvia.fr");
//Limite les fps à 60 images / seconde
window.setFramerateLimit(60);
//On active la synchro verticale
window.setVerticalSyncEnabled(true);
//Instanciation des classes
Input input;
Map map;
// Boucle infinie, principale, du jeu
while (window.isOpen())
{
/** GESTION DES INPUTS (CLAVIER, JOYSTICK) **/
input.gestionInputs(window);
/** DESSIN - DRAW **/
//On dessine tout
window.clear();
//On affiche le background
map.drawBackground(window);
window.display();
}
// On quitte
return 0;
}
|
Vous noterez au passage que map.drawBackground() a besoin de la fenêtre (window), passée en référence, pour pouvoir y dessiner.
Et voilà, c'est fini !
Compilez désormais le programme puis lancez-le et TADAAA !
Notre magnifique background s'affiche dans toute l'immensité de sa beauté ! (J'exagère à peine ! )
@ bientôt pour le chapitre 5 !
Jay