我正在使用Python、PyGame和Legacy PyOpenGL制作一个最小的类似Doom的FPS游戏引擎。我希望玩家能够通过按下左右箭头键,使用glRotatef()
向前、向后、向左和向右四个方向查看。
出现了一些问题:
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 fromglGetDoublev()
, and when I move forward the gun appears to be scaling even though I never implemented such functionality.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
andz_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.