Précédent   Forum du club des développeurs et IT Pro > C et C++ > C++ > Langage
Langage Langage C++, Programmation Orientée Objet, Templates, etc. Avant de poster : FAQ C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 31/12/2012, 15h36   #1
Nick84
Invité de passage
 
Homme
Inscription : décembre 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : décembre 2011
Messages : 4
Points : 2
Points : 2
Par défaut Problème de pointeur

Depuis mon autre problème d'hier, qui a heureusement été résolu, je me confronte aujourd'hui à un second problème, qui je pense est du aux pointeurs (je ne dois probablement pas encore en savoir assez sur eux pour les utiliser correctement, et pourtant je me suis déjà beaucoup renseigné sur eux à travers différents tuto...).

Mon problème est le suivant: j'ai une classe GameLaunch qui me permet de générer un monde à travers une classe WorldManager, qui contient tout simplement un tableau créé dynamiquement à deux dimensions, auquel on peut accéder via des mutateurs (get et set) qui renvoient ou change la valeur du tableau via son pointeur (int** worldTab). Cette classe WorldManager est donc créée dans une des méthodes de ma classe GameLaunch (void lauchGame() qui fait tourner la boucle principale du jeu), et j'ai créé un pointeur ptrWorldManager qui pointe sur cette classe pour pouvoir ensuite l'envoyer en argument à d'autres classes lors de leur construction.

Le problème survient à ce moment là. Par exemple, je crée dynamiquement ma classe GenerateWorld en envoyant comme argument à son constructeur le pointeur ptrWorldManager, qui est alors stocké dans une variable à l'intérieur même de GenerateWorld. Puis le constructeur appel l'une de ses fonctions privées (void biomeCollines(...)). Cette fonction est donc censée utiliser worldManager->setWorldTab(i , j , set), ce qu'elle fait très bien, mais si par exemple set vaut 2, et que tout de suite après j'appel worldManager->getWorldTab(i , j), ce dernier me renvoi 0!!!

J'ai le même problème dans toutes mes autres classes possédant un pointeur sur le fameux worldManager, dans tous les cas, un set ne changera rien et un get renverra toujours 0!

Je suppose donc que mes pointeurs sur worldManager se mélangent, ou alors créent de nouvelles instances de WorldManager, ce que je ne comprend pas...
J'implore donc votre aide, amis développeurs, et voici mon code:

WorldManager.cpp:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "WorldManager.h"
 
#include <SFML/Graphics.hpp>
#include <iostream>
 
WorldManager::WorldManager(int const a_tailleX , int const a_tailleY): tailleX(a_tailleX), tailleY(a_tailleY), worldTab(0)
{
    /* Allocation dynamique du tableau */
    worldTab = this->constructeurTableauDynamique();
 
    /* Initialisation */
    for (int i = 0 ; i < tailleX ; i++)
    {
        for (int j = 0 ; j < tailleY ; j++)
        {
            this->setWorldTab(i , j , 0);
        }
    }
}
 
WorldManager::~WorldManager()
{
    /* Destruction du double tableau */
    this->destructeurTableauDynamique(worldTab);
}
 
int** WorldManager::constructeurTableauDynamique()
{
    int** worldTab = new int* [tailleX];
    for (int i = 0 ; i < tailleX ; i++)
    {
        worldTab[i] = new int[tailleY];
    }
 
    return worldTab;
}
 
void WorldManager::destructeurTableauDynamique(int** worldTab)
{
    for (int i=0; i < tailleX; i++)
    {
        delete[] worldTab[i];
    }
    delete[] worldTab;
}
 
int WorldManager::getWorldTab(int i , int j)
{
    return worldTab[i][j];
}
 
void WorldManager::setWorldTab(int i , int j , int set)
{
    worldTab[i][j] = set;
}
WorldManager.h:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef WORLDMANAGER_H_INCLUDED
#define WORLDMANAGER_H_INCLUDED
 
#include <SFML/Graphics.hpp>
 
class WorldManager
{
    public:
 
    WorldManager(int const a_tailleX , int const a_tailleY);
    ~WorldManager();
 
    int** constructeurTableauDynamique();
    void destructeurTableauDynamique(int** worldTab);
 
    int getWorldTab(int i , int j);
    void setWorldTab(int i , int j , int set);
 
    private:
 
    //Variables stockant la taille du tableau
    int const tailleX;
    int const tailleY;
 
    int **worldTab;
};
 
#endif // WORLDMANAGER_H_INCLUDED
GameLauch.cpp:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "GameLaunch.h"
#include "WorldManager.h"
#include "Camera.h"
#include "GenerateWorld.h"
#include "ImageManager.h"
#include "BlockManager.h"
 
#include <SFML/Graphics.hpp>
#include <iostream>
 
