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.
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()
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.
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.
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()