Помогите с OpenGL ES вершинного пакетирования, C ++, уп - PullRequest
0 голосов
/ 21 февраля 2011

Я экспериментирую с программированием игр и ищу отзывы о моем открытом коде на c ++ для iphone. Я собираюсь представить код, который работает для меня, и обсудить, как я хочу его изменить. То, что я пытаюсь сделать, это сделать все пули моего героя одним вызовом, используя oop для пуль. В приведенном ниже примере используется один вызов отрисовки, но пока нет пуль для пуль.

Вот мое определение движка рендеринга:

class RenderingEngine {
public:
    void Initialize(int width, int height);
    void Render();
    void UpdateAnimation(float timeStep);
    void OnFingerDown(ivec2 location);
private:
    std::vector<Vertex> vertices;
};

Вот методы рендеринга:

void RenderingEngine::Initialize(int width, int height) {
    ...

    glViewport(0, 0, 320, 480);

    glMatrixMode(GL_PROJECTION);

    const float maxX = 2;
    const float maxY = 3;
    glOrthof(-maxX, +maxX, -maxY, +maxY, -1, 1);

    glMatrixMode(GL_MODELVIEW);
}

//here you can see the single draw call
void RenderingEngine::Render() {
    glClearColor(1, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glBindTexture(GL_TEXTURE_2D, m_texture);
    glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].Position.x);
    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].TexCoord.x);
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

/*since all the vertices are only for bullets at this
point, all we need to do is move each vertex up by the
same amount*/
void RenderingEngine::UpdateAnimation(float timeStep) {
    for (int i = 0; i < vertices.size(); ++i) {
        vertices[i].Position.y += timeStep*4.4f;
    }
}

/*I'm using GL_TRIANGLES, so when the user fingers
down I am pushing two triangles(six vertices) onto
the vertices vector. This only happens when the user
taps on the bottom 60 pixels of the screen.*/
void RenderingEngine::OnFingerDown(ivec2 location) {
    if (location.y >= 420) {
        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f - 32*0.0125f,
                                       -2.4f + 32*0.0125f), vec2(0, 1)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f - 32*0.0125f,
                                       -2.4f - 32*0.0125f), vec2(0, 0)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f + 32*0.0125f,
                                       -2.4f + 32*0.0125f), vec2(1, 1)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f - 32*0.0125f,
                                       -2.4f - 32*0.0125f), vec2(0, 0)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f + 32*0.0125f,
                                       -2.4f + 32*0.0125f), vec2(1, 1)));

        vertices.push_back(Vertex(vec2(location.x*0.0125f - 2.0f + 32*0.0125f,
                                       -2.4f - 32*0.0125f), vec2(1, 0)));
}
}

Вершина выглядит так:

struct Vertex {
    Vertex() {}
    Vertex(vec2 position, vec2 texCoord) : Position(position), TexCoord(texCoord) {}
    vec2 Position;
    vec2 TexCoord;
};

Вот упрощенные версии ivec2 и vec2:

template <typename T>
struct Vector2 {
    Vector2() {}
    Vector2(T x, T y) : x(x), y(y) {}
}

typedef Vector2<int> ivec2;
typedef Vector2<float> vec2;

Так что все вышеперечисленное работает для меня, и у меня есть пули, стреляющие из нижней части экрана вверх, когда пользователь касается нижней части экрана. Я хотел бы добавить это к движку рендеринга:

std::vector<HeroBullet> heroBullets;

тогда я бы хотел изменить метод обновления анимации на:

void RenderingEngine1::UpdateAnimation(float timeStep) {
    for (int i = 0; i < heroBullets.size(); ++i) {
       heroBullets[i].UpdateAnimation(timeStep);
    }
}

Я думаю, что это хорошая идея, потому что я не хочу, чтобы все необработанные данные вершин обновлялись и управлялись этим единственным методом UpdateAnimation (). Но скорее я бы хотел, чтобы этот метод UpdateAnimation () вызывал UpdateAnimation () для каждого из моих объектов (сейчас это только пули героев, но в будущем это будут враги, пули врагов и т. Д.)

Итак, мой главный вопрос - как мне создавать экземпляры моих объектов HeroBullet, чтобы эти экземпляры могли получать доступ и изменять свои данные вершин, которые находятся в векторе вершин механизма рендеринга?

А также, я делаю это правильно? Это похоже на обычную установку, которая нужна играм.

1 Ответ

0 голосов
/ 10 февраля 2012

Выглядит нормально, лично я бы добавил несколько переменных для всех этих жестко закодированных поплавков, что сделает код более чистым и упростит настройку позже (и в этом отношении масштабирование, если вы стремитесь к разным размерам дисплея и т. Д.).

Что касается обновления, насколько я могу судить, вы бы добавили дополнительные издержки, выполняя все это отдельно от необработанных данных, однако этого нельзя было бы избежать, и в этом случае вы могли бы также подразделить маркеры на различные подклассы, которыереализовать различные различия, все из которых наследуют общую функцию draw () или переопределяют функцию getVertices () (и, возможно, getTexVertices ()), что позволяет использовать различные реализации.(Это будет означать наличие различных вершин в их соответствующих подклассах, а не в механизме рендеринга, который ИМХО был бы в любом случае более чистым, если бы они в любом случае обновляли их независимо).

...