Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Tableau dynamique/statique  (Lu 6325 fois)

0 Membres et 1 Invité sur ce sujet

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Tableau dynamique/statique
« le: Décembre 26, 2014, 12:15:33 am »
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
« Modifié: Décembre 26, 2014, 03:42:09 am par Develog »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Tableau dynamique/statique
« Réponse #1 le: Décembre 26, 2014, 10:07:34 am »
Salut

Ici c'est un forum concernant SFML, il y a d'autres endroits plus appropriés pour les questions de C++.

Merci.
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #2 le: Décembre 26, 2014, 03:35:32 pm »
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

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Tableau dynamique/statique
« Réponse #3 le: Décembre 26, 2014, 08:49:53 pm »
Citer
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é.
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #4 le: Décembre 26, 2014, 09:46:49 pm »
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
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Tableau dynamique/statique
« Réponse #5 le: Décembre 26, 2014, 10:45:05 pm »
Ok, tu as donc 100 appels à la fonction draw. Quelle est la question ?
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #6 le: Décembre 26, 2014, 11:17:11 pm »
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 :/

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Tableau dynamique/statique
« Réponse #7 le: Décembre 27, 2014, 01:36:56 am »
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.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Tableau dynamique/statique
« Réponse #8 le: Décembre 27, 2014, 11:16:05 am »
Je me permets de mettre en relief la partie importante de la réponse précédente :

Citer
regarde le tuto sur les vertexarray et les tilemap sur le site.

;)
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #9 le: Décembre 27, 2014, 01:05:41 pm »
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

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Tableau dynamique/statique
« Réponse #10 le: Décembre 27, 2014, 01:15:30 pm »
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 ?

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #11 le: Décembre 27, 2014, 01:22:19 pm »
@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.

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #12 le: Décembre 30, 2014, 10:39:14 pm »
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...

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Tableau dynamique/statique
« Réponse #13 le: Décembre 30, 2014, 11:01:52 pm »
Citer
ça n'affiche rien dans mon application
cf. le tutoriel sur les sprites, section "le problème du carré blanc".

Citer
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" ;)

Citer
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.
Laurent Gomila - SFML developer

Develog

  • Full Member
  • ***
  • Messages: 100
    • Voir le profil
    • E-mail
Re : Tableau dynamique/statique
« Réponse #14 le: Décembre 30, 2014, 11:15:38 pm »
Citer
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.

Citer
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 ! :)