我知道在网上以及这里都已经提出了这个问题,但不幸的是,在Python环境中却没有。在网上查看时,我发现了这个(Link),然后从那里开始研究它。由于我使用的是Pyglet,因此我将该函数编写为线程。但是首先,我向您展示我的想法和想要实现的目标:
P =精灵播放器位置
M =鼠标位置
C =一个假想的圆,其半径为P和M之间的距离。
0、1、2、3、4、5、6、7 =精灵可以具有的方向
a =一个方向和另一个方向之间的角度= 45°
S =对应于精灵方向的圆的截面。简而言之,如果M存在于S中,则方向等于1
开始,结束=起始角度和终止角度
因此,在函数中,我插入了一个while循环。后来,我不得不计算出半径何时为:
while mpc_thread:
radius = math.hypot(mpx - cpx, mpy - cpy) + 20
mpx,mpy =鼠标位置(X,Y)
cpx,cpy =精灵播放器位置(X,Y)
由于这个(Link),我使用了math.hypot
。我加了20,所以半径稍微超出了鼠标的位置。
然后我添加了一个for循环来检查每个方向的圆形部分:
while mpc_thread:
radius = math.hypot(mpx - cpx, mpy - cpy) + 20
for ang_obj in range(0, fchar):
reference_angle = 360 // fchar * ang_obj
s_angle = reference_angle - (360 / (fchar / 2))
e_angle = reference_angle + (360 / (fchar / 2))
fchar = Sprite方向的数量,在这种情况下为8
要找出每个方向的开始和结束角度,我将重叠角度除以方向数量的两倍。然后我将结果减去/加到参考角度。
从这里开始出现问题。以我发布第一个链接的方式编写,if函数什么也没检测到,并且如果我输入否定(错误)。然后我寻找解决方案,并从答案中找到了这个(Link)修改了函数,出现了一个新问题(数学域错误)。于是我用math.sqrt
更改了cmath.sqrt
,但是它起作用了,但是出现了一个新问题。答案是,if函数将FPS大大降低到0/1。现在我不知道该去哪里了,您能帮我解决这个问题吗?我应该如何正确构建函数并正常工作?我希望我理解我的意思。我的问题。
答案 0 :(得分:2)
找到最佳方向的最简单方法是计算从播放器位置到鼠标位置的直线与从播放器位置到8点的直线之间的角度的余弦值。
必须发现与“鼠标”方向成最小角度的方向矢量。
0度的余弦为1,180°的余弦为-1。因此,余弦最大的方向就是要找到的方向。
最简单的计算余弦的方法是dot product。
通常,两个向量的 dot 乘积等于两个向量之间的角度的 cosine 乘以两个向量的大小(长度)。
dot( A, B ) == | A | * | B | * cos( angle_A_B )
因此,由于一个单位矢量的长度为1,因此两个单位矢量的 dot 乘积等于两个矢量之间的角度的 cosine 。
uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )
二维向量A和B的dot product可以通过2次乘法和1次加法来计算:
dotAB = Ax * Bx + Ay * By
设置具有8个标准化方向的列表:
dir = [(0, 1), (0.707, 0.707), (1, 0), (0.707, -0.707),
(0, -1), (-0.707, -0.707), (-1, 0), (-0.707, 0.707)]
找到“最佳”方向,即最接近该角度或该角度的最大余弦的方向:
dx, dy = mpx - cpx, mpy - cpy
max_i = max([i for i in range(len(dir))], key = lambda i: dx*dir[i][0] + dy*dir[i][1])
最后max_i
包含搜索的方向。
请注意,该算法不会计算和比较角度的余弦,而是会比较余弦和半径的乘积。 dx*dir[i][0] + dy*dir[i][1]
与 radius * cos(alpha)
等价。
最终搜索到的点是:
radius = math.hypot(mdir_x, mdir_y) + 20
X = (dir[max_i][0] * radius, dir[max_i][1] * radius)