paralleluniverse12
paralleluniverse12

Reputation: 33

Problems with creating a UI and glRotatef()

I am making a minimal Doom-style FPS game engine using Python, PyGame and Legacy PyOpenGL. I hope that the player will be able to look around in four directions - forward, backwards, left and right - using glRotatef() by pressing the left and right arrow keys.

A few problems have arisen:

  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.

Upvotes: 3

Views: 143

Answers (1)

Rabbid76
Rabbid76

Reputation: 210968

In legacy OpenGL there exists different current matrices. The current matrix which is affected by matrix operations can be chosen by glMatrixMode. Each matrix is organized on a stack. Matrices can be pushed and popped by glPushMatrix/glPopMatrix.

The projection matrix should be placed set to the projection matrix stack, the view and model transformations to the modelview matrix stack:

// 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)

The gun should be placed in a first person view ("in front of you"). The esiest wy to achieve this is to draw the gun in viewspace, this means you've to cancel all the previous transformations to the modelview matrix. The matrix can be replace with the identity matrix by glLoadIdentity.
Save the modelview matrix onto the stack, set the identity matrix, draw the gun and finally restore the modelview matrix.e.g:

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

Upvotes: 3

Related Questions