创建UI时出现问题和glRotatef()函数

3

我正在使用Python、PyGame和Legacy PyOpenGL制作一个最小的类似Doom的FPS游戏引擎。我希望玩家能够通过按下左右箭头键,使用glRotatef()向前、向后、向左和向右四个方向查看。

出现了一些问题:

  1. A gun (a cube with a texture applied that changes the texture coordinates depending on the direction the player is facing) that should always appear 0.5 units ahead of the camera in the corresponding x and z position depending on the angle glRotatef() sets it to face towards, is moving to a strange position if I move on the x axis and then look left unless I stand dead centre in the room. The cube also appears to be static when I move left and right even though I am supplying it the x value I obtained from glGetDoublev(), and when I move forward the gun appears to be scaling even though I never implemented such functionality.

  2. When I call

    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
    

    to look to the left of the room, I occasionally get moved inside the wall and this sometimes affects the gun's position further.

    I've tried adding fixed x and z variables (x_steps and z_steps) that are incremented by 0.1 every time the player moves. I'm not particularly sure why that removes the "static gun" problem but it did. However, when I rotated the camera, the same problem (of the gun moving to a strange position) still occurred.

    ## 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()
    

    I expect the gun to appear 0.5 units ahead of the player in any direction regardless of where they are in the room, but the gun is often out of view due to being assigned incorrect x or z co-ordinates.

1个回答

3
在传统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)

枪械应该放在第一人称视角(“在你面前”)。最简单的方法是在视图空间内绘制枪械,这意味着您必须取消所有以前对模型视图矩阵的转换。矩阵可以通过单位矩阵替换,并使用glLoadIdentity命令实现。
将模型视图矩阵保存到堆栈中,设置单位矩阵,绘制枪械,最后恢复模型视图矩阵。例如:
glPushMatrix()
glLoadIdentity()
drawHUDGun(x,-0.1,z-0.5,3,0.1,0.1,0.1)
glPopMatrix()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接