Big Tuto SFML 2 : Rabidja v. 3.0

Annexe 3 : Gestion des tiles lumières !

Tutoriel présenté par : Skrool
Relecture et corrections : Jérémie F. Bellanger (Jay81)

Date d'écriture : 5 avril 2015
Date de révision : 20 mars 2016

      Introduction

   Maintenant que nous avons créé nos lumières, il va être temps de raccorder notre système avec nos tiles, comme on a fait avec les tiles d'obscurité ! angel

   On est reparti ! wink

 

      Ajoutons nos tiles lumières

   Tout d'abord, mettons à jour nos constantes dans map.h :

Fichier : map.h, rajouter :

//Tiles pour les lumières
const int TILE_LUMIERE_DEBUT = 141;
const int TILE_LUMIERE_FIN = 148;
const int TILE_LUMIERE_OMNIDIRECTIONNELLE = 141;
const int TILE_LUMIERE_PLONGEANTE_GAUCHE = 142;
const int TILE_LUMIERE_PLONGEANTE_BAS = 143;
const int TILE_LUMIERE_PLONGEANTE_DROITE = 144;
const int TILE_LUMIERE_PLONGEANTE_MOUVANTE = 145;
const int TILE_LUMIERE_DOUCHE_BAS = 146;
const int TILE_LUMIERE_DOUCHE_HAUT = 147;
const int TILE_LUMIERE_TOURNANTE = 148;
 
   Avec ça, on en aura de la lumière ! laugh
   Ah, et tiens, tant qu'on est dans ce fichier, on va aussi créer une fonction surchargée de Map::setTile(), car on aura bientôt besoin de pouvoir modifier la valeur d'une tile de la map sur les 3 couches (et pas seulement la première). wink
   L'avantage avec la surcharge, c'est que nos 2 fonctions portent le même nom et le programme choisira la bonne en fonction des arguments envoyés. cheeky
   Gardez donc bien les 2 prototypes, surtout ! surprise
 

Fichier : map.h, rajouter la fonction surchargée setTile() :

//Mutateurs
void setLevel(int valeur);
void setStartX(int valeur);
void setStartY(int valeur);
void setTile(int y, int x, int valeur);
 
//Rajouter la ligne ci-dessous :
void setTile(int y, int x, int valeur, int couche);
 
void setNombreMonstres(int valeur);
void setNombrePlateformes(int valeur);

   Voilà, et donc forcément, il va nous falloir rajouter le nouveau mutateur dans map.cpp wink :

Fichier : map.cpp : Rajouter :

void Map::setTile(int y, int x, int valeur, int couche)
{
if (couche == 1)
tile[y][x] = valeur;
else if (couche == 2)
tile2[y][x] = valeur;
else if (couche == 3)
tile3[y][x] = valeur;
}
 
   Ensuite, toujours dans le même fichier, nous mettons à jour notre fonction Map::draw().
   Là, c'est 3 fois, plus ou moins le même code qu'il va falloir mettre à jour pour chaque couche, en-dessous de la gestion des ombres. wink
   Je ne vous ai mis que le code à rajouter, en remplacement du code précédent qui effaçait simplement les tiles lumières. Si vous êtes un peu perdu dans tout ce code (le projet commence à bien prendre de l'ampleur cheeky), reportez-vous à l'archive téléchargeable. wink
 

Fichier : map.cpp : Modifier la fonction draw() :

// Couche 1
 
/* On teste si c'est une lumière*/
else if (tile[mapY][mapX] > TILE_LUMIERE_DEBUT - 1 && tile[mapY][mapX] < TILE_LUMIERE_FIN + 1)
{
 
if (tile[mapY][mapX] == TILE_LUMIERE_OMNIDIRECTIONNELLE)
manager.AddLight(15, sf::Color::White, 200, 250,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_GAUCHE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 120, 50, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 90, 50, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_DROITE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 50, 50, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_MOUVANTE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
2, 90, 50, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_DOUCHE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 90, 80, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_DOUCHE_HAUT)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 270, 80, *this, mapX, mapY, 1);
 
else if (tile[mapY][mapX] == TILE_LUMIERE_DOUCHE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
3, 90, 70, *this, mapX, mapY, 1);
 
//On remplace la tile par du vide
tile[mapY][mapX] = 0;
}
 
 
// Couche 2
 
