修正:如何在 pygame、python 和 opengl 中制作移动角色的第三人称?
Fixed: How to make a moving character 3rd person in pygame,python and opengl?
所以最近我开始制作一款 3rd 人称 3d mmorpg 奇幻游戏,但我似乎无法根据时间长度计算出玩家的旋转和移动。那么我必须在我的代码中更改什么才能使角色旋转然后能够在那个方向上同时行走或同时行走。
我的目标是这样的 https://www.youtube.com/watch?v=PoxDDZmctnU and this https://www.youtube.com/watch?v=d-kuzyCkjoQ 我试图将代码转换为 python 但它不起作用,我的播放器到处移动。请帮助我。
这是我的代码:
玩家class
class Player:
def __init__(self, model, engine):
self.model = model
self.engine = engine
self.RUN_SPEED = 0.1
self.TURN_SPEED = 0.6
self.GRAVITY = -0.01
self.JUMP_POWER = 2
self.TERRAIN_HEIGHT = 0
self.currentSpeed = 0
self.currentTurnSpeed = 0
self.upwardsSpeed = 0
self.isInAir = False
self.position = [0,0,0]
self.rotation = [0,0,0]
def move(self):
Yrot = 1.0 * (self.currentTurnSpeed * self.engine.getFrameTimeSeconds())
distance = 1.0 * (self.currentSpeed * self.engine.getFrameTimeSeconds())
self.upwardsSpeed += 1.0 * (self.GRAVITY * self.engine.getFrameTimeSeconds())
dx = 1.0 * (distance * sin(Yrot+self.rotation[1]))
dz = 1.0 * (distance * cos(Yrot+self.rotation[1]))
self.increaseRotation(0,Yrot,0)
self.increasePosition(dx, 0, dz)
dy = 1.0 * (self.upwardsSpeed * self.engine.getFrameTimeSeconds())
self.increasePosition(0, dy, 0)
if self.position[1] < self.TERRAIN_HEIGHT:
self.upwardsSpeed = 0
self.position[1] = 0
self.isInAir = False
def jump(self):
if not self.isInAir:
self.upwardsSpeed = self.JUMP_POWER
self.isInAir = True
def render(self):
self.model.draw(pos=self.position, rotations=self.rotation)
def handleEvents(self, event):
if event.type == KEYDOWN:
if event.key == K_w:
self.currentSpeed = self.RUN_SPEED
elif event.key == K_s:
self.currentSpeed = -self.RUN_SPEED
if event.key == K_a:
self.currentTurnSpeed = self.TURN_SPEED
elif event.key == K_d:
self.currentTurnSpeed = -self.TURN_SPEED
if event.key == K_SPACE:
self.jump()
else:
self.currentSpeed = 0
self.currentTurnSpeed = 0
def increaseRotation(self,dx,dy,dz):
self.rotation = [self.rotation[0]+dx,
self.rotation[1]+dy,
self.rotation[2]+dz]
def increasePosition(self,dx,dy,dz):
self.position = [self.position[0]+dx,
self.position[1]+dy,
self.position[2]+dz]
main.py,可能没有必要,但如果有人需要它来帮助理解我的代码以便能够帮助我;)比抱歉更安全
pygame.init()
class Game:
def __init__(self):
self.Screen = (800,600)
self.Window = glLibWindow(self.Screen,caption="Test",multisample=True)
self.View3D = glLibView3D((0,0,self.Screen[0],self.Screen[1]),65)
self.View3D.set_view()
glEnable(GL_TEXTURE_2D)
### MAP ###
Mesh = []
heightmap = pygame.image.load(os.path.join("../data/map.png")).convert()
for x in xrange(heightmap.get_width()):
xrow = []
for y in xrange(heightmap.get_height()):
color = heightmap.get_at((x,y))
height = color[0]*0.02
xrow.append(height)
Mesh.append(xrow)
self.Map = glLibObjMap(Mesh,texturing=True,normals=GLLIB_VERTEX_NORMALS,heightscalar=20)
self.MapTexture = glLibTexture(pygame.image.load("../data/map_texture.png"))
self.Map.compile()
self.campos = [0,-2,-20]
self.player = Player(load_obj("../data/Player/kat_hood_up.obj"), self)
self.lastFrameTime = self.getCurrentTime()
self.delta = 0
def loop(self):
pygame.event.pump()
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit(); sys.exit()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 4:
self.campos[2] -= 3
if event.button == 5:
self.campos[2] += 3
self.player.handleEvents(event)
self.player.move()
#Clear
self.Window.clear()
glLightfv(GL_LIGHT1, GL_POSITION, (0,-20,0))
#Position the camera
self.View3D.set_view()
glTranslatef(self.campos[0]+self.player.position[0],
self.campos[1]-self.player.position[1],
self.campos[2]+self.player.position[2])
glTranslatef(*self.campos)
glRotatef(180,0,1,0)
self.player.render()
self.Map.draw([0,0,0],[[0,150,0]])
#Flip
self.Window.flip()
currentFrameTime = self.getCurrentTime()
self.delta = (currentFrameTime - self.lastFrameTime)/1000
self.lastFrameTime = currentFrameTime
def getCurrentTime(self):
return float(1000*pygame.time.get_ticks())
def getFrameTimeSeconds(self):
return float(self.delta)
if __name__ == '__main__':
game = Game()
clock = pygame.time.Clock()
while True:
game.loop()
我修好了,我忘了将 self.rotation[1] 转换为弧度
dx = 1.0 * (distance * sin(radians(Yrot+self.rotation[1])))
dz = 1.0 * (distance * cos(radians(Yrot+self.rotation[1])))
所以最近我开始制作一款 3rd 人称 3d mmorpg 奇幻游戏,但我似乎无法根据时间长度计算出玩家的旋转和移动。那么我必须在我的代码中更改什么才能使角色旋转然后能够在那个方向上同时行走或同时行走。
我的目标是这样的 https://www.youtube.com/watch?v=PoxDDZmctnU and this https://www.youtube.com/watch?v=d-kuzyCkjoQ 我试图将代码转换为 python 但它不起作用,我的播放器到处移动。请帮助我。
这是我的代码:
玩家class
class Player:
def __init__(self, model, engine):
self.model = model
self.engine = engine
self.RUN_SPEED = 0.1
self.TURN_SPEED = 0.6
self.GRAVITY = -0.01
self.JUMP_POWER = 2
self.TERRAIN_HEIGHT = 0
self.currentSpeed = 0
self.currentTurnSpeed = 0
self.upwardsSpeed = 0
self.isInAir = False
self.position = [0,0,0]
self.rotation = [0,0,0]
def move(self):
Yrot = 1.0 * (self.currentTurnSpeed * self.engine.getFrameTimeSeconds())
distance = 1.0 * (self.currentSpeed * self.engine.getFrameTimeSeconds())
self.upwardsSpeed += 1.0 * (self.GRAVITY * self.engine.getFrameTimeSeconds())
dx = 1.0 * (distance * sin(Yrot+self.rotation[1]))
dz = 1.0 * (distance * cos(Yrot+self.rotation[1]))
self.increaseRotation(0,Yrot,0)
self.increasePosition(dx, 0, dz)
dy = 1.0 * (self.upwardsSpeed * self.engine.getFrameTimeSeconds())
self.increasePosition(0, dy, 0)
if self.position[1] < self.TERRAIN_HEIGHT:
self.upwardsSpeed = 0
self.position[1] = 0
self.isInAir = False
def jump(self):
if not self.isInAir:
self.upwardsSpeed = self.JUMP_POWER
self.isInAir = True
def render(self):
self.model.draw(pos=self.position, rotations=self.rotation)
def handleEvents(self, event):
if event.type == KEYDOWN:
if event.key == K_w:
self.currentSpeed = self.RUN_SPEED
elif event.key == K_s:
self.currentSpeed = -self.RUN_SPEED
if event.key == K_a:
self.currentTurnSpeed = self.TURN_SPEED
elif event.key == K_d:
self.currentTurnSpeed = -self.TURN_SPEED
if event.key == K_SPACE:
self.jump()
else:
self.currentSpeed = 0
self.currentTurnSpeed = 0
def increaseRotation(self,dx,dy,dz):
self.rotation = [self.rotation[0]+dx,
self.rotation[1]+dy,
self.rotation[2]+dz]
def increasePosition(self,dx,dy,dz):
self.position = [self.position[0]+dx,
self.position[1]+dy,
self.position[2]+dz]
main.py,可能没有必要,但如果有人需要它来帮助理解我的代码以便能够帮助我;)比抱歉更安全
pygame.init()
class Game:
def __init__(self):
self.Screen = (800,600)
self.Window = glLibWindow(self.Screen,caption="Test",multisample=True)
self.View3D = glLibView3D((0,0,self.Screen[0],self.Screen[1]),65)
self.View3D.set_view()
glEnable(GL_TEXTURE_2D)
### MAP ###
Mesh = []
heightmap = pygame.image.load(os.path.join("../data/map.png")).convert()
for x in xrange(heightmap.get_width()):
xrow = []
for y in xrange(heightmap.get_height()):
color = heightmap.get_at((x,y))
height = color[0]*0.02
xrow.append(height)
Mesh.append(xrow)
self.Map = glLibObjMap(Mesh,texturing=True,normals=GLLIB_VERTEX_NORMALS,heightscalar=20)
self.MapTexture = glLibTexture(pygame.image.load("../data/map_texture.png"))
self.Map.compile()
self.campos = [0,-2,-20]
self.player = Player(load_obj("../data/Player/kat_hood_up.obj"), self)
self.lastFrameTime = self.getCurrentTime()
self.delta = 0
def loop(self):
pygame.event.pump()
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit(); sys.exit()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 4:
self.campos[2] -= 3
if event.button == 5:
self.campos[2] += 3
self.player.handleEvents(event)
self.player.move()
#Clear
self.Window.clear()
glLightfv(GL_LIGHT1, GL_POSITION, (0,-20,0))
#Position the camera
self.View3D.set_view()
glTranslatef(self.campos[0]+self.player.position[0],
self.campos[1]-self.player.position[1],
self.campos[2]+self.player.position[2])
glTranslatef(*self.campos)
glRotatef(180,0,1,0)
self.player.render()
self.Map.draw([0,0,0],[[0,150,0]])
#Flip
self.Window.flip()
currentFrameTime = self.getCurrentTime()
self.delta = (currentFrameTime - self.lastFrameTime)/1000
self.lastFrameTime = currentFrameTime
def getCurrentTime(self):
return float(1000*pygame.time.get_ticks())
def getFrameTimeSeconds(self):
return float(self.delta)
if __name__ == '__main__':
game = Game()
clock = pygame.time.Clock()
while True:
game.loop()
我修好了,我忘了将 self.rotation[1] 转换为弧度
dx = 1.0 * (distance * sin(radians(Yrot+self.rotation[1])))
dz = 1.0 * (distance * cos(radians(Yrot+self.rotation[1])))