Hier werden die Unterschiede zwischen zwei Versionen gezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
ws2425:lebewesenverhalten [2025/03/12 17:52] R.Arndt |
ws2425:lebewesenverhalten [2025/05/05 19:41] (aktuell) stefanborn [Unser Code:] |
||
---|---|---|---|
Zeile 122: | Zeile 122: | ||
Beim nächsten Mal würden wir uns von Anfang an etwas weniger vornehmen und versuchen auf die perfekten Bewegungsverhalten eher zu verzichten und zumindest zum Anfang eher auf gröbere Bewegung zu setzen. Die Arbeitsweise mit der Cloud und den wöchentlichen Dokumentationen war aber sehr gut und hat gut geklappt. | Beim nächsten Mal würden wir uns von Anfang an etwas weniger vornehmen und versuchen auf die perfekten Bewegungsverhalten eher zu verzichten und zumindest zum Anfang eher auf gröbere Bewegung zu setzen. Die Arbeitsweise mit der Cloud und den wöchentlichen Dokumentationen war aber sehr gut und hat gut geklappt. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ====Unser Code:==== | ||
+ | |||
+ | <code python>import tkinter as tk | ||
+ | import random as r | ||
+ | import math as m | ||
+ | import numba | ||
+ | import matplotlib.pyplot as plt | ||
+ | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg | ||
+ | |||
+ | fenster = tk.Tk() | ||
+ | fenster.title("Lebewesenverhalten") | ||
+ | |||
+ | """ | ||
+ | fenster.attributes("-fullscreen", True) | ||
+ | def beenden(event=None): | ||
+ | fenster.attributes("-fullscreen", False) | ||
+ | exit() | ||
+ | fenster.bind("<Escape>", beenden) | ||
+ | |||
+ | width = fenster.winfo_screenwidth() | ||
+ | hight = fenster.winfo_screenheight() | ||
+ | """ | ||
+ | |||
+ | fenster.geometry("1000x600") | ||
+ | |||
+ | width = 1000 | ||
+ | hight = 600 | ||
+ | |||
+ | |||
+ | canvas = tk.Canvas(fenster, bg="pink") | ||
+ | canvas.pack(fill="both",expand=True) | ||
+ | |||
+ | def end_simulation(event): | ||
+ | fenster.destroy() | ||
+ | fenste = tk.Tk() | ||
+ | fenste.title("Statistik") | ||
+ | fenste.geometry("1000x600") | ||
+ | fig, ax = plt.subplots(figsize=(6,4)) | ||
+ | ax.plot(x_werte, plant_values) | ||
+ | ax.plot(x_werte, meat_values) | ||
+ | canvas = FigureCanvasTkAgg(fig, master=fenste) | ||
+ | canvas.draw() | ||
+ | canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True) | ||
+ | |||
+ | fenster.bind("<Return>", end_simulation) | ||
+ | |||
+ | start_pflanzenfresser = 50 | ||
+ | start_fleischfresser = 5 | ||
+ | anzahl_seen = 1 | ||
+ | lines = [] | ||
+ | dis = 100 | ||
+ | time = 0 | ||
+ | pflanzenfresser = [] | ||
+ | new_pflanzenfresser = [] | ||
+ | fleischfresser = [] | ||
+ | new_fleischfresser = [] | ||
+ | seen = [] | ||
+ | x_werte = [] | ||
+ | plant_values = [] | ||
+ | meat_values = [] | ||
+ | |||
+ | def update(event = None): | ||
+ | global time | ||
+ | if time % 50 == 0: | ||
+ | x_werte.append(time) | ||
+ | plant_values.append(len(pflanzenfresser)) | ||
+ | for tier in pflanzenfresser: | ||
+ | if not tier.alive: | ||
+ | plant_values[-1] -= 1 | ||
+ | meat_values.append(len(fleischfresser)) | ||
+ | for tier in fleischfresser: | ||
+ | if not tier.alive: | ||
+ | meat_values[-1] -= 1 | ||
+ | #for z in range(len(lines)): | ||
+ | # canvas.delete(lines[z]) | ||
+ | global new_pflanzenfresser | ||
+ | global new_fleischfresser | ||
+ | for baby in new_pflanzenfresser: | ||
+ | pflanzenfresser.append(baby) | ||
+ | baby.show() | ||
+ | new_pflanzenfresser = [] | ||
+ | for baby in new_fleischfresser: | ||
+ | fleischfresser.append(baby) | ||
+ | baby.show() | ||
+ | new_fleischfresser = [] | ||
+ | |||
+ | for pflanzenfresse in pflanzenfresser: | ||
+ | if pflanzenfresse.alive: | ||
+ | if time % 5 == 2: | ||
+ | pflanzenfresse.sight() | ||
+ | pflanzenfresse.check_grazing() | ||
+ | pflanzenfresse.change_food(-5*pflanzenfresse.speed) | ||
+ | if pflanzenfresse.mating_cooldown > 0: | ||
+ | pflanzenfresse.mating_cooldown -= 5 | ||
+ | pflanzenfresse.move() | ||
+ | |||
+ | for fleischfresse in fleischfresser: | ||
+ | if fleischfresse.alive: | ||
+ | if time % 5 == 0: | ||
+ | fleischfresse.sight() | ||
+ | fleischfresse.change_food(-5*fleischfresse.speed) | ||
+ | if fleischfresse.mating_cooldown > 0: | ||
+ | fleischfresse.mating_cooldown -= 5 | ||
+ | fleischfresse.move() | ||
+ | time += 1 | ||
+ | #fenster.bind("<space>", update) | ||
+ | canvas.after(20, update) | ||
+ | |||
+ | def det(alpha, beta): | ||
+ | return m.sin(m.radians(beta-alpha)) | ||
+ | |||
+ | #Distanz zwischen zwei Punkten | ||
+ | def distance(x1, x2, y1, y2): | ||
+ | return m.sqrt((x1 - x2)**2 + (y1 - y2)**2) | ||
+ | |||
+ | #Quadrat des Abstandes zweier Punkte (für schnelle Berechnungen) | ||
+ | def squared_distance(x1, x2, y1, y2): | ||
+ | return (x1 - x2)**2 + (y1 - y2)**2 | ||
+ | |||
+ | class Objekt: | ||
+ | def __init__(self, x, y): | ||
+ | self.x = x | ||
+ | self.y = y | ||
+ | |||
+ | class Tiere(Objekt): | ||
+ | def __init__(self, x, y , direction, health = 1000, food = 10000, a = 40, b = 180, color = "black", status = "wandering"): | ||
+ | #Eigenschaften | ||
+ | super().__init__(x, y) | ||
+ | self.direction = direction | ||
+ | self.direction_offset = 0 | ||
+ | self.health = health | ||
+ | self.food = food | ||
+ | self.color = color | ||
+ | self.mating_cooldown = 0 | ||
+ | #Sicht | ||
+ | self.sichtweite = a | ||
+ | self.sichtkegelwinkel = b | ||
+ | #Eigenschaften, von denen das Handeln abhängt | ||
+ | self.alive = True | ||
+ | self.status = "wandering" | ||
+ | self.threat = None | ||
+ | self.target = None | ||
+ | self.avoiding = None | ||
+ | |||
+ | def change_food(self, change): | ||
+ | if self.food > 0 or change > 0: | ||
+ | self.food += change | ||
+ | elif self.food <= 0: | ||
+ | self.change_health(-10) | ||
+ | |||
+ | #tiere verlieren teile ihrer Gesundheit | ||
+ | def change_health(self, change): | ||
+ | self.health += change | ||
+ | if self.health <= 0: | ||
+ | self.die() | ||
+ | |||
+ | #Änderung der Richtung | ||
+ | def change_direction(self, type, change): | ||
+ | if type == "set": | ||
+ | self.direction = change | ||
+ | elif type == "add": | ||
+ | self.direction += change | ||
+ | self.direction %= 360 | ||
+ | |||
+ | #tiere werden wenn sie keine Lebenspunkte mehr haben aus der update-schleife genommen | ||
+ | def die(self): | ||
+ | self.alive = False | ||
+ | if isinstance(self, Fleischfresser): | ||
+ | print(self.id) | ||
+ | self.hide() | ||
+ | |||
+ | #bewegt ein Tier vorwärts abhängig von "speed" und "direction" | ||
+ | def forward(self): | ||
+ | self.x += self.speed*m.cos(m.radians(self.direction+self.direction_offset)) | ||
+ | self.y += self.speed*m.sin(m.radians(self.direction+self.direction_offset)) | ||
+ | self.hide() | ||
+ | self.show() | ||
+ | |||
+ | #beschreibt das Verhalten eines Tieres während seines sogenannten Zuges basierend auf dem Status | ||
+ | def move(self): | ||
+ | if self.status == "wandering": | ||
+ | self.change_direction("add", r.randint(-5,5)) | ||
+ | self.forward() | ||
+ | |||
+ | elif self.status == "fleeing": | ||
+ | if squared_distance(self.x, self.threat.x, self.y, self.threat.y) >= 90000 and self.threat.target != self: | ||
+ | self.status = "wandering" | ||
+ | self.threat = None | ||
+ | self.speed = self.walking_speed | ||
+ | self.forward() | ||
+ | |||
+ | elif self.status == "hunting": | ||
+ | self.change_direction("set", m.degrees(m.atan2((self.target.y-self.y),(self.target.x-self.x)))) | ||
+ | if (self.x-self.target.x)**2+(self.y-self.target.y)**2 <= (self.radius+self.target.radius)**2: | ||
+ | self.collision() | ||
+ | self.forward() | ||
+ | |||
+ | #Visualisierung der Tiere | ||
+ | def show(self): | ||
+ | self.id = canvas.create_oval(self.x-self.radius, self.y-self.radius, self.x+self.radius, self.y+self.radius, fill=self.color) | ||
+ | |||
+ | def hide(self): | ||
+ | canvas.delete(self.id) | ||
+ | |||
+ | |||
+ | #def det(alpha, beta): | ||
+ | # return m.sin(m.radians(beta-alpha)) | ||
+ | #Überprüft ob die Richtung des Hindernisses im Wahrnehmungsbereich des Tieres liegt | ||
+ | def in_sight(self, avoid): | ||
+ | direction_left_edge = (self.direction + self.direction_offset) + (self.sichtkegelwinkel / 2) #in der Visualiesierung sind die Seiten vertauscht, weil y-Achse auch gespiegelt ist | ||
+ | direction_right_edge = (self.direction + self.direction_offset) - (self.sichtkegelwinkel / 2) #in der Visualiesierung sind die Seiten vertauscht, weil y-Achse auch gespiegelt ist | ||
+ | return det(direction_left_edge, avoid) < 0 and det(avoid, direction_right_edge) < 0 | ||
+ | |||
+ | #Wahrnehmung der Umwelt mithilfe von Stichpunktartigen Zustandschecks entlang der sightrichtung ("direction") | ||
+ | def sight(self): | ||
+ | self.avoiding = None | ||
+ | |||
+ | potential_targets = [] | ||
+ | potential_threats = [] | ||
+ | |||
+ | #debug: | ||
+ | #lines.append(canvas.create_line(self.x, self.y, self.x+dis*m.cos(m.radians((self.direction + self.direction_offset) + (self.sichtkegelwinkel / 2))), self.y+dis*m.sin(m.radians((self.direction + self.direction_offset) + (self.sichtkegelwinkel / 2))), fill = "orange")) | ||
+ | #lines.append(canvas.create_line(self.x, self.y, self.x+dis*m.cos(m.radians(self.direction+self.direction_offset)), self.y+dis*m.sin(m.radians(self.direction+self.direction_offset)), fill = "orange")) | ||
+ | #lines.append(canvas.create_line(self.x, self.y, self.x+dis*m.cos(m.radians((self.direction + self.direction_offset) - (self.sichtkegelwinkel / 2))), self.y+dis*m.sin(m.radians((self.direction + self.direction_offset) - (self.sichtkegelwinkel / 2))), fill = "orange")) | ||
+ | |||
+ | |||
+ | #Kollision mit der Ecke links oben verhindern | ||
+ | if m.sin(m.radians(self.direction+self.direction_offset)) <= 0 and m.cos(m.radians(self.direction+self.direction_offset)) <= 0: | ||
+ | if self.x > dis and self.y <= dis: | ||
+ | self.avoiding = 270 | ||
+ | elif self.x <= dis and self.y > dis: | ||
+ | self.avoiding = 180 | ||
+ | elif self.x <= dis and self.y <= dis: | ||
+ | if self.avoiding == None: | ||
+ | self.avoiding = 180 | ||
+ | |||
+ | #Kollision mit der Ecke rechts oben verhindern | ||
+ | elif m.sin(m.radians(self.direction+self.direction_offset)) <= 0 and m.cos(m.radians(self.direction+self.direction_offset)) > 0: | ||
+ | if self.x <= width-dis and self.y <= dis: | ||
+ | self.avoiding = 270 | ||
+ | elif self.x > width-dis and self.y > dis: | ||
+ | self.avoiding = 0 | ||
+ | elif self.x > width-dis and self.y <= dis: | ||
+ | if self.avoiding == None: | ||
+ | self.avoiding = 0 | ||
+ | |||
+ | #Kollision mit der Ecke links unten verhindern | ||
+ | elif m.sin(m.radians(self.direction+self.direction_offset)) > 0 and m.cos(m.radians(self.direction+self.direction_offset)) <= 0: | ||
+ | if self.x > dis and self.y > hight-dis: | ||
+ | self.avoiding = 90 | ||
+ | elif self.x <= dis and self.y <= hight-dis: | ||
+ | self.avoiding = 180 | ||
+ | elif self.x <= dis and self.y > hight-dis: | ||
+ | if self.avoiding == None: | ||
+ | self.avoiding = 180 | ||
+ | |||
+ | #Kollision mit der Ecke rechts unten verhindern | ||
+ | elif m.sin(m.radians(self.direction+self.direction_offset)) > 0 and m.cos(m.radians(self.direction+self.direction_offset)) > 0: | ||
+ | if self.x <= width-dis and self.y > hight-dis: | ||
+ | self.avoiding = 90 | ||
+ | elif self.x > width-dis and self.y <= hight-dis: | ||
+ | self.avoiding = 0 | ||
+ | elif self.x > width-dis and self.y > hight-dis: | ||
+ | if self.avoiding == None: | ||
+ | self.avoiding = 0 | ||
+ | if self.avoiding != None: | ||
+ | self.avoid(self.avoiding) | ||
+ | |||
+ | |||
+ | for k in range(len(pflanzenfresser)): | ||
+ | if pflanzenfresser[k].alive and not ((isinstance(self, Pflanzenfresser) and k == self.number)): | ||
+ | direction_animal = m.degrees(m.atan2((pflanzenfresser[k].y-self.y),(pflanzenfresser[k].x-self.x))) | ||
+ | if self.in_sight(direction_animal): | ||
+ | self.react_to_pflanzenfresser(k, potential_targets) | ||
+ | |||
+ | for k in range(len(fleischfresser)): | ||
+ | if fleischfresser[k].alive and not (isinstance(self, Fleischfresser) and k == self.number): | ||
+ | direction_animal = m.degrees(m.atan2((fleischfresser[k].y-self.y),(fleischfresser[k].x-self.x))) | ||
+ | if self.in_sight(direction_animal): | ||
+ | self.react_to_fleischfresser(k, potential_threats) | ||
+ | |||
+ | if len(potential_targets) > 0: | ||
+ | self.set_target(self.find_animal(potential_targets)) | ||
+ | if len(potential_threats) > 0: | ||
+ | self.set_threat(self.find_animal(potential_threats)) | ||
+ | |||
+ | if self.avoiding == None: | ||
+ | self.change_direction("add", self.direction_offset) | ||
+ | self.direction_offset = 0 | ||
+ | |||
+ | #Ändert die Richtung, mithilfe einer Offset variable | ||
+ | def avoid(self, direction_avoid): | ||
+ | determinante = det(self.direction+self.direction_offset, direction_avoid) | ||
+ | if determinante < 0: | ||
+ | self.direction_offset += 10 | ||
+ | else: | ||
+ | self.direction_offset -= 10 | ||
+ | |||
+ | def find_animal(self, animals): | ||
+ | if len(animals) > 0: | ||
+ | nearest_animal = animals[0] | ||
+ | for i in range(1, len(animals)): | ||
+ | if squared_distance(self.x, animals[i].x, self.y, animals[i].y) < squared_distance(self.x, nearest_animal.x, self.y, nearest_animal.y): | ||
+ | nearstest_animal = animals[i] | ||
+ | return nearest_animal | ||
+ | |||
+ | #setzt den status auf "fleeing" | ||
+ | def set_threat(self, threat): | ||
+ | self.status = "fleeing" | ||
+ | self.threat = threat | ||
+ | self.speed = self.running_speed | ||
+ | self.change_direction("set", m.degrees(m.atan2((self.threat.y-self.y),(self.threat.x-self.x))) + 180) | ||
+ | |||
+ | #setzt den status auf "hunting" | ||
+ | def set_target(self, target): | ||
+ | self.status = "hunting" | ||
+ | self.target = target | ||
+ | self.color = "red" | ||
+ | self.speed = self.running_speed | ||
+ | |||
+ | #Wenn ein Fleischfresser einen Pflanzenfresser gefangen hat verliert der Pflanzenfresser leben bis er stirbt. Dann wird der Status des Fleischfressers wieder zurückgesetzt | ||
+ | def collision(self): | ||
+ | self.target.change_health(-100) | ||
+ | if self.target.alive == False: | ||
+ | self.change_food(500) | ||
+ | self.status = "wandering" | ||
+ | self.color = "blue" | ||
+ | self.speed = self.walking_speed | ||
+ | |||
+ | class Pflanzenfresser(Tiere): | ||
+ | radius = 5 | ||
+ | def __init__(self, i, x, y, direction): | ||
+ | self.number = i | ||
+ | self.grazing_speed = 0.1 | ||
+ | self.walking_speed = 0.5 | ||
+ | self.running_speed = 2.5 | ||
+ | self.speed = self.walking_speed | ||
+ | super().__init__(x, y, direction, 1000, 1000, 40, 180, "green") | ||
+ | |||
+ | def check_grazing(self): | ||
+ | if self.food < 900: | ||
+ | self.speed = self.grazing_speed | ||
+ | elif self.food >= 1000: | ||
+ | self.speed = self.walking_speed | ||
+ | if self.speed == self.grazing_speed: | ||
+ | self.change_food(1) | ||
+ | |||
+ | def react_to_pflanzenfresser(self, k, potential_threats): | ||
+ | if self.status == "wandering" and pflanzenfresser[k].status == "wandering": | ||
+ | if squared_distance(self.x, pflanzenfresser[k].x, self.y, pflanzenfresser[k].y) < 4*self.radius**2: | ||
+ | if self.mating_cooldown == 0 and pflanzenfresser[k].mating_cooldown == 0: | ||
+ | if self.food >= 500 and pflanzenfresser[k].food >= 500: | ||
+ | if len(pflanzenfresser) <= 400: | ||
+ | global new_pflanzenfresser | ||
+ | random_direction = r.randint(0,359) | ||
+ | new_pflanzenfresser.append(Pflanzenfresser(len(pflanzenfresser)+len(new_pflanzenfresser), self.x, self.y, random_direction)) | ||
+ | self.mating_cooldown = 1000 | ||
+ | pflanzenfresser[k].mating_cooldown = 1000 | ||
+ | elif squared_distance(self.x, pflanzenfresser[k].x, self.y, pflanzenfresser[k].y) < 10000: | ||
+ | if self.mating_cooldown == 0: | ||
+ | self.change_direction("set", m.degrees(m.atan2((pflanzenfresser[k].y-self.y),(pflanzenfresser[k].x-self.x)))) | ||
+ | |||
+ | def react_to_fleischfresser(self, k, potential_threats): | ||
+ | quadratischeDistanz = squared_distance(self.x, fleischfresser[k].x, self.y, fleischfresser[k].y) | ||
+ | if quadratischeDistanz <= dis**2: | ||
+ | potential_threats.append(fleischfresser[k]) | ||
+ | |||
+ | class Fleischfresser(Tiere): | ||
+ | radius = 8 | ||
+ | def __init__(self, i, x, y, direction): | ||
+ | self.number = i | ||
+ | self.walking_speed = 0.8 | ||
+ | self.running_speed = 2 | ||
+ | self.speed = self.walking_speed | ||
+ | super().__init__(x, y, direction, 1000, 1000, 100, 120, "blue") | ||
+ | |||
+ | def react_to_pflanzenfresser(self, k, potential_targets): | ||
+ | quadratischeDistanz = squared_distance(self.x, pflanzenfresser[k].x, self.y, pflanzenfresser[k].y) | ||
+ | if quadratischeDistanz <= 200**2: | ||
+ | if self.food < 500: | ||
+ | if self.status == "wandering": | ||
+ | potential_targets.append(pflanzenfresser[k]) | ||
+ | elif self.status == "hunting": | ||
+ | if quadratischeDistanz < squared_distance(self.x, self.target.x, self.y, self.target.y): | ||
+ | potential_targets.append(pflanzenfresser[k]) | ||
+ | |||
+ | def react_to_fleischfresser(self, k, potential_targets): | ||
+ | if self.status == "wandering" and fleischfresser[k].status == "wandering": | ||
+ | if squared_distance(self.x, pflanzenfresser[k].x, self.y, pflanzenfresser[k].y) < 4*self.radius**2: | ||
+ | if self.mating_cooldown == 0 and fleischfresser[k].mating_cooldown == 0: | ||
+ | if self.food >= 500 and fleischfresser[k].food >= 500: | ||
+ | global new_fleischfresser | ||
+ | random_direction = r.randint(0,359) | ||
+ | new_fleischfresser.append(Fleischfresser(len(fleischfresser)+len(new_fleischfresser), self.x, self.y, random_direction)) | ||
+ | self.mating_cooldown = 1000 | ||
+ | fleischfresser[k].mating_cooldown = 1000 | ||
+ | elif squared_distance(self.x, fleischfresser[k].x, self.y, fleischfresser[k].y) < 40000: | ||
+ | if self.mating_cooldown == 0: | ||
+ | self.change_direction("set", m.degrees(m.atan2((fleischfresser[k].y-self.y),(fleischfresser[k].x-self.x)))) | ||
+ | |||
+ | class See(Objekt): | ||
+ | radius = 50 | ||
+ | def __init__(self, number, x = 50, y = 50): | ||
+ | self.number = number | ||
+ | self.radius = radius | ||
+ | self.x = x | ||
+ | self.y = y | ||
+ | self.color = "blue" | ||
+ | super().__init__(x, y) | ||
+ | |||
+ | #Simulationsaufbau | ||
+ | for i in range(start_pflanzenfresser): | ||
+ | random_x = r.randint(Pflanzenfresser.radius, width - Pflanzenfresser.radius) | ||
+ | random_y = r.randint(Pflanzenfresser.radius, hight - Pflanzenfresser.radius) | ||
+ | random_direction = r.randint(0,359) | ||
+ | pflanzenfresser.append(Pflanzenfresser(i, random_x, random_y , random_direction)) | ||
+ | pflanzenfresser[i].show() | ||
+ | |||
+ | for i in range(start_fleischfresser): | ||
+ | random_x = r.randint(Fleischfresser.radius, width - Fleischfresser.radius) | ||
+ | random_y = r.randint(Fleischfresser.radius, hight - Fleischfresser.radius) | ||
+ | random_direction = r.randint(0,359) | ||
+ | fleischfresser.append(Fleischfresser(i, random_x, random_y, random_direction)) | ||
+ | fleischfresser[i].show() | ||
+ | |||
+ | |||
+ | for i in range(anzahl_seen): ###hiermit habe ich den See und Strand gezeichnet | ||
+ | | ||
+ | id = canvas.create_rectangle(0, 70, 100, 0, fill= "yellow", outline = "yellow") # Das ist die Füllung vom Loch oben links | ||
+ | | ||
+ | id = canvas.create_rectangle(0, 200, 100, 0, fill= "yellow", outline = "yellow") | ||
+ | | ||
+ | id = canvas.create_oval(0, 250, 100, 0, fill= "yellow", outline = "yellow") | ||
+ | |||
+ | id = canvas.create_oval(0, 245, 50, 150, fill= "yellow", outline = "yellow") | ||
+ | |||
+ | id = canvas.create_oval(0, 255, 70, 150, fill= "yellow", outline = "yellow") | ||
+ | |||
+ | id = canvas.create_oval(-50, 255, 30, 100, fill= "yellow", outline = "yellow") | ||
+ | |||
+ | id = canvas.create_oval(-100, 260, 100, 100, fill= "yellow", outline = "yellow") | ||
+ | |||
+ | id = canvas.create_oval(-100, 260, 200, 100, fill= "yellow", outline = "yellow") | ||
+ | |||
+ | |||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | id = canvas.create_oval(0, 150, 100, 0, fill= "blue", outline = "blue") | ||
+ | |||
+ | id = canvas.create_oval(300, 150, 170, 0, fill= "blue", outline = "blue") | ||
+ | |||
+ | id = canvas.create_oval(50, 100, 240, 200, fill= "blue", outline = "blue") | ||
+ | |||
+ | id = canvas.create_rectangle(50, 0, 220, 150, fill= "blue", outline = "blue") | ||
+ | |||
+ | id = canvas.create_oval(250, 140, 220, 157, fill= "blue", outline = "blue") | ||
+ | |||
+ | id = canvas.create_oval(16, 50, 220, 190, fill= "blue", outline = "blue") | ||
+ | update() | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ |