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

Auteur Sujet: traduire le tuto c++ des vertexArray et le comprendre :)  (Lu 7425 fois)

0 Membres et 1 Invité sur ce sujet

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
traduire le tuto c++ des vertexArray et le comprendre :)
« le: Février 11, 2014, 06:00:26 pm »
Bonjour :)

Je viens de débuter sur SFML

Je souhaiterai convertir mon projet de jeux 2d ( basé sur un affichage de tileset et de sprite ) en PyGame, loin d'être fini mais PyGame n’étant pas assez véloce dans certain domaine je voulais essayer SFML pour comparer. Puis apparemment cette librairie offre plus de possibilité :)

J’essaie de traduire le tuto en C++ des vertexarray ( celui qui charge un tileset et l'affiche ) mais je galère quand même pas mal

Voila l'url du tuto C++
http://www.sfml-dev.org/tutorials/2.1/graphics-vertex-array-fr.php

et voici mon début de traduction :

import sfml as sf

class TileMap (sf.Drawable) :

    def __init__ (self):
        sfml.Drawable.__init__(self)
       
        # on declare la texture et le VertexArray
        self.m_tileset = sf.Texture
        self.m_vertices = sf.VertexArray(sf.PrimitiveType.QUADS)
     
    def load (self,tileset, tileSize, tiles, width, height) :
       
        # on charge la texture
        self.m_tileset = sf.Texture.from_file(tileset)

        # on redimensionne le tableau de vertex pour qu'il puisse contenir tout le niveau
        self.m_vertices.resize(width * height * 4);
       
        # on remplit le tableau de vertex, avec un quad par tuile
        for i in range(width) :
            for j in range(height) :
               
           
                # on récupère le numéro de tuile courant
                tileNumber = tiles[i + j * width];

               
               
               
                # on en déduit sa position dans la texture du tileset
                #
                # déjà la ça déconne ...
                #
                tu = tileNumber % (self.m_tileset.size.x / tileSize.x);
                tv = tileNumber // (self.m_tileset.size.x / tileSize.x);
               
               
               
                # on récupère un pointeur vers le quad à définir dans le tableau de vertex
                self.quad = self.m_vertices[(i + j * width) * 4]
               
                print(type(self.quad))
               
                # on définit ses quatre coins
                #
                # C'est la que je ne comprend pas ... un type(self.quad) m'indique que c'est un vertex
                # hors un vertex ne n'est pas iterable donc d’où vient le quad[2]
                #
                self.quad[0].position = sf.Vector2(i * tileSize.x, j * tileSize.y)
                self.quad[1].position = sf.Vector2((i + 1) * tileSize.x, j * tileSize.y)
                self.quad[2].position = sf.Vector2((i + 1) * tileSize.x, (j + 1) * tileSize.y)
                self.quad[3].position = sf.Vector2(i * tileSize.x, (j + 1) * tileSize.y)

                # on définit ses quatre coordonnées de texture
                self.quad[0].tex_coords = sf.Vector2(tu * tileSize.x, tv * tileSize.y)
                self.quad[1].tex_coords = sf.Vector2((tu + 1) * tileSize.x, tv * tileSize.y)
                self.quad[2].tex_coords = sf.Vector2((tu + 1) * tileSize.x, (tv + 1) * tileSize.y)
                self.quad[3].tex_coords = sf.Vector2(tu * tileSize.x, (tv + 1) * tileSize.y)




# On crée la fenêtre principale
window = sf.RenderWindow(sf.VideoMode(800, 600), "PySFML test")
# window.vertical_synchronization = True
# window.framerate_limit = 60
# icon = sf.Image.from_file("data/icon.bmp")
# window.icon = icon.pixels  
     
       
level = [
        0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
        1, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
        0, 1, 0, 0, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 0, 0,
        0, 1, 1, 0, 3, 3, 3, 0, 0, 0, 1, 1, 1, 2, 0, 0,
        0, 0, 1, 0, 3, 0, 2, 2, 0, 0, 1, 1, 1, 1, 2, 0,
        2, 0, 1, 0, 3, 0, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1,
        0, 0, 1, 0, 3, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1,
    ]
tm = TileMap()
tm.load("resources/tileset1a.jpg",sf.Vector2(32,32),level,16,8)

window.draw(tm)
window.display()
 


Je ne comprend pas cette histoire de quad, qui est un vertex et qui serait iterrable ???

version C++ :

                // on récupère un pointeur vers le quad à définir dans le tableau de vertex
                sf::Vertex* quad = &m_vertices[(i + j * width) * 4];

                // on définit ses quatre coins
                quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #1 le: Février 11, 2014, 08:34:20 pm »
Dans la version C++, c'est un pointeur sur un sf::Vertex qu'on a, pas un sf::Vertex. Et avec un pointeur on peut se balader pour aller pointer sur les élements (vertex) suivants dans le tableau. Dans ta version Python, je ne suis pas sûr que tu puisses avoir l'équivalent.

De toute façon ce n'est pas nécessaire, c'est juste pour ne pas écrire 8 fois le calcul d'indice complet. Tu peux faire ça pour t'en passer :

base = (i + j * width) * 4;

self.m_vertices[base + 0].position = ...;
self.m_vertices[base + 1].position = ...;
self.m_vertices[base + 2].position = ...;
self.m_vertices[base + 3].position = ...;

self.m_vertices[base + 0].texCoords = ...;
self.m_vertices[base + 1].texCoords = ...;
self.m_vertices[base + 2].texCoords = ...;
self.m_vertices[base + 3].texCoords = ...;
Laurent Gomila - SFML developer

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #2 le: Février 12, 2014, 11:07:58 pm »
Merci pour ta réponse :) je vais essayer ça