GameLaunch::GameLaunch(sf::RenderWindow *a_app):  worldLength(200), worldHeight(100), app(a_app), camera(0), Event(), framerate(), LeftKeyDown(), RightKeyDown(), LeftButtonDown(), RightButtonDown(), MouseX(), MouseY()
{
    camera = new Camera(worldLength * 10 - app->GetWidth() / 2 , worldHeight * 10 - app->GetHeight() / 2 , app->GetWidth() , app->GetHeight());
    std::cout << "Launching game loop" << std::endl;
}
 
GameLaunch::~GameLaunch()
{
    delete camera;
}
 
void GameLaunch::launchGame()
{
    //Activation de la synchronisation vertcale
    app->UseVerticalSync(true);
 
    //Création du tableau dans la classe WorldManager
    WorldManager *ptrWorldManager;
    WorldManager worldManager(worldLength , worldHeight);
    ptrWorldManager = &worldManager; //Le fameux pointeur
 
    GenerateWorld *generator;
    generator = new GenerateWorld(ptrWorldManager, worldLength, worldHeight);
 
    ImageManager *imageManager;
    imageManager = new ImageManager();
 
    BlockManager *blockManager;
    blockManager = new BlockManager(ptrWorldManager, worldLength, worldHeight, imageManager, app, camera);
    //Le problème se situe dans les classes GenerateWorld et BlockManager
 
    //Création d'une constante input permettant de récupérer les entrées claviers/souris ou la position de la souris -> cette classe n'a pas été initialisée dans le constructeur, mais pourrait l'être à l'avenir
    const sf::Input& Input = app->GetInput();
 
    // Exécution de la boucle principale du jeu
    while (app->IsOpened())
    {
        //Efface l'écran (remplissage avec du noir)
        app->Clear();
 
        //On récupère les IPS actuels de notre fenêtre
        framerate = 1.f / app->GetFrameTime();
 
        // Traitement des évènements: fermeture de la fenêtre
        while (app->GetEvent(Event))
        {
            // Fenêtre fermée : on quitte
            if (Event.Type == sf::Event::Closed)
                app->Close();
        }
 
        // Traitement des entrées
        LeftKeyDown     = Input.IsKeyDown(sf::Key::Left);
        RightKeyDown    = Input.IsKeyDown(sf::Key::Right);
        LeftButtonDown  = Input.IsMouseButtonDown(sf::Mouse::Left);
        RightButtonDown = Input.IsMouseButtonDown(sf::Mouse::Right);
        MouseX          = Input.GetMouseX();
        MouseY          = Input.GetMouseY();
 
        //Affichage du monde
        blockManager->blitMap();
 
        // Affichage du contenu de la fenêtre à l'écran
        app->Display();
    }
 
    delete generator;
    delete imageManager;
    delete blockManager;
}
GameLaunch.h:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#ifndef GAMELAUNCH_H_INCLUDED
#define GAMELAUNCH_H_INCLUDED
 
#include <SFML/Graphics.hpp>
 
#include "WorldManager.h"
#include "Camera.h"
 
class GameLaunch
{
    public:
 
    GameLaunch(sf::RenderWindow *a_app);
    ~GameLaunch();
 
    void launchGame();
 
    private:
 
    int const worldLength;
    int const worldHeight;
 
    sf::RenderWindow *app; // Création d'un pointeur sur la fenêtre de rendu
 
    Camera *camera; //Création d'un pointeur sur la caméra
    WorldManager *worldManager; //Création d'un pointeur sur le manageur de monde
 
    sf::Event Event; //Création de l'évènement event (pas de pointeur)
 
    float framerate; //Fréquence de rafraîchissement de l'image
 
    //Différentes variables qui stockent les entrées claviers/souris et la position de la souris
    bool         LeftKeyDown;
    bool         RightKeyDown;
    bool         LeftButtonDown;
    bool         RightButtonDown;
    unsigned int MouseX;
    unsigned int MouseY;
 
};
 
#endif // GAMELAUNCH_H_INCLUDED
GenerateWorld.cpp:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include "GenerateWorld.h"
#include "WorldManager.h"
 
#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
 
GenerateWorld::GenerateWorld(WorldManager *a_worldManager, int a_tailleX, int a_tailleY): worldManager(0), tailleX(a_tailleX), tailleY(a_tailleY), seaLevel(tailleY * (1/2))
{
    worldManager = a_worldManager;
    this->biomeCollines(tailleX , 0 , 10 , 3);
    std::cout << "Biome Collines has been generated" << std::endl;
    std::cout << "Generation done" << std::endl;
    std::cout << "Gen : " << worldManager->getWorldTab(156 , 86); //Normalement, il devrait s'afficher Gen : 2 suite à la génération du monde (j'ai fait les tests pour 156 86), or ce n'est pas le cas (Gen : 0)
}
 
