【问题标题】:Problems with creating a UI and glRotatef()创建 UI 和 glRotatef() 的问题
【发布时间】:2019-09-17 19:49:14
【问题描述】:

我正在使用 PythonPyGameLegacy PyOpenGL 制作一个最小的 Doom 风格 FPS 游戏引擎。我希望玩家能够通过按左右箭头键使用glRotatef() 向四个方向(向前、向后、向左和向右)环顾。

出现了一些问题:

  1. 一把枪(一个应用了纹理的立方体,它根据玩家面对的方向改变纹理坐标)应该始终出现在相机前方 0.5 个单位的相应 x 和 z 位置,具体取决于角度glRotatef() 将其设置为面向,如果我在 x 轴上移动然后向左看,除非我站在房间的死点中心,否则它会移动到一个奇怪的位置。当我向左和向右移动时,立方体似乎也是静态的,即使我提供了从 glGetDoublev() 获得的 x 值,当我向前移动时,即使我从未实现过这样的功能,枪似乎也在缩放。

  2. 当我打电话时

    if event.type == pygame.KEYDOWN: # key pressed events
                    if event.key == pygame.K_LEFT:
                        glRotatef(-90,0,1,0)
                        if direction == 0:
                            direction = 3
                        else:
                            direction -= 1
    

    看向房间的左侧,我偶尔会在墙内移动,这有时会进一步影响枪的位置。

    我尝试添加固定的 x 和 z 变量(x_stepsz_steps),每次玩家移动时,这些变量都会增加 0.1。我不太确定为什么这会消除“静电枪”问题,但确实如此。然而,当我旋转相机时,同样的问题(枪移动到一个奇怪的位置)仍然发生。

    ## pygame/opengl initialisation code
    def main():
        pygame.init()
        display = (800,600)
        global displaySurface
        displaySurface = pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
        pygame.display.set_caption("Wolfenstein 4D")
        glEnable(GL_TEXTURE_2D)
        glEnable(GL_DEPTH_TEST)
        gluPerspective(45, (display[0]/display[1]),0.1,50.0)
    
    ## game loop, obtaining x,y,z positions and looking around the room
    def room1():
        direction = 3 ## 3 = forward, 2 = left, 1 = backward, 0 = right
        while True:
            pos = glGetDoublev(GL_MODELVIEW_MATRIX)
            x = pos[3][0]
            y = pos[3][1]
            z = pos[3][2]
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    quit()
    
                if event.type == pygame.KEYDOWN: # key pressed events
                    if event.key == pygame.K_LEFT:
                        glRotatef(-90,0,1,0)
                        if direction == 0:
                            direction = 3
                        else:
                            direction -= 1
                        x_steps = 0
                        z_steps = 0
    
                    if event.key == pygame.K_RIGHT:
                        glRotatef(90,0,1,0)
                        if direction == 3:
                            direction = 0
                        else:
                            direction += 1
                        x_steps = 0
                        z_steps = 0
    
    ## movement code
            spd = 0.1
            keys = pygame.key.get_pressed()
            if direction == 3:
                if keys[pygame.K_a]:
                        glTranslatef(spd,0,0)
                        x_steps -= spd
                if keys[pygame.K_d]:
                        glTranslatef(-spd,0,0)
                        x_steps += spd
                if keys[pygame.K_w]:
                        glTranslatef(0,0,spd)
                        z_steps -= spd
                if keys[pygame.K_s]:
                        glTranslatef(0,0,-spd)
                        z_steps += spd
            if direction == 2:
                if keys[pygame.K_a]:
                        glTranslatef(0,0,-spd)
                        x_steps += spd
                if keys[pygame.K_d]:
                        glTranslatef(0,0,spd)
                        x_steps -= spd
                if keys[pygame.K_w]:
                        glTranslatef(spd,0,0)
                        z_steps -= spd
                if keys[pygame.K_s]:
                        glTranslatef(-spd,0,0)
                        z_steps += spd
    
    ## gun drawing code in game loop
                if direction == 3:
                    loadTexture("gun1.png")
                    drawHUDGun(x,-0.1,z-0.5,3,0.1,0.1,0.1)
                if direction == 2:
                    loadTexture("gun.png")
                    drawHUDGun(z-0.5,-0.1,x+0.5,2,0.1,0.1,0.1)
    
    ## gun drawing function
    def drawHUDGun(x,y,z,angle,width,height,depth=0.5,color = ((1,1,1))):
        vertices = (
            (width+x,-height+y,-depth+z),
            (width+x,height+y,-depth+z),
            (-width+x,height+y,-depth+z),
            (-width+x,-height+y,-depth+z),
            (width+x,-height+y,depth+z),
            (width+x,height+y,depth+z),
            (-width+x,-height+y,depth+z),
            (-width+x,height+y,depth+z)
        )
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glBegin(GL_QUADS)
        if angle == 3:
            j = 0
        if angle == 2:
            j = 8
    
        i = 0
        for surface in surfaces:
            i += 1
            for vertex in surface:
                glColor4f(1,1,1,1)
                setTexCoord(0, texCoords, j)
                if angle == 3:
                    if i >= 0 and i < 4:
                        if j < 4:
                            j += 1
                if angle == 2:
                    if i == 2:
                        if j < 12:
                            j += 1
                glVertex3fv(vertices[vertex])
        glEnd()
        glDisable(GL_BLEND)
    
        glBegin(GL_LINES)
        for edge in edges:
            glColor3fv((0,1,0))
            for vertex in edge:
                glVertex3fv(vertices[vertex])
        glEnd()
    
    ## implementation of the functions
    
    main()
    room1()
    

    我希望无论玩家在房间中的哪个方向,枪都会出现在玩家前方 0.5 个单位的位置,但由于分配了不正确的 x 或 z 坐标,枪经常不在视线范围内。

【问题讨论】:

    标签: python opengl pygame pyopengl opengl-compat


    【解决方案1】:

    在旧版 OpenGL 中存在不同的当前矩阵。受矩阵运算影响的当前矩阵可由glMatrixMode 选择。每个矩阵都组织在一个堆栈上。矩阵可以通过glPushMatrix/glPopMatrix进行推送和弹出。

    投影矩阵应该放置设置到投影矩阵堆栈,视图和模型转换到模型视图矩阵堆栈:

    // choose projection matrix stack
    glMatrixMode(GL_PROJECTION)
    gluPerspective(45, (display[0]/display[1]),0.1,50.0)
    
    // choose modelview matrix stack, for the following matrix operations
    glMatrixMode(GL_MODELVIEW)
    

    枪应该放在第一人称视角(“在你面前”)。实现这一点的最简单方法是在视图空间中画枪,这意味着您必须取消之前对模型视图矩阵的所有转换。该矩阵可以用identity matrix 替换为glLoadIdentity
    将模型视图矩阵保存到堆栈中,设置单位矩阵,画枪,最后恢复模型视图矩阵。例如:

    glPushMatrix()
    glLoadIdentity()
    drawHUDGun(x,-0.1,z-0.5,3,0.1,0.1,0.1)
    glPopMatrix()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 2012-08-20
      • 2020-08-29
      • 1970-01-01
      相关资源
      最近更新 更多