简体   繁体   中英

Why is this way of finding the angle between two points so inaccurate?

I'm trying to get one sprite to intersect with another using angles. This is the function I've used, found online:

def findAngle(x,y,x2,y2):
    deltaX = x2 - x
    deltaY = y2 - y

    return math.atan2(deltaY,deltaX)

However, this is horribly inaccurate. When the two sprites are at around the same X, they are still usually 100-200 pixels away from eachother.

Here is my entire program for you to run yourself.

import pygame
import math

screen_size = screen_width,screen_height = 700,500
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()

BLACK   = (   0,   0,   0)
WHITE   = ( 255, 255, 255)
RED     = ( 255,   0,   0)
GREEN   = (   0, 255,   0)
BLUE    = (   0,   0, 255)

class Sprite(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)


class Particle(Sprite):
    def __init__(self,x,y,size):
        self.image = pygame.Surface((size,size))
        self.rect = pygame.Rect(x,y,size,size)

        self.angle = 0
        self.speed = 0

    def draw(self):

        self.rect.x -= math.cos(self.angle) * self.speed
        self.rect.y -= math.sin(self.angle) * self.speed
        pygame.draw.circle(screen, BLACK, (self.rect.x,self.rect.y), self.rect.width)

def findAngle(x,y,x2,y2):
    deltaX = x2 - x
    deltaY = y2 - y

    return math.atan2(deltaY,deltaX)

class main:

    p1 = Particle(100,100,16)
    p2 = Particle(600,400,5)

    p2.angle = findAngle(100,100,600,400)
    p2.speed = 2

    done = False
    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    done = True

                if event.key == pygame.K_r:
                        pass

        pygame.display.init()
        screen.fill(WHITE)

        p1.draw()
        p2.draw()

        pygame.display.flip()
        clock.tick(60)
    pygame.display.quit()
    pygame.quit()

You should use cos for the x-coordinate and sin for the y-coordinate. You have it backward in the draw function.

P1 is at 100,100 and stationary P2 is at 600,400 and moving at an angle of ~30 degrees (or more accurately, -120 degrees since you're doing -= instead of +=.
If you swap cos and sin, Every frame, p2 moves -1.715 units in the X direction and -1.02 units in the Y direction. After it has moved 300 units in the Y (which would finish it), it should have moved 500 units in the X, which is what you're looking for.

Simplifying things to take pygame stuff:

import math

def findAngle(x,y,x2,y2):
    return math.atan2(y2-y,x2-x)

x = 600
y = 400
angle = findAngle(100,100,x,y)
dx = 2 * math.cos(angle)
dy = 2 * math.sin(angle)
while x > 100:
    x -= dx
    y -= dy
print "At end, we were at %f,%f"%(x,y)

This prints out: At end, we were at 99.224131,99.534479

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM