我正在使用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();
}
谢谢。
答案 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();
}
因为这是一个参考,所以改变应该坚持下去。