import pygame import math class Compass(): def __init__(self, font_size, size): pygame.font.init() self.textColor = pygame.Color("white") self.backgroundColor = pygame.Color("White") self.needleColor = pygame.Color("black") self.font = pygame.font.Font(pygame.font.get_default_font(), font_size) self.surface = pygame.Surface(size, pygame.SRCALPHA) self.size = size self.x = 0 self.y = 0 self.backgroundSurface = None def setX(self, x): self.x = x def getX(self): return self.x def setY(self, y): self.y = y def getY(self): return self.y def get(self): return self.surface def setTextColor(self, color): try: self.textColor = pygame.Color(color) except: self.textColor = pygame.Color("black") def setBackgroundColor(self, color): try: self.backgroundColor = pygame.Color(color) except: self.backgroundColor = pygame.Color("white") def setNeedleColor(self, color): try: self.needleColor = pygame.Color(color) except: self.needleColor = pygame.Color("black") def update(self, value): raise NotImplementedError() class MiddleNeedle(Compass): def update(self, value): radius = min(self.size[0]//2, self.size[1]//2) pygame.draw.circle( self.surface, self.backgroundColor, (self.size[0]//2, self.size[1]//2), radius) arrow = pygame.Surface( ((self.size[0]//100*60)//2, self.size[1]//100*60), pygame.SRCALPHA ) polygon_list = [ ( arrow.get_width()//2, 0 ), #Middle top ( 0, arrow.get_height() ), #bottom left ( arrow.get_width()//2, (arrow.get_height()-arrow.get_height()//100*30) ), #middle pos ( arrow.get_width(), arrow.get_height() ), #bottom right ] pygame.draw.polygon(arrow, self.needleColor, polygon_list) arrow = pygame.transform.rotate( arrow, value ) self.surface.blit( arrow, ( (self.size[0]//2)-(arrow.get_width()//2), (self.size[1]//2)-(arrow.get_height()//2))) text = self.font.render("N", True, self.textColor) self.surface.blit( text, ( (self.size[0]//2) - (text.get_width()//2), int(self.size[1]/100*10) - text.get_height()//2 ) ) text = self.font.render("W", True, self.textColor) self.surface.blit( text, ( int(self.size[0]/100*10) - (text.get_width()//2), (self.size[1]//2) - (text.get_height()//2) ) ) text = self.font.render("O", True, self.textColor) self.surface.blit( text, ( int(self.size[0]/100*90)- (text.get_width()//2), (self.size[1]//2) - (text.get_height()//2) ) ) text = self.font.render("S", True, self.textColor) self.surface.blit( text, ( (self.size[0]//2) - (text.get_width()//2), int(self.size[1]/100*90) - text.get_height()//2 ) ) class OuterNeedle(Compass): def update(self, value): radius = min(self.size[0]//2, self.size[1]//2) pygame.draw.circle( self.surface, self.backgroundColor, (self.size[0]//2, self.size[1]//2), radius) if self.backgroundSurface: self.surface.blit( self.backgroundSurface, (0,0) ) if self.lineLength is None: self.lineLength = 5 # 0 is down -> +90 # alpha = 2 * arcsin (s / 2r); s is bottom line alpha = 2 * math.asin( self.lineLength / (2*radius) ) value = math.radians(value) + math.pi/2 #put 0 to bottom bottom_left = self.getPos(value +alpha/2, radius) bottom_left = ( int(bottom_left[0] + radius), bottom_left[1]+radius) #offset to screen middle bottom_right = self.getPos(value -alpha/2, radius) bottom_right = ( int(bottom_right[0] + radius), bottom_right[1]+radius) height_of_segment = self.lineLength/2 * math.tan( alpha / 4 ) height_of_triangle = math.sqrt(3) /2 * self.lineLength top = self.getPos(value, radius-height_of_segment-height_of_triangle) top = ( int(top[0] + radius), top[1]+radius ) points = [ bottom_left, top, bottom_right ] pygame.draw.lines( self.surface, self.needleColor, False, points,3) text = self.font.render("N", True, self.textColor) self.surface.blit( text, ( (self.size[0]//2) - (text.get_width()//2), int(self.size[1]/100*10) - text.get_height()//2 ) ) text = self.font.render("W", True, self.textColor) self.surface.blit( text, ( int(self.size[0]/100*10) - (text.get_width()//2), (self.size[1]//2) - (text.get_height()//2) ) ) text = self.font.render("O", True, self.textColor) self.surface.blit( text, ( int(self.size[0]/100*90)- (text.get_width()//2), (self.size[1]//2) - (text.get_height()//2) ) ) text = self.font.render("S", True, self.textColor) self.surface.blit( text, ( (self.size[0]//2) - (text.get_width()//2), int(self.size[1]/100*90) - text.get_height()//2 ) ) def getPos(self, alpha, radius): return ( int( radius * math.cos(alpha) ), int( radius * math.sin(alpha) ) ) def setLineLength(self, length): self.lineLength = length def setBackgroundSurface(self, surface): self.backgroundSurface = surface