-
Bonjour,
Je suis en train de faire une petite carte 2D (But final avoir une carte de 1000 * 1000 ... soit 1 000 000 de tuiles avec différents types de tuiles), je rencontre un soucis de taille, enfin c'est plutôt une question ...
Vaut il mieux utiliser un tableau dynamique ou un tableau statique sachant que la taille de ma carte est de base définie ? J'opterai pour un tableau statique.
J'ai actuellement fait le test avec un tableau dynamique et ne serai ce que pour afficher 100 tuiles, il faut 10 secondes environ alors que sans tableau j'en ai pour même pas une seconde ...
Voici les 2 codes :
Avec MAPSIZE = 10
Avec un tableau dynamique : (environ 10 secondes)
for(int x = 0; x < MAPSIZE; x++)
{
for(int y = 0; y < MAPSIZE; y++)
{
sizeVector = Tilemap.size();
Tilemap.push_back(tile);
Tilemap[sizeVector].addTile(x, y);
}
}
Sans le tableau : (Même pas une seconde)
for(int x = 0; x < MAPSIZE; x++)
{
for(int y = 0; y < MAPSIZE; y++)
{
tile.addTile(x, y);
}
}
Fonction addTile() :
void Tile::addTile(int posX, int posY)
{
vertex.position = sf::Vector2f(posX * TILESIZE, posY * TILESIZE);
vertex.texCoords = sf::Vector2f(128,0);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE + TILESIZE, posY * TILESIZE);
vertex.texCoords = sf::Vector2f(256,0);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE + TILESIZE, posY * TILESIZE + TILESIZE);
vertex.texCoords = sf::Vector2f(256,128);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE, posY * TILESIZE + TILESIZE);
vertex.texCoords = sf::Vector2f(128,128);
tiles.append(vertex);
}
Donc voilà, je pense que sans tableau on fait appel à draw une seule fois mais avec le tableau dynamique j'ai l'impression qu'on fait appel à draw à chaque tour de boucle. Est ce normal ? Et si non comment régler ce soucis ? :)
Merci d'avance
-
Salut
Ici c'est un forum concernant SFML, il y a d'autres endroits plus appropriés pour les questions de C++.
Merci.
-
En effet, j'ai trouvé réponse à ma question pour les tableaux, il fallait que j'utilise la fonction reserve pour réserver un espace mémoire pour mon tableau dynamique.
Maintenant j'ai une autre question, on est d'accord qu'à chaque tour de boucle mon code fait un nouvel appel à la fonction draw ?
Il devrait le faire qu'une fois puisque je charge toujours la même texture
-
Maintenant j'ai une autre question, on est d'accord qu'à chaque tour de boucle mon code fait un nouvel appel à la fonction draw ?
Aucune idée, il n'y a aucun appel à draw dans le code que tu as posté.
-
Dans la boucle principale :
window.clear(sf::Color(0, 0, 0, 0));
for (int i = 0; i < 100; i ++)
window.draw(map.getVector()[i]);
window.display();
La fonction getVector me permet de récupérer le tableau
const std::vector<Tile> &getVector(void) {return Tilemap;}
Et dans mon header de ma classe où se trouve ma boucle principale :
#ifndef SCREEN_MAP_H
#define SCREEN_MAP_H
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Screen.h"
#include "Map.h"
class Screen_Map : public Screen
{
public:
Screen_Map(void);
virtual int Run(sf::RenderWindow &window);
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
target.draw(map, states);
}
Map map;
};
#endif
-
Ok, tu as donc 100 appels à la fonction draw. Quelle est la question ?
-
Ma question est toute simple et j'imagine que la réponse aussi ...
J'aimerai faire un seul appel à draw et donc je cherche un moyen de le faire ;)
Car si je fais juste window.draw(map.getVector()) ça ne veut pas dessiner :/
-
Ton getvector() renvois quoi?
la texture de ton renderstate c'est quoi ?
pour dessiner une fois, tu dessines seulement ton vertexarray avec la bonne texture. regarde le tuto sur les vertexarray et les tilemap sur le site.
-
Je me permets de mettre en relief la partie importante de la réponse précédente :
regarde le tuto sur les vertexarray et les tilemap sur le site.
;)
-
Je n'utilise pas exactement le même code ...
J'ajoute une tuile comme ça :
#include "Tile.h"
#define TILESIZE 128
Tile::Tile()
{
if (!textureTileset.loadFromFile("Resources/Tileset.png"))
std::cout << "Error Loading" << std::endl;
tiles.setPrimitiveType(sf::Quads);
}
void Tile::addTile(int posX, int posY)
{
vertex.position = sf::Vector2f(posX * TILESIZE, posY * TILESIZE);
vertex.texCoords = sf::Vector2f(128,0);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE + TILESIZE, posY * TILESIZE);
vertex.texCoords = sf::Vector2f(256,0);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE + TILESIZE, posY * TILESIZE + TILESIZE);
vertex.texCoords = sf::Vector2f(256,128);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE, posY * TILESIZE + TILESIZE);
vertex.texCoords = sf::Vector2f(128,128);
tiles.append(vertex);
}
Mais si j'utilise un vector je peux pas afficher plus de 100 tuiles sans que ça prenne plus de 10 secondes :/ Pourtant j'utilise la fonction append pour rajouter des vertices à mon Vertex Array
-
Bah tu draw ta variable "tiles" qui semble être un vertexArray. ??? Et voilà un seul appel à draw.
Mais franchement les bouts de code que tu donnes, c'est n'importe quoi. On ne sait pas à quoi ça correspond, y'a pas tout, et on ne sait pas vraiment ce que tu veux.
Quand tu fais un vector, est-ce que tu charges la texture à chaque création d'une tile ?
-
@G. Désolé, je reconnais que c'est très incompréhensible ... Moi même je me perds, j'ai dû mal là ...
Je vais recommencer tout ça au propre.
-
Voilà je reviens avec un peu de propreté :
Ma classe Game où tout se passe :
#include "Game.h"
Game::Game()
{
sf::RenderWindow window(sf::VideoMode(WIDTH_WINDOW, HEIGHT_WINDOW), "[V0.01]Conquest of the World", sf::Style::Default);
window.setKeyRepeatEnabled(true);
window.setFramerateLimit(200);
Map map;
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
if ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape) )
{
window.close();
}
}
window.clear(sf::Color(0, 0, 255, 0));
window.draw(map);
window.display();
}
}
Son header :
#ifndef GAME_H
#define GAME_H
#include <cstdlib>
#include <time.h>
#include <SFML/Graphics.hpp>
#include "Map.h"
#define WIDTH_WINDOW 800
#define HEIGHT_WINDOW 450
class Game
{
public:
Game();
private:
};
#endif // GAME_H
Ma classe Tuile :
#include "Tile.h"
#define TILESIZE 128
Tile::Tile()
{
}
void Tile::addTile(int posX, int posY)
{
vertex.position = sf::Vector2f(posX * TILESIZE, posY * TILESIZE);
vertex.texCoords = sf::Vector2f(128,0);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE + TILESIZE, posY * TILESIZE);
vertex.texCoords = sf::Vector2f(256,0);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE + TILESIZE, posY * TILESIZE + TILESIZE);
vertex.texCoords = sf::Vector2f(256,128);
tiles.append(vertex);
vertex.position = sf::Vector2f(posX * TILESIZE, posY * TILESIZE + TILESIZE);
vertex.texCoords = sf::Vector2f(128,128);
tiles.append(vertex);
}
void Tile::loadTexture()
{
tiles.setPrimitiveType(sf::Quads);
if (!textureTileset.loadFromFile("Resources/Tileset.png"))
std::cout << "Error Loading" << std::endl;
}
Son Header :
#ifndef TILE_H
#define TILE_H
#include <SFML/Graphics.hpp>
#include <iostream>
class Tile : public sf::Drawable, public sf::Transformable
{
public:
Tile();
void addTile(int posX, int poxY);
void loadTexture();
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.transform *= getTransform();
states.texture = &textureTileset;
target.draw(tiles, states);
}
sf::Vertex vertex;
sf::VertexArray tiles;
sf::Texture textureTileset;
};
#endif // TILE_H
Et pour finir la classe Map : (où j'essaye d'avoir 10 tuiles de long et 10 tuiles de large)
#include "Map.h"
#define MAPSIZE 5
Map::Map()
{
tile.loadTexture();
for(int x = 0; x < MAPSIZE; x++)
{
for(int y = 0; y < MAPSIZE; y++)
{
sizeVector = Tilemap.size();
Tilemap.push_back(tile);
Tilemap[sizeVector].addTile(x, y);
}
}
}
Son header :
#ifndef MAP_H
#define MAP_H
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Tile/Tile.h"
class Map : public sf::Drawable, sf::Transformable
{
public:
Map();
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
target.draw(tile, states);
}
int sizeVector = 0;
Tile tile;
std::vector <Tile> Tilemap;
};
#endif // MAP_H
Et voilà mon problème c'est que ça n'affiche rien dans mon application ... Et ensuite au lancement de l'application j'en ai pour 10 secondes à charger ce "rien", j'aurai quelque chose ça irai mieux mais je trouve ça beaucoup trop long pour seulement 100 entités surtout que là j'ai qu'un seul appel à draw.
Donc dites moi si j'ai tout faux déjà, mais j'implore vraiment votre aide, je n'y arrive vraiment pas...
-
ça n'affiche rien dans mon application
cf. le tutoriel sur les sprites, section "le problème du carré blanc".
ensuite au lancement de l'application j'en ai pour 10 secondes à charger ce "rien"
Tu recopies plusieurs dizaines de fois la texture, je n'appelle pas ça "rien" ;)
Donc dites moi si j'ai tout faux déjà
En gros, oui. Chaque tuile possède sa texture, mais c'est en réalité la même qui est dupliquée à chaque fois. Chaque tuile possède son petit vertex array de 4 éléments alors que tout pourrait être dans le même (et la fonction addTile dans la classe Tile... ??). Chaque tuile est transformable alors qu'elles ne sont jamais déplacées / tournées / redimensionnées. Chaque tuile est drawable alors que l'ensemble de la carte est statique et pourrait être dessinée en une seule fois avec une seule texture et un seul vertex array.
Relis bien le tutoriel sur les vertex arrays, et... fais la même chose, c'est comme ça que ça doit être ;)
Enfin, mais ça c'est secondaire, ne stocke pas toutes tes variables temporaires comme membres de tes classes. Certaines variables (tile, vertex) devraient être locales aux fonctions dans lesquelles elles sont utilisées.
-
cf. le tutoriel sur les sprites, section "le problème du carré blanc".
D'accord, ce problème va être réglé, je n'y ai pas fait attention.
Tu recopies plusieurs dizaines de fois la texture, je n'appelle pas ça "rien" ;)
Justement en utilisant ma fonction .loadTexture() je me suis dit que ça allais charger ma texture une fois et puis basta, mais quand je fais .texcoord ça charge à chaque fois la texture ? Que dois je faire du coup ?
Ok je vais relire le tuto sur les Vertex Arrays, mais là ça fait tellement longtemps que je butte dessus que j'ai vraiment eu besoin de votre aide, parce que je cherche par tout les moyens de faire un truc mais je me plante et m'enfonce toujours plus et là je commence à être lassé par tout ça. En faites je pensais qu'on pouvais optimiser l'exemple dans le tutoriel avec la fonction append ...
Mais merci beaucoup de votre aide ! :)
-
Justement en utilisant ma fonction .loadTexture() je me suis dit que ça allais charger ma texture une fois et puis basta, mais quand je fais .texcoord ça charge à chaque fois la texture ? Que dois je faire du coup ?
Regarde là :
Tilemap.push_back(tile);
Là tu recopies tile et sa texture dans le tableau. Et lorsque le tableau a besoin de plus de place en mémoire, tous ses éléments sont à nouveau recopiés avec leur texture. Tout ceci fait au total environ une quarantaine de recopies de Tile, et donc de texture.
Ce que tu dois faire, c'est ne pas stocker la texture dans chaque tuile, puisque celles-ci partagent toutes la même. Elle doit être stockée au niveau de la carte.
Ok je vais relire le tuto sur les Vertex Arrays, mais là ça fait tellement longtemps que je butte dessus que j'ai vraiment eu besoin de votre aide
Est-ce que tu as compris ce tutoriel et l'exemple de tilemap ? Si non, tu butes sur quel(s) point(s) en particulier ?
-
En faites je ne buttes pas vraiment. C'est juste que je voulais que chaque tuile soit un objet indépendant pour pouvoir lui définir des variables propre à elle même. Et je pensais pas ca possible avec le tutoriel du site.
Et aussi c'est l'histoire des textures où j'ai pas mal de problème ... C'est surement dû au fait que j'ai toujours eu du mal avec les pointeurs :-\
Et puis surtout c'est que si je veux une carte de 100 * 100 je vais devoir générer la carte procéduralement et non avec le tableau d'entier présenté dans le tutoriel et je ne sais pas comment faudrait il faire autrement ;)
-
C'est juste que je voulais que chaque tuile soit un objet indépendant pour pouvoir lui définir des variables propre à elle même.
Le rendu et la logique peuvent rester séparés, pas besoin d'avoir une texture + vertex array par tuile, tu peux juste mettre les variables dont tu as besoin et garder l'aspect "rendu" centralisé dans Map.
Et aussi c'est l'histoire des textures où j'ai pas mal de problème ... C'est surement dû au fait que j'ai toujours eu du mal avec les pointeurs
Dans ce cas mon conseil c'est de bosser tes bases de C++ avant de commencer à faire des trucs compliqués. Sinon on risque de te revoir tous les jours sur ce forum, tu vas buter sur des détails du langage au lieu d'avancer sur les aspects intéressants de ton projet.
-
Dans ce cas mon conseil c'est de bosser tes bases de C++ avant de commencer à faire des trucs compliqués. Sinon on risque de te revoir tous les jours sur ce forum, tu vas buter sur des détails du langage au lieu d'avancer sur les aspects intéressants de ton projet.
Il faut au moins que je revois cette partie, car je pense me débrouiller autrement dans les classes, les fonctions, les conditions, l'héritage et même un peu avec la STL.
Je repost ça : (car vous avez pas du le voir, j'ai édité juste avant que vous mettiez la réponse)
Et puis surtout c'est que si je veux une carte de 100 * 100 je vais devoir générer la carte procéduralement et non avec le tableau d'entier présenté dans le tutoriel et je ne sais pas comment faudrait il faire autrement ;)
-
Et puis surtout c'est que si je veux une carte de 100 * 100 je vais devoir générer la carte procéduralement et non avec le tableau d'entier présenté dans le tutoriel et je ne sais pas comment faudrait il faire autrement
Quel est le rapport avec ce dont on discute ici ? Une fois que tu as une carte Map fonctionnelle, tu l'initialises comme tu veux, c'est un autre aspect.
-
Mais dois je automatiquement passer par le tableau d'entier pour définir chaque case ?
-
De toute évidence, non ;)
C'est toi le développeur, tu crées les fonctionnalités dont tu as besoin. Le tableau d'entier, c'était juste le plus simple et concis pour le tutoriel.
-
Oki doki, je tiens vraiment à vous remercier pour votre aide !
J'ai donc quelques trucs à revoir en C++ et surtout des fonctions à créer pour tout ça.
Merci beaucoup !