变量在对象列表中不会更改

时间:2012-11-28 21:15:32

标签: c++ list class draw

我正在使用openGL和c ++做一些小行星游戏。 我遇到了一个我现在试着描述的问题。

我有一个包含变量和方法的小行星类。它有一个创建方法,用于设置小行星的当前位置,以及一个用于随机改变小行星位置的绘制方法。

当我尝试在我的主类中使用这个小行星时,它工作正常。它移动并完成我想要的一切。

然后我创建了一个用于创建小行星列表的小行星生成器的类,我还有一个方法可以在列表的每个元素上初始化draw方法。但是当我运行它时,小行星不会移动。我使用visual studio对我的代码进行了一步,我发现在小行星的draw方法中,值被正确更改,但是当绘制再次发生时,位置被重置回其原始值,因此它不会移动。它可能与每个方法之后的c ++转储内存有关,所以我相信我搞乱了指针。如果您发现我的错误,我将不胜感激!

我添加了头文件和方法,以显示我如何使用我的小行星生成器。

AsteroidGen.h

#ifndef ASTEROIDGEN_H
#define ASTEROIDGEN_H

#undef UNICODE
#define WIN32_LEAN_AND_MEAN

#include <windows.h>    // for timeGetTime()
#include <mmsystem.h>   // ditto
#include <iostream>     // I/O
#include "model3DS.h"
#include "Camera.h"
#include <glut.h>       // for gluPerspective & gluLookAt
#include <List>
#include "asteroid.h"
#include "position.h"

class AsteroidGen{
    public:
        std::list<Asteroid> listAsteroids;
        void AsteroidGen::generateAsteroid(int amount, int delet);
        void AsteroidGen::DrawAsteroids();
};

#endif // ASTEROIDGEN_H

AsteroidGen.cpp

#include "asteroidgen.h"

void AsteroidGen::generateAsteroid(int amount, int delet){
        if (delet == true)
            listAsteroids.clear();

        for (int i = 0; i < amount; i++)
        {
            Asteroid temp;
            temp.Create();
            listAsteroids.push_front(temp);
        }
}

void AsteroidGen::DrawAsteroids(){
    for each (Asteroid c in listAsteroids){
        c.Draw();  
    }
}

Asteroid.h

#ifndef ASTEROID_H
#define ASTEROID_H

#undef UNICODE
#define WIN32_LEAN_AND_MEAN

#include <windows.h>    // for timeGetTime()
#include <mmsystem.h>   // ditto
#include <iostream>     // I/O
#include "model3DS.h"
#include "Camera.h"
#include "position.h"
#include <glut.h>       // for gluPerspective & gluLookAt
#include <cmath>
#include "textureTGA.h"

class Asteroid{
    public:
    GLuint textureId;
        GLuint list;
        Position pos;
        float incX;
        float incY;
        float asteroidSpeed;
        float radio;
        float rotation;
        bool status;

        void Asteroid::GenSphere();
        void Asteroid::Reset();
        void Asteroid::Draw();
        void Asteroid::Create();
};

#endif // ASTEROID_H

Main.cpp的

初始化一次

asteroidgen.generateAsteroid(1, false);

每帧绘制方法

asteroidgen.DrawAsteroids();

编辑:

void Asteroid::Draw(){
    pos.z += asteroidSpeed;
    pos.y += incY;
    pos.x += incX;
    rotation += 1;

    glPushMatrix();
        glTranslatef(pos.x, pos.y, pos.z);    
        glRotatef(rotation, 1, 1, 1);
        glBindTexture(GL_TEXTURE_2D,textureId);
        glCallList(list);
    glPopMatrix();
}

谢谢。

3 个答案:

答案 0 :(得分:1)

问题是listAsteroids持有小行星,而不是指向小行星的指针。通过将std::list<Asteroid> listAsteroids;更改为std::list<Asteroid*> listAsteroids;而不是Asteroid temp;执行Asteroid* temp = new Asteroid来解决此问题。

你的实际问题是在for循环中引起的。 for each (Asteroid c in listAsteroids)在这里,您将每个Asteroid实例的值按Asteroid c获取,然后更改,并且不会更改实际实例。再次使用Asteroid* c,这样您就可以获得指向实际实例的指针。

这样你的列表包含指向实际的Asteroids实例的指针,而不是按值复制实例(这会导致对临时对象的临时更改)

除了解决问题之外,还可以节省时间和资源;如果你曾经使用列表作为函数中的参数,那么复制指针而不是值会快得多。请记住使用->代替.

答案 1 :(得分:0)

这只是猜测,但您的Astroid类的复制构造函数可能无法与OpenGL一起正常工作?我注意到在generate方法中,您在堆栈上创建一个新的astroid,调用Create()函数然后将其推送到列表中。在那个时间点,列表中有一个创建的astroid副本,而不是那个名为temp的副本。我个人会在堆上创建一个astroid,然后将列表列为指向astroids的指针。只要你记得做所有适当的内存清理,这可能会有所帮助。让我知道这是否真的很接近!

答案 2 :(得分:0)

我认为问题在于“每个”循环;它似乎是按值迭代列表,因此在列表中获取每个小行星的副本,然后在其Draw方法中进行修改,但这些修改会丢失,因为它只是一个副本。

我不完全确定,因为那是非标准语法;据我所知,它是一些奇怪的Visual C ++扩展。标准的写作方式是:

for (Asteroid& asteroid : listAsteroids) {
    asteroid.Draw();
}

因为这是一个参考,所以改变应该坚持下去。