0

我正在使用 openGL 和 c++ 制作一个小行星游戏。我遇到了一个问题,我现在将尝试描述。

我有一个小行星类,它有变量和方法。它有一个 create 方法来设置小行星的当前位置,还有一个 draw 方法用来随机改变小行星的位置。

当我尝试在我的主课中使用这颗小行星时,它工作正常。它会移动并做我想做的一切。

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

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

小行星生成器

#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();  
    }
}

小行星.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

主文件

初始化一次

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();
}

谢谢你。

4

3 回答 3

1

问题是listAsteroids持有小行星,而不是指向小行星的指针。std::list<Asteroid> listAsteroids;通过更改为std::list<Asteroid*> listAsteroids;and 而不是Asteroid temp;do来修复它Asteroid* temp = new Asteroid

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

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

除了解决您的问题之外,这还可以节省时间和资源;例如,如果您曾经将列表用作函数中的参数,则复制指针比复制值要快得多。只要记住使用->而不是.

于 2012-11-28T22:13:13.993 回答
0

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

于 2012-11-28T21:25:17.627 回答
0

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

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

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

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

于 2012-11-28T21:57:26.540 回答