void GenerateWorld::biomeCollines(int length , int biomeX , int heightMax , int layersTerre) //Où biomeX est la place du biome dans le monde, et lenght la longueur du biome -> à noter que le biome occupe toute la hauteure du monde
{
    int progress = 0;
    int pProgress;
    int rep = (rand() % 2) + 2;
    int height = seaLevel;
    int r1 , r2;
    int q , i , j;
 
    while (progress < length - 6 * rep)
    {
        if (height < seaLevel + heightMax - rep && height > seaLevel - heightMax + rep) {r1 = rand() % 2;}
        else if (height >= seaLevel + heightMax - rep) {r1 = 1;}
        else {r1 = 0;}
 
        for (q = 0 ; q < rep ; q++)
        {
            if (r1 == 0) {height++;}
            else {height--;}
 
            r2 = rand() % 9;
 
            if (r2 == 0) {pProgress = 2;}
            else if (r2 > 0 && r2 < 3) {pProgress = 3;}
            else if (r2 > 2 && r2 < 6) {pProgress = 4;}
            else if (r2 > 5 && r2 < 8) {pProgress = 5;}
            else {pProgress = 6;}
 
            for (i = 0 ; i < pProgress ; i++)
            {
                for (j = height ; j < tailleY ; j++)
                {
                    if (j - height < layersTerre) {worldManager->setWorldTab(i + biomeX , j , 1);}
                    else {worldManager->setWorldTab(i + biomeX , j , 2);}
                }
            }
            progress += pProgress;
        }
        rep = (rand() % 2) + 2;
    }
 
    for (int a = 0 ; a < length - progress ; a++)
    {
        for (int b = height ; b < tailleY ; b++)
        {
            if (b - height < layersTerre) {worldManager->setWorldTab(a + biomeX , b , 1);}
            else {worldManager->setWorldTab(a + biomeX , b , 2);}
        }
    }
}
GenerateWorld.h:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef GENERATEWORLD_H_INCLUDED
#define GENERATEWORLD_H_INCLUDED
 
#include <SFML/Graphics.hpp>
 
#include "WorldManager.h"
 
class GenerateWorld
{
    public:
 
    GenerateWorld(WorldManager *a_worldManager, int a_tailleX, int a_tailleY);
 
    private:
 
    void biomeCollines(int length , int biomeX , int heightMax , int layersTerre);
 
    WorldManager *worldManager;
 
    int const tailleX;
    int const tailleY;
    int seaLevel;
};
 
#endif // GENERATEWORLD_H_INCLUDED
Nick84 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2012, 16h12   #2
Iradrille
Membre éprouvé
 
Homme
Étudiant
Inscription : juin 2012
Messages : 263
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : juin 2012
Messages : 263
Points : 443
Points : 443
C'est ton algo qui renvoi 0, pas un soucis de pointeur
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <stdlib.h>
#include <iostream>
 
 
const int tailleY = 100;
const int tailleX = 200;
int seaLevel = 50;
int tab[tailleX][tailleY];
 
void biomeCollines(int length , int biomeX , int heightMax , int layersTerre)
{
 
	int progress = 0;
	int pProgress;
	int rep = (rand() % 2) + 2;
	int height = seaLevel;
	int r1 , r2;
	int q , i , j;
 
	while (progress < length - 6 * rep)
	{
		if (height < seaLevel + heightMax - rep && height > seaLevel - heightMax + rep) {r1 = rand() % 2;}
		else if (height >= seaLevel + heightMax - rep) {r1 = 1;}
		else {r1 = 0;}
 
		for (q = 0 ; q < rep ; q++)
		{
			if (r1 == 0) {height++;}
			else {height--;}
 
			r2 = rand() % 9;
 
			if (r2 == 0) {pProgress = 2;}
			else if (r2 > 0 && r2 < 3) {pProgress = 3;}
			else if (r2 > 2 && r2 < 6) {pProgress = 4;}
			else if (r2 > 5 && r2 < 8) {pProgress = 5;}
			else {pProgress = 6;}
 
			for (i = 0 ; i < pProgress ; i++)
			{
				for (j = height ; j < tailleY ; j++)
				{
					if (j - height < layersTerre) {tab[i + biomeX][j] = 1;}
					else {tab[i + biomeX][j] = 2;}
				}
			}
			progress += pProgress;
		}
		rep = (rand() % 2) + 2;
	}
 
	for (int a = 0 ; a < length - progress ; a++)
	{
		for (int b = height ; b < tailleY ; b++)
		{
			if (b - height < layersTerre) {tab[a + biomeX][b] = 1;}
			else {tab[a + biomeX][b] = 2;}
		}
	}
}
 
