用opengl随机移动小行星

Posted

技术标签:

【中文标题】用opengl随机移动小行星【英文标题】:Moving asteriods randomly with opengl 【发布时间】:2019-02-04 17:00:45 【问题描述】:

我正在尝试以随机方式移动小行星。我传入一个星体向量作为参数,在方法开始时清除屏幕以防止在屏幕上多次绘制星体,就像这样:

但是,通过我编写的代码,所有小行星都朝着同一个方向移动。我需要让它随机运动,请帮忙。 以下是我的代码:

void Entity::move(GLFWwindow * window, vector<Entity> allAsteriods, Entity &sp ) 

    DrawEntity de = DrawEntity();

    while (!glfwWindowShouldClose(window)) 

        glClear(GL_COLOR_BUFFER_BIT);   

        for (int i = 0; i < allAsteriods.size(); i++) 

            glLoadIdentity();
            glMatrixMode(GL_MODELVIEW);

            float x = allAsteriods[i].return_PositionVector().back().get_X();
            float y = allAsteriods[i].return_PositionVector().back().get_Y();

            glPushMatrix();
            glTranslatef(x, y, 0.0); // 3. Translate to the object's position.

            de.drawEntity(allAsteriods[i]);

            float additionalX = GenerateRandom(0.10, 0.90);
            float additionalY   = GenerateRandom(0.10, 0.90);

            allAsteriods[i].addTo_PositionVector(x + additionalX, y + additionalY);       
            glPopMatrix();      
        
        de.drawEntity(sp);

        // Swap front and back buffers
        glfwSwapBuffers(window);

        // Poll for and process events
        glfwPollEvents();
    

【问题讨论】:

您必须检查您生成的 PositionVector。它们似乎被初始化为相同的值。 GenerateRandom 是做什么的? 是的,positionVector被初始化为相同的值> GenerateRandom 生成一个介于 0.10 - 0.90 之间的随机数。 【参考方案1】:

您正在为每一帧的小行星添加一个随机位置(您可以看到它们在屏幕下方移动时是如何摇晃的)。你的随机位置在 X 和 Y 上都只有 0.1 到 0.9,所以它们只会向屏幕的左下方移动。

要解决此问题,您需要执行以下操作:

在您的实体类中,您需要存储一个与位置分开的Velocity 向量。

当你第一次初始化你的小行星实体时,你需要为它们随机分配一个速度,但是你需要为 X 和 Y 选择一个从 -1 到 1 的速度

allAsteroids[i].velocity.x = GenerateRandom(-1.0, 1.0)
allAsteroids[i].velocity.y = GenerateRandom(-1.0, 1.0) 
在您的主游戏循环中,您必须将速度添加到每一帧的位置:
//Not sure why you're doing it like this - it should be easy to get X and Y from vectors, but I'll do it the same way:

float velX = allAsteriods[i].return_VelocityVector().back().get_X();
float velY = allAsteriods[i].return_VelocityVector().back().get_Y();

allAsteriods[i].addTo_PositionVector(x + velX, y + velY);

还有,你的

 glLoadIdentity();
 glMatrixMode(GL_MODELVIEW);

不应该在所有小行星的循环内。这应该在游戏循环的顶部每帧只执行一次。您的每小行星循环应该以 glPushMatrix() 开头并以 glPopMatrix() 结尾

【讨论】:

谢谢,我相应地更改了代码,小行星确实随机移动,但是,即使 allAsteriod 矢量中有 3 个项目,屏幕上也只有一个小行星被绘制。这非常重要,因为我还有 glClear(GL_COLOR_BUFFER_BIT);在循环 allAsteriods 之前。如果没有 glClear(GL_COLOR_BUFFER_BIT) 部分,屏幕上会在它移动的位置绘制一大块小行星,而不是像我在这篇文章中发布的屏幕截图那样在屏幕上移动一颗小行星。有什么办法可以解决吗? @LimTing 这可能有很多不同的原因。 1)您的位置都被初始化为相同的 X,Y 坐标。 2) 您的 init 函数为所有 3 颗小行星分配了相同的速度。不看整个代码很难判断。 啊...我一直在尝试在没有 glClear 方法的情况下移动对象,但我没有成功... 用于初始化allAsteriod向量的代码是vector&lt;Entity&gt; Entity::initAsteriodVector() Entity e = Entity(); vector&lt;Entity&gt; allEntity = vector&lt;Entity&gt;(); vector&lt;Vector2D&gt; pos1 Vector2D(500, 250) ; Entity a = Entity(pos1, pos1, 0, "asteriod"); allEntity.push_back(a); vector&lt;Vector2D&gt; pos2 Vector2D(360, 400) ; Entity a2 = Entity(pos2, pos2, 0, "asteriod"); allEntity.push_back(a2); vector&lt;Vector2D&gt; pos3 Vector2D(60, 50) ; Entity a3 = Entity(pos3, pos3, 0, "asteriod"); allEntity.push_back(a3); return allEntity; draw方法中的代码为:void DrawGame::draw(GLFWwindow* window, vector&lt;Entity&gt; drawAllEntity) DrawEntity de = DrawEntity(); vector&lt;Vector2D&gt; pos = vector&lt;Vector2D&gt;(); pos.push_back(Vector2D(820, 460)); Entity e = Entity(pos, pos, 0, "spaceship"); de.drawEntity(e); for (int i = 0; i &lt; drawAllEntity.size(); i++) float Velocity_x = e.GenerateRandom(-1.0, 1.0); float Velocity_y = e.GenerateRandom(-1.0, 1.0); drawAllEntity[i].addTo_velocityVector(Velocity_x, Velocity_y); drawAllEntity[i].move(window, drawAllEntity, e);

以上是关于用opengl随机移动小行星的主要内容,如果未能解决你的问题,请参考以下文章

在OpenGL中为行星绘制轨道试验[关闭]

OpenGL片段着色器不照亮场景

OpenGL 在进行自旋转时围绕对象旋转

OpenGL 的旋转和光照问题

用OpenGL实现粒子的随机运动

一个主 OpenGL 程序中的多个着色器