Benutzer-Werkzeuge

Webseiten-Werkzeuge


ws2425:lebewesenverhalten

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
ws2425:lebewesenverhalten [2025/05/05 19:27]
stefanborn [Unser Code:]
ws2425:lebewesenverhalten [2025/05/05 19:41] (aktuell)
stefanborn [Unser Code:]
Zeile 129: Zeile 129:
 ====Unser Code:==== ====Unser Code:====
  
-<​code>​ +<​code ​python>import tkinter as tk 
-a = 1+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>​ </​code>​
  
ws2425/lebewesenverhalten.1746466040.txt.gz · Zuletzt geändert: 2025/05/05 19:27 von stefanborn