/* On teste si c'est une lumière*/
else if (tile2[mapY][mapX] > TILE_LUMIERE_DEBUT - 1 && tile2[mapY][mapX] < TILE_LUMIERE_FIN + 1)
{
 
if (tile2[mapY][mapX] == TILE_LUMIERE_OMNIDIRECTIONNELLE)
manager.AddLight(15, sf::Color::White, 200, 250,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_GAUCHE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 120, 50, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 90, 50, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_DROITE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 50, 50, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_MOUVANTE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
2, 90, 50, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_DOUCHE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 90, 80, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_DOUCHE_HAUT)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 270, 80, *this, mapX, mapY, 2);
 
else if (tile2[mapY][mapX] == TILE_LUMIERE_DOUCHE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
3, 90, 70, *this, mapX, mapY, 2);
 
//On remplace la tile par du vide
tile2[mapY][mapX] = 0;
}
 
 
// Couche 3
 
/* On teste si c'est une lumière*/
else if (tile3[mapY][mapX] > TILE_LUMIERE_DEBUT - 1 && tile[mapY][mapX] < TILE_LUMIERE_FIN + 1)
{
 
if (tile3[mapY][mapX] == TILE_LUMIERE_OMNIDIRECTIONNELLE)
manager.AddLight(15, sf::Color::White, 200, 250,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_GAUCHE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 120, 50, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 90, 50, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_DROITE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 50, 50, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_PLONGEANTE_MOUVANTE)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
2, 90, 50, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_DOUCHE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 90, 80, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_DOUCHE_HAUT)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
1, 270, 80, *this, mapX, mapY, 3);
 
else if (tile3[mapY][mapX] == TILE_LUMIERE_DOUCHE_BAS)
manager.AddDirectionalLight(sf::Color::White, 200, 200,
sf::Vector2f(mapX*TILE_SIZE + TILE_SIZE / 2, mapY*TILE_SIZE + TILE_SIZE / 2),
3, 90, 70, *this, mapX, mapY, 3);
 
//On remplace la tile par du vide
tile3[mapY][mapX] = 0;
}
 
   On remplace donc nos tiles de lumière par de vraies lumières. wink
   Chaque lumière a ses paramètres propres et vous noterez qu'on envoie en arguments la position de la tile source ainsi que sa couche, pour pouvoir la recopier ensuite.
   Dans Light::update, maintenant, on va s'occuper de décharger les lumières qui sortent de l'écran en utilisant ces arguments pour recopier la tile source au bon endroit et sur la bonne couche. Comme ça, on économisera de la mémoire, et en plus, cela permettra d'afficher bien plus de lumières par niveau ! angel
 

Fichier : light.cpp : Remplacer le code précédent par :

