Я делаю маленькую игру с астероидами, используя openGL и c ++.
Я столкнулся с проблемой, которую попытаюсь описать сейчас.
У меня есть класс для астероида, который имеет переменные и методы. У него есть метод create, который устанавливает текущую позицию астероида, и метод рисования, который он использует для случайного изменения положения астероида.
Когда я пытаюсь использовать этот астероид в своем основном классе, он работает нормально. Он двигается и делает все, что хотел.
Затем я создал класс для Генератора астероидов, который создает список астероидов, и у меня также есть метод, который инициализирует метод рисования для каждого элемента списка. Но когда я запускаю его, астероид не двигается. Я сделал шаг по моему коду с использованием Visual Studio и обнаружил, что внутри метода рисования астероида значение изменяется правильно, но когда рисование происходит снова, позиция возвращается к исходному значению, поэтому она не двигается , Это может быть связано с дампированием памяти 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();
}
Спасибо.
Проблема в 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
здесь, так что вы получите указатель на фактический пример.
Таким образом, ваш список содержит указатели на фактические экземпляры астероидов, а не копируют экземпляры по значению (что приводит к временным изменениям временного объекта).
Помимо решения вашей проблемы, это экономит время и ресурсы; если вы когда-либо используете список, например, в качестве параметра функции, гораздо быстрее копировать указатели, а не значения. Просто не забудьте использовать ->
вместо .
Это всего лишь предположение, но возможно, что ваш конструктор копирования вашего класса Astroid не работает правильно с OpenGL? Я заметил, что в методе generate вы создаете нового астроида в стеке, вызываете функцию Create () и затем помещаете его в список. В этот момент в списке есть копия созданного астроида, а не точная, которая называется временная. Я лично создал бы кучу астроидов, а затем составил бы список указателей на астроидов. Пока вы помните, чтобы все правильно очистить память, это может помочь. Дайте мне знать, если это было даже близко!
Я думаю, что проблема с этим «для каждого» цикла; похоже, он выполняет итерацию списка по значению, поэтому берется копия каждого астероида в списке, который затем модифицируется в его методе Draw, но эти изменения теряются, потому что это только копия.
Я не совсем уверен, хотя, потому что это нестандартный синтаксис; насколько я вижу, это странное расширение Visual C ++. Стандартный способ записи:
for (Asteroid& asteroid : listAsteroids) {
asteroid.Draw();
}
И потому что это ссылка, изменения должны придерживаться.