Je dispose d'une classe Block qui me permet de créer object Block et une classe World qui me permet de gérer mon monde.
Je m'explique, dans le constructeur de World je remplis une liste à deux dimensions d'object Block.Lors de leurs création, le constructeur de Block affecte à l'object créer un Sprite auquel il lui applique une texture. Ensuite à l'aide d'une méthode de World que j'appelle dans le Main, je draw les objects Block contenu dans World (dans la liste à deux dimensions) .. seulement j'obtiens le fameux carré blanc.
Donc le Sprite est bien là, c'est la texture qui n'existe plus. J'ai fais des recherches et j'en ai conclu que la texture était supprimé à la sortie de la classe dans laquelle elle a été crée (ce qui explique pourquoi cela marche quand je draw à partir de la classe Block). J'ai aussi cru comprendre que je devais utiliser des allocations dynamiques pour résoudre ce problème ... mais je n'y arrive pas .. Quelqu'un pourrait il m'aider ?
Cordialement.
Voici mon code car je doute que mon explication soit suffisamment clair :
Et si j'étais toi, je ferai hériter la classe Block de sf::Drawable, en redéfinissant ensuite la fonction draw() dans la classe Block, cela te permet de passer directement tes objets comme n'importe quel autre drawable dans la fonction draw() de ta fenêtre.
Autre chose, n'utilise pas using namespace std; (voir pourquoi ici).
Aussi, tu devrais utiliser la linéarisation d'un vector pour simuler une grille, ce serait bien plus simple et les array C-Style c'est pas bien en C++. Tu peux même créer ta propre classe template Matrice, ça te faciliterai l'existence.
Par contre le this n'est pas nécessaire du tout, il est implicite.
L'en-tête <stdio.h> est une en-tête du C. En C++ on fait appel à <cstdio>.
w et h devraient être constants.
Pourquoi instancier window, view, world et event dans l'espace global ?
Tu retournes une copie... par terrible niveau performances... Retourner par référence serait plus judicieux. Enfin de toute façon cette fonction n'a pas vraiment de sens quand on hérite de sf::Drawable... Et la fonction devrait être déclaré comme const étant donné qu'elle ne modifie aucun éléments de la classe; la fonction render() également.
Woh merci pour cette réponse complète, on ne se rends pas compte de toutes les erreurs qu'on peut faire .
J'ai fais tout ce que tu m'as dis (enfin je crois bien), j'ai fais mon world.render() entre window.clear() et window.display(), j'ai retirer tout les namespace (et fait les modifications en conséquence) pour ce qui est de la linéarisation de vector je ne vois pas bien ce dont tu parles (mais bien qu'il faudra que je m'y penche à un moment, ce n'est pas là le coeur de mon problème ... pour l'instant ), j'ai viré les this et remplacé <stdio.h> par <cstdio>, mit constant mes variables w et h ainsi que la methode render() de World, instancié window, view, world et event dans ma fonction main, supprimé ma méthode getBlockSprite() et fait hérité ma classe Block de sf::Drawable et donc egalement redefinie la fonction draw() dans Block ... seulement j'ai toujours le même problème : un carré blanc s'affiche (mon Sprite sans texture) .. le poids de la fatalité s'abat sur moi
Ps: J'ai modifier mon code dans mon premier post pour éviter le flood
Ah... je vois que la notion d'héritage t'est encore un peu flou ^^.
Oui c'est normal qu'il t'indique cette erreur. Quand tu hérites de drawable tu dois forcément redéfinir la fonction draw() avec exactement la même signature, là du fait que tu ais changé la signature, la classe Block hérite de la fonction virtuelle pure de drawable et cela fait de ta classe Block, une classe abstraite. Du coup ici ta fonction draw() dans Block est une surcharge et non pas une redéfinition...
La fonction draw() doit être tel quel dans ta classe Block (on redéfinie une fonction en ne changeant que le corps) :
Tu ne dois en aucun cas modifier la signature de la fonction, elle doit être identique, la seule chose qui doit changer, c'est le corps. Tout à l'heure quand je te disais de retirer states dans la fonction draw() cela insinuait "dans le corps de la fonction" ;).
Autant pour moi ! Pour ma défense je le savais mais j'avais cru comprendre que c'était ce que tu me demandais de faire, donc je me suis exécuté quand même , j'ai retiré state dans le corps mais ceci dit cela ne change rien à l'absence de texture .. c'est vachement frustrant je peux plus avancer .. mais si je veux travailler "convenablement" en POO qui se respecte un minimum, je dois trouver comment faire ..
.. c'est vachement frustrant je peux plus avancer ..
C'est ça qui est bon. C'est dans des moments comme ça qu'on en apprend le plus, enfin en admettant d'avoir la motivation :p.
Bon sinon j'ai regardé de plus prêt pour ton problème, pour le régler il suffit de stocker la texture dans la classe Block sous forme de pointeur (pas de pointeurs sauvages hein). Sinon au moment d'une copie, la texture se perd en cours de route, enfin si je ne dis pas de bêtise :).
Mais au final on ne va pas procéder ainsi car cette façon de procéder n'est pas des plus efficace. Si on regarde bien, à chaque blocs crées tu charges la texture, ce qui veut dire que si tu as 400 blocs, alors tu vas charger 400 fois la texture et prendre de la place en mémoire pour rien...
Une texture on la charge une fois, pas besoin de plus (sauf peut-être cas vraiment exceptionnel). Ensuite si un objet quelquonque en a besoin, on lui passe la texture sous forme d'adresse au moment de sa création par exemple.
Pour résumer et en m'adaptant à ton code de départ ça donnerait quelque chose comme ça (attention : conception immonde en approche):
/// /////////////////////////////////////////////////////
/// BLOCK
class Block : public sf::Drawable
{
public:
Block() = default;
Block(sf::Texture *texture);
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
target.draw(block_sprite, states);
}
protected:
sf::Sprite block_sprite;
sf::Texture *block_wood;
};
Block::Block(sf::Texture *texture) :
block_wood{texture}
{
block_sprite.setTexture(*block_wood);
block_sprite.setPosition(0, 0);
}
/// /////////////////////////////////////////////////////
/// WORLD
class World
{
public:
World(sf::Texture *texture);
void render(sf::RenderWindow& window) const;
protected:
Block map[20][20];
};
World::World(sf::Texture *texture)
{
map[0][0] = Block(texture);
}
void World::render(sf::RenderWindow& window) const
{
window.draw(map[0][0]);
}
/// /////////////////////////////////////////////////////
/// MAIN
int main()
{
// ...
// On charge une fois la texture
sf::Texture wood;
if(!wood.loadFromFile("textures/planks_spruce.png"))
std::cout << "Cannot load planks_spruce" << '\n';
// On passe l'adresse de la texture à World
World world(&wood);
// ...
while (window.isOpen())
{
// ...
window.clear();
world.render(window);
window.display();
}
return 0;
}
Mais déjà rien qu'avec ce bout de code on sent déjà venir les ennuis niveau conception ^^.
Dernière chose, faut vraiment éviter les array C-Style... c'est à bannir en C++.
Tout d'abord MERCI ! vraiment MERCI, ça fait franchement du bien de revoir à nouveau une texture sur son écran Oui même en étant noob je sens les ennuis et surtout les contraintes que ça va me poser de travailler de cette manière .. ceci-dit ne serait-il pas possible de fonctionner par un moyen "hybride" :
Stocker la texture dans la classe Block avec un pointeur ET d'utiliser une variable de classe (un compteur d'instance) pour déterminer si un block de ce type (sous entendu nécessitant la même texture) à déjà été crée et de ce faite ne pas recharger la texture ?
Car le faite de devoir passer la texture (enfin une référence) me parait assez "non-generique", surtout que par la suite je devrais affecter d'autre caracteristique (Solide ? Cliquable ? Destructible ?, etc) aux différents block selon leur type (passé en argument dans le constructeur) et je vois mal le faire selon leurs textures (je compte à terme fonctionner avec une multitude de block différents, et donc de classe du style : "Pierre" ou "Bois" héritant dans le classe Block .. mais chaque chose en sont temps pardi ! )
Ps : Promis je bannirais ces méchants array C-Style
Pour les tableaux dont tu connais la taille à l'avance (à la compilation ), utilise std::array<Type, Size> dans l'entête <array> , sinon std::vector<Type> (entête <vector> ) . Après , la STL dispose d'autres conteneurs : http://en.cppreference.com/w/cpp/container
En fait, pour tout ce que tu demandes, on sent bien qu'il va falloir une certaine structure à tout ce bazarre, donc plutôt que de répondre à tes questions une à une, je vais plutôt te faire part de ce que l'on doit faire/utiliser pour avoir une belle architecture. Mais attention, ce n'est vraiment pas facile à comprendre, d'ailleurs je n'expliquerai que vaguement ici, car moi-même je n'ai pas encore expérimenter les concepts qui vont suivre, ce sera à toi de te documenter là-dessus
Donc, quand on commence à développer des programmes volumineux nécessitant une certaine structure, pour éviter que ce soit le capharnaüm et la noyade dans le code, on utilise ce qu'on appelle des DESIGN PATTERNS.
Grosso-modo, les patterns sont là pour simplifier la conception/modification d'un programme demandant une orchestration particulière entre les éléments qui le composent.
Les plus connus dont tu entendras forcément de nouveau parler sont :
L'Entity Component System (ECS) - nottamant apprécié dans la programmation de jeux vidéos - est très efficace pour manipuler des entités "composées" tout en gardant une bonne cohérence globale du programme avec une bonne gestion des éléments.
Le Singleton - pour s'assurer qu'il n'y est qu'une seule est unique instance à la fois d'une classe donnée, j'ai souvent vu des exemples avec des classes "Audio/Sound"
La Factory - c'est une classe à qui tu délègues la création de différents types d'objets selon des arguments donnés, comme une usine en fait
L'Observer - comme son nom l'indique il... observe :). Son rôle est de surveiller les autres pour savoir ce qui se passe (nottament si il y a eu un changement sur une des classes surveillées), c'est un peu la commère du quartier
Et bien sûr la liste ne s'arrête pas là !
Bon je vais quand même te prévenir à propos des patterns : certains ne sont vraiment pas facile du tout à comprendre (ah mais je l'ai déjà dit ça il me semble ?). Et il y a une bonne raison à cela, c'est tout simplement parce que ces patterns sont là pour contourner des éventuels problèmes de conception, et si tu n'as jamais été confronté toi-même à certains problèmes particuliers, il y a de forte chance pour que tu ne vois pas de suite l'utilité de certains.
Personnellement, la première fois que j'ai eu un contact avec eux, j'étais complètement paumé (je le suis toujours un peu d'ailleurs) mais au final je pense qu'il n'y a pas de secret pour les comprendre, il faut pratiquer sans les utiliser au début, juste essayer de construire des programmes avec ta propre idée de conception puis, de là, tu vas forcément te retrouver face à un mur un moment ou un autre qui sera lié au fait que l'architecture du programme est mal organisée; et c'est à ce moment là que tu te poseras la question de savoir si il existe un design pattern pour contourner le problème. Ce qui induit que tu l'assimileras mieux à ce moment là :).
Du coup tout ce que je peux te dire c'est : vas-y programme ton idée comme tu le penses pour le moment, c'est en mettant les mains dans le camboui qu'on progresse :).
Bon j'ai pris le temps de bien regarder les différents concepts sur le wiki et d'autre site et c'est .. complexe en effet, comme tu dis pour les comprendre et avant de chercher à les utiliser, je vais le faire sans et simplement programmer avec l'achitecture que je conçois, le besoin de design patterns se fera surement ressentir par la suite de lui même et je pourrais mieux les comprendre une fois confronté aux problèmes que son absence engendre.
Maintenant il faut que j'arrive ce dont je parlais au post précédent, j'avoue que je galère énormément mais bon on verra bien si je fini par y arriver d'ici 2032 (Un peu de cynisme )
Maintenant il faut que j'arrive ce dont je parlais au post précédent, j'avoue que je galère énormément mais bon on verra bien si je fini par y arriver d'ici 2032 (Un peu de cynisme )
Héhé, t'inquiètes pas, ça fait partie du jeu ;). Tu n'imagines pas le nombres de fois où je me suis dis que j'allais programmer un super jeu et où je me suis lamentablement noyé dans mon propre code ou alors il me manquait de sérieuse base. Finalement, je me suis retrouvé avec plusieurs projets abandonnés, mais j'en ai tiré de bonnes leçons qui m'ont fait comprendre que mettre la charrue avant les boeufs n'était pas une bonne chose.
Au final j'ai plutôt fini par me concentrer sur des petits projets en m'amusant à programmer quelques classiques du genre comme Pong, BlockBreaker, Tetris... etc... et ce fût un très bon exercice (non sans mal parfois ^^), nottament au niveau de l'interaction entre objets.
En tout cas ne t'en fait pas si tu patoges, c'est normal .
Oui je sais c'est le jeu . Oui c'est ce que j'ai fais j'ai déjà codé plusieurs petit jeux comme un genre de Street Fighter mais c'était dans d'autre langage (Python) et c'était en Terminal : On nous avait pas enseigné la POO. Je """programme""" depuis longtemps des petits jeux, mais sans la POO que je travail en autodidacte depuis cette année seulement. A ce propos je vais devoir programmer un BlockBreaker c'est mon projet de 1ère année ... mais en JAVA .. enfin breeeeef la route sera longue
En tout cas merci de tout tes conseils
[SFML] Impossible de draw un Sprite d'autre Classe
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
...
...
...
...
Mon site web de jeux SDL2 entre autres : https://www.ant01.fr
...
...