void Light::update(Map &map)
{
// On rajoute une partie de la différence entre les valeurs r, g et b des
//deux variables pour avoir un effet de transition en douceur
if (m_shadowColor.r < m_targetShadowColor.r)
m_shadowColor.r++;
else if (m_shadowColor.r > m_targetShadowColor.r)
m_shadowColor.r--;
 
if (m_shadowColor.g < m_targetShadowColor.g)
m_shadowColor.g++;
else if (m_shadowColor.g > m_targetShadowColor.g)
m_shadowColor.g--;
 
if (m_shadowColor.b < m_targetShadowColor.b)
m_shadowColor.b++;
else if (m_shadowColor.b > m_targetShadowColor.b)
m_shadowColor.b--;
 
// Si le timer est arrivé à 0, on met la variable timerOk à true.
bool timerOk = decrementeTimer();
 
//On boucle sur toutes les lumières
for (int i = 0; i<m_light.size(); i++)
{
//On met à jour les coordonnées m_position de la lumière par rapport à
//sa position sur la carte, et à map.startX et startY
m_light[i].move(sf::Vector2f((m_light[i].getAbsolutePosition().x
- m_light[i].getPosition().x) - map.getStartX(),
(m_light[i].getAbsolutePosition().y - m_light[i].getPosition().y)
- map.getStartY()));
 
// Si la lumière est hors de l'écran, on détruit et on replace la tile
//source par la tile correspondante
if (m_light[i].getPosition().x + m_light[i].GetRadius() < 0 ||
m_light[i].getPosition().x - m_light[i].GetRadius() > 800 ||
m_light[i].getPosition().y + m_light[i].GetRadius() < 0 ||
m_light[i].getPosition().y - m_light[i].GetRadius() > 600)
{
//Si les coordonnées de la tile sont pas 0,0 ( = ne provient pas d'une tile)
//on remplace la tile par la tile de lumière correspondant
if (m_light[i].getSourceX() != 0 || m_light[i].getSourceY() != 0)
{
map.setTile(m_light[i].getSourceY(), m_light[i].getSourceX(),
m_light[i].getSourceID(), m_light[i].getCouche());
}
m_light[i].clear();
m_light.erase(m_light.begin() + i);
 
//et on baisse i de 1, sinon gare aux erreurs d'allocation
if (i >0) i--;
else break;
}
 
if (timerOk) //Si le timer s'est écoulé on met à jour la lumière
m_light[i].update(map);
}
 
}

 

   Et voilà ! angel
   Maintenant, vous aurez sans doute remarqué qu'on a rajouté la gestion de la couche (ou layer) de la map pour nos tiles. Il va donc nous falloir faire quelques modifications pour que le reste du jeu la prenne aussi en charge.
   Commençons d'abord par créer une nouvelle variable m_couche pour la stocker dans lightEntity.h :
 
Fichier : lightEntity.h : Faire les modifications nécessaires :
//Tile source, pour replacer la tile de lumière à sa place quand
//elle sortira de l'écran pour économiser du CPU
int m_sourceX, m_sourceY, m_sourceID, m_couche;

 

   Voilà, maintenant, il va nous falloir modifier les prototypes et fonctions de AddLight() et AddDirectionalLight() dans light.cpp / light.h pour prendre la couche en argument.
   Idem pour create() et createDirectionalLight() dans lightEntity.cpp / lightEntity.h :
 

Fichier : light.h : Faire les modifications nécessaires :

//Ajout de lumière
 
void AddLight(int quality, sf::Color color, float radius, float intensity,
sf::Vector2f position, int type, Map &map, int sourceX, int sourceY, int couche);
 
void AddDirectionalLight(sf::Color color, float radius, float intensity, sf::Vector2f position,
int type, float angle, float o_angle, Map &map, int sourceX, int sourceY, int couche);

 

Fichier : light.cpp : Faire les modifications nécessaires :

void Light::AddLight(int quality, sf::Color color, float radius, float intensity,
sf::Vector2f position, int type, Map &map, int sourceX, int sourceY, int couche)
{
if (m_light.size() < MAX_LIGHT)
{
m_light.push_back(lightEntity());
m_light.back().create(quality, color, radius, intensity, position, type,
map, sourceX, sourceY, couche);
}
}
 
 
void Light::AddDirectionalLight(sf::Color color, float radius, float intensity,
sf::Vector2f position, int type, float angle, float o_angle, Map &map, int sourceX,
int sourceY, int couche)
{
if (m_light.size() < MAX_LIGHT)
{
m_light.push_back(lightEntity());
m_light.back().createDirectionalLight(color, radius, intensity, position,
type, angle, o_angle, map, sourceX, sourceY, couche);
}
 
}

 