int main(int argc, char** argv) {
 
	biomeCollines(tailleX , 0 , 10 , 3);
	std::cout << tab[156][86];
	return 0;
}
-> Affiche 0 (oui variables globales etc... J'assume :p)

Sinon tu devrais utiliser des smart ptr pour "generator", "imageManager" et "blockManager" (dans GameLaunch::launchgame() ). La si une exception est lancée tu te retrouve avec une fuite mémoire.

edit: Heu... il ya que des tab[x][y] = 1 ou 2 dans le code, pas de memset ni de ZeroMemory et pourtant ça me donne 0, les tableaux de int sont initialisés à 0 ? *_*
Iradrille est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2012, 16h15   #3
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 665
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 665
Points : 4 421
Points : 4 421
Bonjour,

si tu veux faire un minecraft en c++, il faut que tu commences par arrêter d'utiliser des pointeurs partout

Concrètement, au lieu de:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    //Création du tableau dans la classe WorldManager
    WorldManager *ptrWorldManager;
    WorldManager worldManager(worldLength , worldHeight);
    ptrWorldManager = &worldManager; //Le fameux pointeur
 
    GenerateWorld *generator;
    generator = new GenerateWorld(ptrWorldManager, worldLength, worldHeight);
 
    ImageManager *imageManager;
    imageManager = new ImageManager();
 
    BlockManager *blockManager;
    blockManager = new BlockManager(ptrWorldManager, worldLength, worldHeight, imageManager, app, camera);
 
    // code
 
    delete generator;
    delete imageManager;
    delete blockManager;
}
Préférer le code:
Code :
1
2
3
4
5
6
7
8
9
10
    //Création du tableau dans la classe WorldManager
    WorldManager worldManager(worldLength , worldHeight);
    GenerateWorld generator(worldManager, worldLength, worldHeight);
    ImageManager imageManager;
    BlockManager blockManager(ptrWorldManager, worldLength, worldHeight, imageManager, app, camera);
 
    // code
 
    // pas besoin d'appeler les destructeurs
}
C'est plus court, plus facile, et surtout, ça t'éviteras de nombreuses erreurs. Les pointeurs sont sources de problèmes, il faut les éviter tant que faire se peut.

De même, si tu a besoin de ton worldManager dans ton generator, passes-le par référence, et non par pointeur. Du coup, GenerateWorld ressemblera à quelque chose comme ceci:
Code :
1
2
3
4
5
// le contructeur:
GenerateWorld::GenerateWorld(WorldManager & a_worldManager, int a_tailleX, int a_tailleY);
 
// et la variable membre
WorldManager & worldManager;
Si tu fais ce que je t'explique là (bannir les pointeurs de ton code), tu verras tout fonctionnera sans prise de tête.
r0d est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2012, 16h19   #4
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 665
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 665
Points : 4 421
Points : 4 421
J'insiste lourdement, mais c'est important. Tu as écrit:
Code :
GameLaunch(sf::RenderWindow *a_app);
Si tu regardes un peu les en-têtes de la SFML, tu verras que tous les paramètres sont passés par référence. Il FAUT que tu fasses pareil, c'est à dire:
Code :
GameLaunch(sf::RenderWindow & a_app);
r0d est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2012, 16h23   #5
Nick84
Invité de passage
 
Homme
Inscription : décembre 2011
Messages : 4
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations forums :
Inscription : décembre 2011
Messages : 4
Points : 2
Points : 2
Effectivement Iradrille tu avais raison c'était bien un problème dans mon algo (tout simplement un - ou lieu d'un + )... C'est bête tout ce que cela peut engendrer comme problèmes... Donc je m'excuse pour ce post si long alors que le problème était vraiment tout bête...

r0d: oui je crois que je vais arrêter avec tous ces pointeurs, et utiliser des références (je pensais que les pointeurs permettaient de faire plus de chose, mais effectivement, il y a beaucoup plus simple ).
Donc merci à tous deux pour vos réponses rapides, et encore désolé pour ce mes stupides erreurs!!!
Nick84 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2012, 16h32   #6
r0d
Expert Confirmé Sénior
 
Inscription : août 2004
Messages : 3 665
Détails du profil
Informations personnelles :
Localisation : Belgique

Informations forums :
Inscription : août 2004
Messages : 3 665
Points : 4 421
Points : 4 421
Citation:
Envoyé par Iradrille Voir le message
edit: Heu... il ya que des tab[x][y] = 1 ou 2 dans le code, pas de memset ni de ZeroMemory et pourtant ça me donne 0, les tableaux de int sont initialisés à 0 ? *_*
ça dépend du compilateur et des options de compilation.
r0d est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 06h52.


 
 
 
 
Partenaires

Hébergement Web