J'en profite, pour un affichage en tuile, ( comme dans le tuto)  il est préférable d'utiliser les tableau de vertex ou un affichage de multiple sprites fonctionne aussi très bien ?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #3 le: Février 12, 2014, 11:14:52 pm »
Les sprites seront bien moins efficaces. Comme expliqué dans le tutoriel.
Laurent Gomila - SFML developer

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #4 le: Février 13, 2014, 01:08:05 pm »
J'ai fait ce que tu m'a dit :) il n'y pas d'erreur mais il n'y a pas d'affichage non plus.

Je pense qu'il y a un truc qui rechape avec la méthode draw de la classe Tilemap et la methode sf.draw originale aussi


ce code fonctionne et m’affiche un jolie rectangle avec un dégradé de couleur :

import sfml as sf

window = sf.RenderWindow(sf.VideoMode(640, 480), 'SFML Window')

quad = sf.VertexArray(sf.PrimitiveType.QUADS, 4)
quad[0].position = (10, 10)
quad[1].position = (110, 10)
quad[2].position = (110, 110)
quad[3].position = (10, 110)

quad[0].color = sf.Color.RED
quad[1].color = sf.Color.GREEN
quad[2].color = sf.Color.BLUE
quad[3].color = sf.Color.YELLOW

window.draw(quad)
 

Mais pour appliquer une texture, je pensai qu'il suffisait de passer cette texture en paramètre comme l'indique le tuto

Citer
sf::VertexArray vertices;
sf::Texture texture;

...

window.draw(vertices, &texture);

donc :

tileset = sf.Texture.from_file("resources/tileset1a.jpg")
window.draw(quad, tileset)
 
Erreur :
Citer
TypeError: Argument 'states' has incorrect type (expected sfml.graphics.RenderStates,
got sfml.graphics.Texture)

Il faut passer un renderStates ? et la ...

quad = sf.VertexArray(sf.PrimitiveType.QUADS, 4)
quad[0].position = (10, 10)
quad[1].position = (110, 10)
quad[2].position = (110, 110)
quad[3].position = (10, 110)

quad[0].color = sf.Color.RED
quad[1].color = sf.Color.GREEN
quad[2].color = sf.Color.BLUE
quad[3].color = sf.Color.YELLOW

quad[0].tex_coords = (0, 0);
quad[1].tex_coords = (25, 0);
quad[2].tex_coords = (25, 50);
quad[3].tex_coords = (0, 50);

tileset = sf.Texture.from_file("resources/tileset1a.jpg")