Fichier : lightEntity.h : Faire les modifications nécessaires :

//Création d'une lumière omnidirectionnelle
void create(int quality, sf::Color color, float radius, float intensity, sf::Vector2f position,
int type, Map &map, int sourceX, int sourceY, int couche);
 
//Création d'une lumière directionnelle
void createDirectionalLight(sf::Color color, float radius, float intensity, sf::Vector2f position,
int type, float angle, float o_angle, Map &map, int sourceX, int sourceY, int couche);

 

Fichier : lightEntity.cpp : Faire les modifications nécessaires :

void lightEntity::create(int quality, sf::Color color, float radius, float intensity,
sf::Vector2f position, int type, Map &map, int sourceX, int sourceY, int couche)
{
//Initialisation de variables
m_quality = quality;
m_color = color;
m_radius = radius;
m_intensity = intensity;
m_absoluteX = (int)position.x;
m_absoluteY = (int)position.y;
m_position = position; // Par défaut. Sera modifié au prochain update
m_type = type;
 
//Récupération des données de tiles
m_sourceX = sourceX;
m_sourceY = sourceY;
m_couche = couche;
 
m_sourceID = map.getTile(sourceY, sourceX);
 
m_directionnal = false;
 
Generate(map);
}
 
 
void lightEntity::createDirectionalLight(sf::Color color, float radius, float intensity,
sf::Vector2f position, int type, float angle, float o_angle, Map &map, int sourceX,
int sourceY, int couche)
{
//Initialisation de variables
m_color = color;
m_radius = radius;
m_intensity = intensity;
m_type = type;
m_angle = angle;
m_opening_angle = o_angle;
 
m_absoluteX = (int)position.x;
m_absoluteY = (int)position.y;
m_position = position; // Par défaut. Sera modifié au prochain update
 
//Récupération des données de tiles
m_sourceX = sourceX;
m_sourceY = sourceY;
m_couche = couche;
 
m_sourceID = map.getTile(sourceY, sourceX);
 
m_directionnal = true;
 
Generate(map);
}

   Et voilà pour les couches ! angel

   Par contre, comme la map se recharge à chaque mort, il faut aussi nettoyer les lumières, donc dans la fonction initialize() de player.cpp, on rajoute tout à la fin :

Fichier : player.cpp, rajouter :

//On réinitialise les lumières
manager.clear();
manager.setTargetShadowColor(sf::Color::White);

   On compile, et ... MAGNIFIQUE !! cool Cela marche ! angel

   Ou pas... frown

Note de Jay : Pour ma part, j'ai eu ici un problème avec Visual Studio 2013, alors que Skrool n'avait aucun souci avec Xcode sur Mac !
Bon, je laisse la guerre des Trolls Windows vs Mac pour d'autres sites, plus spécialisés là-dedans. wink Et je vais simplement essayer de vous expliquer comment j'ai résolu le problème. 
Si, maintenant, tout roule pour vous, vous pouvez passer ce qui suit ! wink

   Voilà, donc comme je le disais, je compilais vaillamment sur Visual Studio, quand mon compilo m'a craché à la figure l'erreur suivante :

