OpenGL перерисовывает объект, как только игрок достигает цели - PullRequest
0 голосов
/ 31 марта 2020

Я работаю над простой игрой в 3D лабиринт, в которой сам лабиринт автоматически генерируется при каждом запуске. То, что у меня есть до сих пор - это лабиринт, который отличается с каждым пробегом, персонаж, который может двигаться, и как только он достигает цели (сталкивается с точной позицией), я распечатываю «win».

Что я хотел бы сделать сейчас: Я бы хотел воссоздать лабиринт тем же способом, который я делал ранее, и распечатать этот новый лабиринт на экране, чтобы позволить игроку повторить на другой карте. Я начал писать оператор if: если игрок находится на выигрышной позиции, я должен удалить буфер и массив вершин, а затем создать новый и снова заполнить его данными ..? но нет .. я в значительной степени застрял здесь, и я был бы так рад за вашу помощь! Я был бы счастлив, если бы кто-то мог показать мне работоспособное решение по этому вопросу. Ниже показаны некоторые фрагменты кода.

Здесь я проверяю, находится ли игрок на цели:

static void MoveCharacter(Cube& character, Keyboard keyboard, std::vector<Cube> maze)
{
        //... key handling...
        if (keyboard.getKey(GLFW_KEY_LEFT))
        {
            //...
        }
        if (character.position.x >= MazeHeight - 1.0f && character.position.z >= MazeWidth - 1.0f)
        {
            std::cout << "YOU WIN" << std::endl;
            win = true;
            //reached the goal
        }

}

Я показываю вам некоторые части моего основного кода:

int main(void)
{
    // some settings here...

    // Cube vertices
    static const GLfloat g_vertex_buffer_data[] = {
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, 1.0f,
        //...and so on
    };

    // Import the shader files
    Shader cube("shaders/cube.vert", "shaders/cube.frag");
    Shader lightShader("shaders/light.vert", "shaders/light.frag");

    // Create the VBO and VAO for the cubes
    GLuint VBO, vao;
    glGenVertexArrays(1, &vao);
    glGenBuffers(1, &VBO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
    glBindVertexArray(vao);

    // Position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void*)0); // stride: byte offset between consecutive generic vertex attributes, offset init: 0
    glEnableVertexAttribArray(0);

    // Normal attribute
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    ///////////////////////
    // Then, we set the light's VAO (VBO stays the same. After all, the vertices are the same for the light object (also a 3D cube))
    GLuint lightVAO;
    glGenVertexArrays(1, &lightVAO);
    glBindVertexArray(lightVAO);
    // We only need to bind to the VBO (to link it with glVertexAttribPointer), no need to fill it; the VBO's data already contains all we need.
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    // Set the vertex attributes (only position data for the lamp))
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); // Note that we skip over the normal vectors
    glEnableVertexAttribArray(0);
    glBindVertexArray(0);
    ///////////////////////

    // Creating the character
    Cube character = { glm::vec3(0, 1.1, 0), glm::vec3(0.2f) }; //position (0,0,0 is the START)

    // Creating the maze
    std::vector<Cube> ground;
    createGround(ground);
    std::vector<glm::vec3> initMaze = GenerateMaze();
    std::vector<Cube> maze = PutTheWalls(initMaze);
    ground.reserve(ground.size() + maze.size()); //allocate places for the walls 
    ground.insert(ground.end(), maze.begin(), maze.end()); // put all together (walls + ground)

    // Set projection
    glm::mat4 projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 150.0f);

    while (!glfwWindowShouldClose(window)) {

        // Calculate delta time of the current frame
        float currentFrame = glfwGetTime();
        delta = currentFrame - lastFrame;
        lastFrame = currentFrame;

        glfwPollEvents();

        // Movements
        MoveCamera(camera, keyboard, delta);
        MoveCharacter(character, keyboard, maze);

       if (win == true)
        {
            glDeleteVertexArrays(1, &vao);
            glDeleteBuffers(1, &VBO);

            // I don't know how to go on with this one. Here I should handle the recreation of the maze or shouldn't I? This is a complete mess in my head now.

        }

        // Clear the colorbuffer
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        camera.update();

        // Use the CUBE shader and set uniform objects
        cube.use();
        glBindVertexArray(vao);

        glUniform3f(glGetUniformLocation(cube.program, "lightPos"), character.position.x, character.position.y, character.position.z);
        glUniform3f(glGetUniformLocation(cube.program, "viewPos"), ((GLfloat)MazeWidth / 2), ((GLfloat)MazeWidth * 2), ((GLfloat)MazeWidth / 2));
        glUniform3f(glGetUniformLocation(cube.program, "lightColor"), 0.1f, 0.1f, 0.1f); //1.0 világos, 0.1 sötét
        glUniform3f(glGetUniformLocation(cube.program, "objectColor"), 0.1f, 0.9f, 0.9f); //color of the walls

        glUniformMatrix4fv(glGetUniformLocation(cube.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
        glUniformMatrix4fv(glGetUniformLocation(cube.program, "view"), 1, GL_FALSE, glm::value_ptr(camera.matrix()));

        for (unsigned i = 0; i < ground.size(); i++) {
            glm::mat4 model;
            model = glm::translate(model, ground[i].position);
            model = glm::scale(model, ground[i].size);
            glUniformMatrix4fv(glGetUniformLocation(cube.program, "model"), 1, GL_FALSE, glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
        }

        // Use the shader and set uniform objects
        lightShader.use();

        glUniformMatrix4fv(glGetUniformLocation(lightShader.program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
        glUniformMatrix4fv(glGetUniformLocation(lightShader.program, "view"), 1, GL_FALSE, glm::value_ptr(camera.matrix()));

        glm::mat4 model;
        model = glm::translate(model, character.position);
        model = glm::scale(model, character.size);
        glUniformMatrix4fv(glGetUniformLocation(lightShader.program, "model"), 1, GL_FALSE, glm::value_ptr(model));

        glDrawArrays(GL_TRIANGLES, 0, 12 * 3);
        glBindVertexArray(0);

        glfwSwapBuffers(window);
    }

    glUseProgram(0);

    glDeleteVertexArrays(1, &vao);
    glDeleteVertexArrays(1, &lightVAO);
    glDeleteBuffers(1, &VBO);

    glfwTerminate();

    return EXIT_SUCCESS;
}

1 Ответ

1 голос
/ 31 марта 2020

Как я вижу, то, что вы визуализируете, на самом деле хранится в массиве ground, а данные, используемые для перемещения, находятся в maze. Сброс, например:

ground.clear();
createGround(ground);
std::vector<glm::vec3> initMaze = GenerateMaze();
maze = PutTheWalls(initMaze);
ground.reserve(ground.size() + maze.size()); ground.insert(ground.end(), maze.begin(), maze.end());

Убедитесь, что используются фактические переменные, а не копии =) (например, ваш MoveCharacter получает копию maze каждый раз, когда он вызывается; рассмотрите возможность передачи по ссылке [const] ).

...