import math import graphics # Siehe https://mcsp.wartburg.edu/zelle/python/graphics/graphics.pdf class Kroete: @classmethod def start(cls): """Initialisierung des Graphikfensters (nur einmal nötig, darum Klassenmethode)""" cls.window = graphics.GraphWin("Sei kein Frosch Du Kröte", 800, 800) cls.window.setCoords(-400,-400,400,400) cls.window.setBackground('black') @classmethod def fertig(cls): """Auf Mausklick warten und Fenster schliessen. Aufruf mit ''Kroete.fertig()''""" cls.window.getMouse() # Pause to view result cls.window.close() del cls.window # Konstruktor, wird beim Erzeugen einer Turtle aufgerufen def __init__(self): """Alle Turtlevariablen werden hier auf Anfangswerte gesetzt.""" if not hasattr(Kroete, 'window'): Kroete.start() self.x = 0 # Startposition x,y self.y = 0 self.r = 100 # Schrittlaenge self.a = 0 # Winkel self.turn = 90 # Drehwinkel self.color = 'white' self.hsvcycle = 0.0 # Wenn grösser Null, wird hue automatisch erhöht und die Farbe entsprechend gesetzt. self.hue = 0.0 self.stack = [] # Liste, um Zustände zu speichern def save(self): """Speichert den aktuellen Zustand (Position, Winkel, etc.)""" self.stack.append({k:v for (k,v) in vars(self).items() if k!='stack'}) def restore(self): """Lädt die zuletzt gespeicherten Werte""" if len(self.stack)>0: for (k,v) in self.stack.pop().items(): setattr(self, k, v) # Destructor, wird beim Programmende aufgerufen (oder wenn man die Turtle manuell löschen würde, nicht ganz sauber bei Verwendung mehrerer Turtles) def __del__(self): if hasattr(Kroete, 'window'): Kroete.fertig() # Turtle vorwärst bewegen, ohne Zeichnen def move(self, r=None): """Turtle in Blickrichtung um Standardlänge r bewegen (oder mit der zusätzlich gegebenen Länge, die dann als Standard gesetzt wird.""" if r!=None: self.r = r bogenmass = self.a/180*math.pi self.x = self.x + self.r*math.cos(bogenmass) self.y = self.y + self.r*math.sin(bogenmass) # Strich zeichnen def forward(self, r=None): """Zeichnet eine Linie in der aktuellen Blickrichtung mit der Standard-Länge r (oder mit der zusätzlich gegebenen Länge, die dann als Standard gesetzt wird.""" a,b = self.x, self.y # Startposition self.move(r) # Bewegen # Linie definieren l = graphics.Line(graphics.Point(a,b), graphics.Point(self.x, self.y)) if self.hsvcycle>0.0: self.hue = (self.hue+self.hsvcycle)%1 self.hsv(self.hue, 1.0, 1.0) l.setOutline(self.color) # Farbe l.draw(Kroete.window) # Zeichnen # Drehung nach rechts def right(self, turn=None): """Drehung nach rechts. Optional kann der Drehwinkel festgelegt werden. Dieser wird dann der Standard-Winkel.""" if turn!=None: self.turn=turn; self.a -= self.turn # Drehung nach links def left(self, turn=None): """Drehung nach links. Optional kann der Drehwinkel festgelegt werden. Dieser wird dann der Standard-Winkel.""" if turn!=None: self.turn=turn; self.a += self.turn def rgb(self, r,g,b): """Farbe aus rgb-Werten (0-255) festlegen.""" self.color = graphics.color_rgb(int(r),int(g),int(b)) def hsv(self, h, s, v): """Farbe auch hsv-Werten (0.0 bis 1.0) festlegen Code von https://stackoverflow.com/questions/24852345/hsv-to-rgb-color-conversion """ def hsv_to_rgb(h, s, v): if s == 0.0: return (v, v, v) i = int(h*6.) # XXX assume int() truncates! f = (h*6.)-i; p,q,t = v*(1.-s), v*(1.-s*f), v*(1.-s*(1.-f)); i%=6 if i == 0: return (v, t, p) if i == 1: return (q, v, p) if i == 2: return (p, v, t) if i == 3: return (p, q, v) if i == 4: return (t, p, v) if i == 5: return (v, p, q) r,g,b = [int(x*255) for x in hsv_to_rgb(h,s,v)] self.rgb(r,g,b)