以下是我到目前为止的情况。此刻,玩家移动,我现在想要做的就是始终面向鼠标光标(想想热线迈阿密或其他自上而下的游戏)。我已经使用了一些我在网上找到的涉及atan2的代码,但我几乎不明白它的作用(找到播放器和鼠标之间的距离......)而且我的角色在屏幕外疯狂旋转直到我得到'内存不足'错误。任何帮助都会非常感激,我在互联网上看了一遍,找不到任何可以帮助我的东西。
import pygame, sys, math
from pygame.locals import *
pygame.init()
#setup the window with a 720p resolution and a title
winX, winY = 1280, 720
display = pygame.display.set_mode((winX, winY))
winTitle = pygame.display.set_caption("Game name")
#Colours
cBlack = (0, 0, 0)
#setup the clock and FPS limit
FPS = 70
clock = pygame.time.Clock()
#sprite groups
allSprites = pygame.sprite.Group()
#background image
bg = pygame.image.load("bg.jpg")
class Player(pygame.sprite.Sprite):
def __init__(self, speed):
#import the __init__ from the Sprite class
pygame.sprite.Sprite.__init__(self)
#sets the objects speed to the speed argument
self.speed = speed
#set the soldiers image
self.image = pygame.image.load("soldier_torso_DW.png")
#get the rectangle of the image (used for movement later)
self.rect = self.image.get_rect()
#sets starting position
self.rect.x, self.rect.y = winX/2, winY/2
def checkPlayerMovement(self):
"""Check if user has pressed any movement buttons
and sets the characters position accordingly."""
pressed = pygame.key.get_pressed()
if pressed[K_w]:
self.rect.y -= self.speed
if pressed[K_s]:
self.rect.y += self.speed
if pressed[K_a]:
self.rect.x -= self.speed
if pressed[K_d]:
self.rect.x += self.speed
def checkMouseMovement(self):
"""Check if user has moved the mouse and rotates the
character accordingly."""
mX, mY = pygame.mouse.get_pos()
angleRad = math.atan2(mY, mX) - math.atan2(self.rect.y, self.rect.x)
angleDeg = math.degrees(angleRad)
print angleDeg
self.image = pygame.transform.rotate(self.image, angleDeg)
def update(self):
"""Performs all movement and drawing functions and shit
for the object"""
self.checkPlayerMovement()
self.checkMouseMovement()
#draw the image at the given coordinate
display.blit(self.image, (self.rect.x, self.rect.y))
def updateAll():
#fill the window with black
display.blit(bg, (0, 0))
#update all sprites
allSprites.update()
#keeps FPS at 60
clock.tick(FPS)
#updates the display
pygame.display.flip()
#creates a player with a speed of 5
mainChar = Player(5)
#add the player character to main sprite group
allSprites.add(mainChar)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
updateAll()
答案 0 :(得分:4)
(完全披露,我不熟悉pygame包,但我用其他语言做过这种编程)
当你希望玩家确定它应该旋转多少面对一个物体时,玩家应该认为自己是世界中心。但是,它的坐标并不总是(0,0)
。我们首先需要通过从想要面对的对象中减去玩家的位置,将我们的坐标转换为自我中心坐标。
接下来,看起来你只是使用玩家的位置来计算旋转。除非玩家总是面向等于从当前位置到原点的矢量方向的方向,否则这不是正确的计算。您必须包含其他信息以跟踪玩家的旋转,这通常通过带有(x,y)组件的单位方向向量来完成。
atan2函数将从正X轴给出签名旋转。
因此,给定笛卡尔XY平面和位置(x,y),如果从(0,0)到(x,y)绘制一个向量,那么atan2(y,x)将给出两者之间的角度向量(1,0)和(x,y)。例如,如果你的(x,y)是(0,1)(沿着y轴),那么atan2(1,0)将给你π/ 2或90°,如果你的(x,y)去了沿负y轴(0,-1),然后atan2(0,-1)将给你-π/ 2,或-90°。
atan2的正角度输出始终为逆时针旋转,负角度为顺时针旋转。大多数计算器确实需要atan2(y,x)形式,但不是全部,所以要小心。 In Python's math library, it is atan2(y, x)
原谅不规模,糟糕的颜色选择,幼儿园质量图片,并尝试专注于概念。
位置(5,5)处的对象 位置(-3,-1)的球员。 球员面向方向(-0.8,0.6)
atan2(V rel )= atan2(6,8)= 0.9272952180016122 rad
所以玩家必须围绕自己的中心(顺时针近90度)旋转-1.57 rad才能面对物体。
答案 1 :(得分:2)
您正在计算屏幕和鼠标之间的角度与精灵与其位置之间的角度之间的差异。那不是你想要的。
我建议:
angleRad = math.atan2(self.rect.y-mY, mX-self.rect.x) # y is reversed due to top-left coordinate system
这是精灵应该看鼠标指针的绝对角度。
但是,你可能还有第二个问题:你在每一步都按这个角度旋转精灵。但是你应该只通过精灵的当前方向和所需的方向之间的差异来旋转(如果精灵是90度,你希望它面向90度,那么你就不应该旋转它。)
您应该保留前一个角度,以便仅通过差异旋转(但每次旋转可能会稍微改变精灵),或保持精灵的非旋转副本每次旋转这个角度:
self.image = pygame.transform.rotate(self.unrotated_image, angleDeg)