states = sf.RenderStates
states.texture = tileset

window.draw(quad,states)



Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #5 le: Février 13, 2014, 01:17:15 pm »
Là je ne peux pas t'aider, le type de paramètre et la manière de le passer sont spécifiques au binding Python.

Mais ton dernier morceau de code a l'air ok, ça ne fonctionne pas non plus ?
Laurent Gomila - SFML developer

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #6 le: Février 13, 2014, 02:13:32 pm »
et non :)

Voici le message d'erreur  concernant la ligne : states.texture = tileset

Citer
TypeError: can't set attributes of built-in/extension type 'sfml.graphics.RenderStates'

EDIT :

ahh j'ai vue d’où provient une des erreurs :

states = sf.RenderStates()

Je vais déjà chercher de ce coté la :)


EDIT 2 :

J'arrive a afficher la map :)

Voici le code pour les intéressés  :

import sfml as sf

class TileMap (sf.TransformableDrawable) : # sf.Transformable

    def __init__ (self):
        sf.Drawable.__init__(self)
       
        # on declare la texture et le VertexArray
        self.m_tileset = sf.Texture
        self.m_vertices = sf.VertexArray(sf.PrimitiveType.QUADS)
     
    def load (self,tileset, tileSize, tiles, width, height) :
       
        # on charge la texture
        self.m_tileset = sf.Texture.from_file(tileset)

        # on redimensionne le tableau de vertex pour qu'il puisse contenir tout le niveau
        self.m_vertices.resize(width * height * 4);
       
        # on remplit le tableau de vertex, avec un quad par tuile
        for i in range(width) :
            for j in range(height) :
               
                # on récupère le numéro de tuile courant
                tileNumber = tiles[i + j * width];

                # on en déduit sa position dans la texture du tileset
                tu = tileNumber % (self.m_tileset.size.x / tileSize.x);
                tv = tileNumber // (self.m_tileset.size.x / tileSize.x);

                # On incremante une variable qui definie la position de chaque case
                case = (i + j * width) * 4;
               
                # on définit ses quatre coins
                self.m_vertices[case + 0].position = sf.Vector2(i * tileSize.x, j * tileSize.y)
                self.m_vertices[case + 1].position = sf.Vector2((i + 1) * tileSize.x, j * tileSize.y)
                self.m_vertices[case + 2].position = sf.Vector2((i + 1) * tileSize.x, (j + 1) * tileSize.y)
                self.m_vertices[case + 3].position = sf.Vector2(i * tileSize.x, (j + 1) * tileSize.y)
               
                # on définit ses quatre coordonnées de texture
                self.m_vertices[case + 0].tex_coords = sf.Vector2(tu * tileSize.x, tv * tileSize.y)
                self.m_vertices[case + 1].tex_coords = sf.Vector2((tu + 1) * tileSize.x, tv * tileSize.y)
                self.m_vertices[case + 2].tex_coords = sf.Vector2((tu + 1) * tileSize.x, (tv + 1) * tileSize.y)
                self.m_vertices[case + 3].tex_coords = sf.Vector2(tu * tileSize.x, (tv + 1) * tileSize.y)

    def draw(self, target) :
       
        states = sf.RenderStates()
        states.texture = self.m_tileset
        target.draw(self.m_vertices, states)

# ----- MAIN -----


# On crée la fenêtre principale
window = sf.RenderWindow(sf.VideoMode(800, 600), "PySFML test")
     
level = [
        0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
        1, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3,
        0, 1, 0, 0, 2, 0, 3, 3, 3, 0, 1, 1, 1, 0, 0, 0,
        0, 1, 1, 0, 3, 3, 3, 0, 0, 0, 1, 1, 1, 2, 0, 0,
        0, 0, 1, 0, 3, 0, 2, 2, 0, 0, 1, 1, 1, 1, 2, 0,
        2, 0, 1, 0, 3, 0, 2, 2, 2, 0, 1, 1, 1, 1, 1, 1,
        0, 0, 1, 0, 3, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 1,
    ]

# on crée la tilemap avec le niveau précédemment défini
map = TileMap()
map.load("resources/tileset1a.jpg", sf.Vector2(32,32),level,16,8)