error C2582: 'operator =' fonction non disponible dans 'lightEntity'

   D'abord dubitatif, je me suis dit : "Allons, bon, on recompile tout à zéro, et ça devrait lui passer !" indecision Mais, non ! surprise

   Alors, j'ai cherché 5 minutes sur internet, et j'ai vu que le compilo n'était pas content car il ne trouvait pas de constructeur de copie par opération d'affectation (=) valide. 

   OK, c'est vrai que j'en ai pas écrit, mais normalement, il devrait pouvoir en faire un bateau, tout seul comme un grand, non ?! angry

   Eh ben, non (sans que je sache pourquoi Xcode y arrive, lui !).

   De plus, pourquoi a-t-il besoin d'un tel constructeur, qui pour ceux qui n'auraient pas suivi, sert simplement à copier un objet dans un autre, en faisant Objet1 = Objet2; ?

   Et bien, en cherchant un peu dans la lib standard, il semblerait que cela vienne de nos tableaux dynamiques. En effet, quand on supprime un objet du tableau, les autres sont déplacés à l'aide d'une fonction move(), qui fait ni plus ni moins que la même chose que moi dans mes tableaux statiques. Elle copie donc des objets du tableau à la place des éléments supprimés.

   Or, c'est ici que ça coince, puisque VS ne sait pas comment faire lightEntity1 = lightEntity2;, par exemple.

   Soit, s'il n'y a que ça ! Créons un constructeur par opérateur d'affectation, dans le fichier lightEntity.cpp :

Fichier : lightEntity.cpp, rajouter :

// Constructeur par opérateur d'affectation =
lightEntity& lightEntity::operator=(const lightEntity& source)
{
// On copie les variables d'un objet à l'autre
m_quality = source.GetQuality();
m_color = source.GetColor();
m_radius = source.GetRadius();
m_intensity = source.GetIntensity();
m_absoluteX = source.getAbsolutePosition().x;
m_absoluteY = source.getAbsolutePosition().y;
m_position = source.getPosition();
m_type = source.getType();
m_sourceX = source.getSourceX();
m_sourceY = source.getSourceY();
m_couche = source.getCouche();
m_sourceID = source.getSourceID();
m_directionnal = source.getDirectionnal();
m_angle = source.getAngle();
m_opening_angle = source.getO_Angle();
m_timer = source.getTimer();
m_targetIntensity = source.getTargetIntensity();
m_triangle = source.getTriangle();
 
return *this;
}
 
   Comme vous pouvez le voir, c'est très simple en fait.
   Cela ressemble beaucoup à nos fonctions copy() précédentes. wink
   Par contre, il va nous manquer des accesseurs, à ce train-là ! surprise
   Rajoutons-les donc :

Fichier : lightEntity.cpp, rajouter :

int lightEntity::getType(void) const { return m_type; }
int lightEntity::getDirectionnal(void) const { return m_directionnal; }
float lightEntity::getAngle(void) const { return m_angle; }
float lightEntity::getO_Angle(void) const { return m_opening_angle; }
int lightEntity::getTimer(void) const { return m_timer; }
int lightEntity::getCouche(void) const { return m_couche; }
float lightEntity::getTargetIntensity(void) const { return m_targetIntensity; }
std::vector <sf::VertexArray> lightEntity::getTriangle(void) const { return m_triangle; }

   Voilà, et n'oublions pas le header, à présent ! wink

Fichier : lightEntity.h, rajouter :

// Opérateur d'affectation
lightEntity& operator=(lightEntity const&);
 
 
// Et plus loin, nos nouveaux prototypes d'accesseurs :
int getType(void) const;
int getDirectionnal(void) const;
float getAngle(void) const;
float getO_Angle(void) const;
int getTimer(void) const;
int getCouche(void) const;
float getTargetIntensity(void) const;
std::vector <sf::VertexArray> getTriangle(void) const;

   Et voilà pour ce passage ! wink

   Normalement, Skrool avait prévu de ne faire qu'un chapitre des annexes 2, 3 et 4, mais je vais encore reporter la suite au chapitre suivant, car cela me semble déjà bien suffisant pour un chapitre. wink

   Au chapitre suivant, Skrool vous montrera comment améliorer ce système en rendant l'affichage des lumières plus doux, et en ajoutant un shader de blur (= flou en anglais). wink

   @ bientôt pour l'annexe 4 ! angel

                                          Skrool 

 

 
 
 
 

This site uses cookies to enable you to log in. We do not store or sell any personal data. By continuing to use this website, you agree to their use. Thanks!