问题
I am aware that on the net and also here the question has already been asked, but unfortunately not in the Python environment. Looking on the net, I found this (Link) and from there I started working on it. Since I'm using Pyglet, I wrote the function as a thread. But first, I show you what I thought and wanted to accomplish:
P = Sprite Player Position
M = Mouse Position
C = An imaginary circle, having as its radius the distance between P and M.
0, 1, 2, 3, 4, 5, 6, 7 = Directions that the sprite can have
a = Angle between one direction and another = 45°
S = Section of the circle corresponding to the sprite direction. In simple words, if M is present in S, the direction is equal to 1
start, end = Start Angle and End Angle
So, in the function, I inserted a while loop. Later, I had to calculate when the radius was:
while mpc_thread:
radius = math.hypot(mpx - cpx, mpy - cpy) + 20
mpx, mpy = Mouse position (X, Y)
cpx, cpy = Sprite Player Position (X, Y)
I used math.hypot
thanks to this (Link). I added 20, so that the radius slightly exceeded the position of the mouse.
Then I added a for loop to check the circle section for each direction:
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 = Amount of Sprite directions, in this case 8
To find out the starting and ending angle for each direction, I divided the lap angle by twice the number of directions. Then I subtracted / added the result to the reference angle.
From here on the problems started. Writing in the way I posted the first link, the if function didn't detect anything and if I went in negative (, I got an error. I then searched for a solution and found this (Link) from the answer of user7048690. Modified the function, I got a new problem (math domain error). So I changed math.sqrt
with cmath.sqrt
, and it worked. But a new problem had arisen. That is, always following that answer, the if function drastically reduced FPS to 0/1. Now I don't know where to head. Can you help me with this problem? How should I build the function correctly and work properly? I hope I understood what I meant by my question.
回答1:
The easiest way to find the best direction is to calculate the cosine of the angle between the line from the player position to the mouse position and the line from the player position to the 8 points.
It has to be found that direction vector which has the smallest angle to the "mouse" direction.
The cosine of 0 degrees is 1 and the cosine of 180° is -1. So the direction with the greatest cosine is the direction to be found.
The easiest way to calculate the cosine is the dot product.
In general the dot product of 2 vectors is equal the cosine of the angle between the 2 vectors multiplied by the magnitude (length) of both vectors.
dot( A, B ) == | A | * | B | * cos( angle_A_B )
This follows, that the dot product of 2 unit vectors is equal the cosine of the angle between the 2 vectors, because the length of a unit vector is 1.
uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )
The dot product of 2-dimensional vectors A and B can be calculated by 2 multiplications and 1 addition:
dotAB = Ax * Bx + Ay * By
Set up a list with the 8 normalized directions:
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)]
Find the "best" direction, this is the direction with the closest angle or the greatest cosine of the angle:
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])
Finally max_i
contains the searched direction.
Note the algorithm doesn't calculate and compare the cosine of the angles, it compares product of the cosine and the radius. dx*dir[i][0] + dy*dir[i][1]
is eqault to radius * cos(alpha)
.
The searched point finally is:
radius = math.hypot(mdir_x, mdir_y) + 20
X = (dir[max_i][0] * radius, dir[max_i][1] * radius)
来源:https://stackoverflow.com/questions/55501123/check-whether-a-point-exists-in-circle-sector-or-not-with-python