views:

317

answers:

4

I'm using pygame to draw a line between two arbitrary points. I also want to append arrows at the end of the lines that face outward in the directions the line is traveling.

It's simple enough to stick an arrow image at the end, but I have no clue how the calculate the degrees of rotation to keep the arrows pointing in the right direction.

+1  A: 

I would have to look up the exact functions to use, but how about making a right triangle where the hypotenuse is the line in question and the legs are axis-aligned, and using some basic trigonometry to calculate the angle of the line based on the lengths of the sides of the triangle? Of course, you will have to special-case lines that are already axis-aligned, but that should be trivial.

Also, this Wikipedia article on slope may give you some ideas.

MattK
This would be the best solution IMO. I might be wrong, but IIRC the formula you want is Angle = arctan(YDiff/XDiff), where Angle controls the rotation of one Arrow, and ((Angle + 180) % 360) controls the rotation of the other arrow.
Sukasa
+1  A: 

We're assuming that 0 degrees means the arrow is pointing to the right, 90 degrees means pointing straight up and 180 degrees means pointing to the left.

There are several ways to do this, the simplest is probably using the atan2 function. if your starting point is (x1,y1) and your end point is (x2,y2) then the angle in degrees of the line between the two is:

import math
deg=math.degrees(math.atan2(y2-y1,x2-x1))

this will you an angle in the range -180 to 180 so you need it from 0 to 360 you have to take care of that your self.

+3  A: 

Here is the complete code to do it. Note that when using pygame, the y co-ordinate is measured from the top, and so we take the negative when using math functions.

import pygame
import math
import random
pygame.init()

screen=pygame.display.set_mode((300,300))
screen.fill((255,255,255))

pos1=random.randrange(300), random.randrange(300)
pos2=random.randrange(300), random.randrange(300)

pygame.draw.line(screen, (0,0,0), pos1, pos2)

arrow=pygame.Surface((50,50))
arrow.fill((255,255,255))
pygame.draw.line(arrow, (0,0,0), (0,0), (25,25))
pygame.draw.line(arrow, (0,0,0), (0,50), (25,25))
arrow.set_colorkey((255,255,255))

angle=math.atan2(-(pos1[1]-pos2[1]), pos1[0]-pos2[0])
##Note that in pygame y=0 represents the top of the screen
##So it is necessary to invert the y coordinate when using math
angle=math.degrees(angle)

def drawAng(angle, pos):
    nar=pygame.transform.rotate(arrow,angle)
    nrect=nar.get_rect(center=pos)
    screen.blit(nar, nrect)

drawAng(angle, pos1)
angle+=180
drawAng(angle, pos2)
pygame.display.flip()
Nikwin
A: 

just to append to the above code, you'd probably want an event loop so it wouldn't quit right away:

...
clock = pygame.time.Clock()
running = True

while (running):
    clock.tick()
tmatth