# On démarre la boucle de jeu
while window.is_open :
    # on gère les évènements
    for event in window.events :
        if type(event) is sf.CloseEvent :
            window.close()
   
    # On dessine le niveau
    window.clear()
    map.draw(window)    
    window.display()
   
« Modifié: Février 13, 2014, 03:45:58 pm par davs63 »

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #7 le: Février 13, 2014, 03:44:48 pm »
Il me reste une question, sur la methode draw de la classe Tilemap du tuto :
    virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        // on applique la transformation
        states.transform *= getTransform();

        // on applique la texture du tileset
        states.texture = &m_tileset;

        // et on dessine enfin le tableau de vertex
        target.draw(m_vertices, [b]states[/b]);
    }

Je ne comprend pas comment est elle appelée puisque dans Main() on a un simple :

window.draw(map);
puis le paramètre sf::RenderStates statesje ne voie nul pars ou il est envoyé :/


en python je suis obligé d'appeler la methode classiquement :

map.draw(window)

et sans passer le paramètre states
« Modifié: Février 13, 2014, 03:52:58 pm par davs63 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #8 le: Février 13, 2014, 04:12:13 pm »
Citer
Je ne comprend pas comment est elle appelée
Citer
puis le paramètre sf::RenderStates statesje ne voie nul pars ou il est envoyé :/
Je pense qu'une vue (simplifiée) du contenu de RenderWindow::draw répondra à tes questions :

void RenderWindow::draw(sf::Drawable& drawable, sf::RenderStates states = sf::RenderStates::Default) // paramètre optionnel
{
    drawable.draw(this, states);
}

Donc :

window.draw(object);

// équivaut à :

sf::RenderStates states = sf::RenderStates::Default;
window.draw(object, states);

// et tout ceci finit en :

object.draw(window, states);
Laurent Gomila - SFML developer

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #9 le: Février 13, 2014, 05:35:29 pm »
C'est vraiment sympa de m'expliquer :) , j'ai tenté de comprendre mais je pense que mon niveau est à des années lumière du tient  :'(

Je ne connais absolument pas C++ dont la syntaxe est assez exotique pour moi, et comparé aux langages plus simple que je connais un peu (python, php)

En c++ apparemment on doit déclarer les variables sans le fameux = et en indiquant obligatoirement le type en avant celle ci. Il y a une bestiole étrange " :: " qui a l'air de dire " je suis un membre de la classe ... " et donc remplace la simple notation pointé. Et le void, je crois que je l'ai déjà vue en AS3 ^^ et veut dire " je renvoie rien " . Bref C++ c'est hard pour les petits esprits comme le miens, je vais pas t’embêter à m'expliquer ce langage on sortirai du cadre de ce forum

Mais en python quand j'envoie :  window.draw(objet) ça n'appelle pas la méthode draw de cet objet :/

Du coup mon code map.draw(window) dans la boucle while est une mauvaise manière d'utiliser la classe Tilemap ?

Je vais re relire la doc de pysmfl au sujet de renderWindow
« Modifié: Février 13, 2014, 05:38:20 pm par davs63 »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #10 le: Février 13, 2014, 11:00:25 pm »
Là encore, c'est spécifique au binding, je ne peux pas t'aider. Il y a des choses qui fonctionnent en C++ mais ne sont pas reproduites dans certains bindings, notamment les histoires d'héritage.
Laurent Gomila - SFML developer

davs63

  • Newbie
  • *
  • Messages: 17
    • Voir le profil
Re : traduire le tuto c++ des vertexArray et le comprendre :)
« Réponse #11 le: Février 14, 2014, 09:52:06 am »
Ça fonctionne sans l’héritage donc je vais faire sans :)  et je reviendrai dessus quand j'aurai plus d’expérience.

Je compte tenir un blog pour montrer toutes les étapes de A à Z du développement de mon jeu avec Python et Sfml, et en français évidement. C'est pour ça que j’essaie de ne pas trop contourner les problèmes mais de les comprendre et les repoudre. J'ai pas fini de venir sur ce forum ^^

En tout cas merci pour tes explications et ton aide :)

 

anything