import pygame from random import uniform import numpy as np from numpy import sign from scipy.spatial import cKDTree def board(screen,xsc,sizey,bloblist,struc): #Funktion die das Board in jeder Iteration neu zeichnet i=0 k=0 pinc=0 while (i<struc): pygame.draw.line(screen,0,((xsc/2)+(xsc*i), sizey),(((xsc/2)+(xsc)*i), (sizey-50))) #Zeichnet die Linien der Faecher while (k<=i): #Zeichnet einen Punkt an jeder Koordinate in der "bloblist"-Liste pygame.draw.line(screen,0,bloblist[pinc],bloblist[pinc]) pinc=pinc+1 k=k+2 i=i+1 k=i*(-1) def main(sizex, sizey, struc, radi, nball, mode,filos): #Hauptfunktion pygame.init() #erzeugung der pygame instanz screen = pygame.display.set_mode((int(sizex), int(sizey))) #Setzt die Fenstergroesse anhand der Uebergeben Groessen fest pygame.display.set_caption("Galton") #Name des Fensters screen.fill((255,255,255)) #hintergurndfarbe pygame.draw.line(screen,0,(50.0,50),(50,150)) #Massstab um groessen zu Vergleichen pygame.draw.circle(screen,0,(int(50),int(50.0)),5,0) #-------------------VARIABLEN-------------------------------------------------------------------------------------------------------------------------------------------------- i=0 k=0 j=0 by=0.0 #Y-Impuls der Kugel bx=0.0 #X-Impuls der Kugel t=0.0 #Zeitparameter s=9000000.0 #Maxmimale Zeit, Abruchkriterium colisionY=0.0 #Y-Koordinate des Abstands zwichen 2 Punkten colisionX=0.0 #X-Koordinate des Abstands zwichen 2 Punkten bloblist= [] #Liste aller Pins (Enthaelt je ein Orts-Tupel) loballs=[] #Liste aller Kugel und ihrer Eigenschaften poballs=[] #Liste aller Kugelpositionen (Enthaelt je ein Orts-Tupel) pinc=0 #Zaehler der die Pins zaehlt, wird zur erzeugung der Pinstruktur benoetigt bacou=0 #Beschreibt die Farbe der Kugel grav=0.00981 #Gravitationskontante, Bestimmt die zuname der Geschwindigkeit in Y-richtung #radi=5 #Radius der Kugel, Bestimmt auch Kollisionsradius zahlen='' #String in dem jedesmal wenn eine Kugel in ein Fach faellt die Nummer des Fachs geschrieben wird a=0 #Anzahl der Kugel in einem Fach w=(struc*(-0.5)) #das am weitesten Linke Fach dati="" #String der in die Datei geschrieben wird coliimpx=0.0 #Variablen die zur Berechnung der dezentralen Kollision verwendet werden coliimpy=0.0 coliswapx=0.0 coliswapy=0.0 impimpx=0.0 impimpy=0.0 xsc=(sizex/(struc)) #Struktur Einteilung in X-Richtung ysc=(sizey/(struc+1)) #Struktur Einteilung in Y-Richtung #-------------------ERZEUGUNG------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ if mode >1: # Verhindert Modi groesser 1 mode=1 while i<nball: # Erzeugung der Kugeln loballs.append([(sizex/2)+(np.random.rand()-0.5)*5, (np.random.rand()-0.5)*5 + (sizey/2 *mode), (bx+(np.random.rand()-0.5)*0.02+(np.random.rand()-0.5)*0.5*mode), (by+(np.random.rand()-0.5)*0.02*mode), bacou]) # (X-Position,Y-Position,X-Impuls,Y-Impuls,Farbe) loballs[i][4]=((np.random.randint(0,255)),(np.random.randint(0,255)),(np.random.randint(0,255))) #Erzeugung der Farbe durch RNG i=i+1 i=0 if mode==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) while (i<struc): #Erzeugung des Boards pygame.draw.line(screen,0,((xsc/2)+(xsc*i), sizey),(((xsc/2)+(xsc)*i), (sizey-50))) #Zeichnen der Linien der Faecher while (k<=i): #Erzeugung der Pins bloblist.append(((((sizex/2)+(xsc/2)*(k))), ((ysc)*i)+50)) pygame.draw.line(screen,0,bloblist[pinc],bloblist[pinc]) pinc=pinc+1 k=k+2 i=i+1 k=i*(-1) i=0 tree = cKDTree(bloblist,leafsize=1) #Erzeugung des Pin-Tree in dem alle Orte der Pins gespeichert werden #-------------------Bewegung und Kollision--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- while t!=s: #Grosse Schleife, bricht ab sobald Zeitparameter t den Abruchparameter s erreicht if t!=s: t=t+1 #Iteriert den Zeitparameter screen.fill((255,255,255)) #setzt das Fenster auf Weiss zurueck poballs=[] #Leert die Liste for ball in loballs: #Fuegt die aktuellen Positionen aller Kugeln hinzu poballs.append((ball[0],ball[1])) tree2 = cKDTree(poballs, leafsize=1) #Erzeugt den Kugel-Tree #-------------------Bewegung------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ for ball in loballs: if mode==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) ball[3]=ball[3]+grav #Fuegt der Y-Impulskoordinate die Gravitation hinzu (in Testbench nicht noetig) ball[0]=ball[0]+ball[2] #Addiert die X-Impulskoordinate auf den X-Ort der Kugel (Bewegung) ball[1]=ball[1]+ball[3] #Addiert die Y-Impulskoordinate auf den Y-Ort der Kugel (Bewegung) pygame.draw.circle(screen,ball[4],(int(ball[0]),int(ball[1])),radi,0) #Zeichnet die Kugel am neuen Ort in ihrer Farbe pygame.draw.circle(screen,(0,0,0),(int(ball[0]),int(ball[1])),radi,1) #Zeichnet schwarzen Rand um die Kugel #-------------------Kollision------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #----------------------Wand--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if ball[0]>=(sizex-5): #rechtsseitiger Rand ball[2]=ball[2]*(-1) if ball[0]<=5: #linksseitiger Rand ball[2]=ball[2]*(-1) if mode!=0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) if ball[1]>=(sizey-5): #unterer Rand (nur in Testbench) ball[3]=ball[3]*(-1) if ball[1]<=(5): #oberer Rand (nur in Testbench) ball[3]=ball[3]*(-1) #----------------------Pin--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) d,j= tree.query([ball[0],ball[1]]) #dursucht den Pin-Tree nach naechstem Pin if d <radi: colisionY = ball[1]-bloblist[j][1] #Bestimmung des Abstandsvektors colisionX = ball[0]-bloblist[j][0] ball[3]=0.5*ball[3]*sign(ball[3])*sign(colisionY) #Reversion des Kugel-Impulses, wenn dieser auf den Pin zeigt ball[2]=ball[2]*sign(ball[2])*sign(colisionX) if abs(ball[3])<grav: #Verhindert das der Impuls zu klein wird und die Kugel am Pin 'klebt' ball[3]=ball[3]+(sign(ball[3])*0.8*grav) if abs(ball[2])<0.002: ball[2]=ball[2]+((np.random.rand()-0.5)*0.05) #----------------------Kugel-Kugel--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- h,g= tree2.query(([ball[0],ball[1]]),2) #durchsucht den Kugel-Tree nach naechste Kugel die nicht sie selbst ist if h[1]<(2*radi): if g[1]<len(loballs): colisionY = ball[1]-loballs[g[1]][1]+0.000001 #Bestimmung des Abstandsvektors der Beiden Kugeln colisionX = ball[0]-loballs[g[1]][0]+0.000001 #+0.0000001 damit der Abstand nicht 0 wird [WORKAROUND] coliimpx = colisionX*ball[2] #multiplikation mit den Impulskoordinaten der Kugel mit dem Abstandsvektor coliimpy = colisionY*ball[3] impimpx = ball[2]*loballs[g[1]][2] #multiplikation der Impulskoordinaten beider Kugeln impimpy = ball[3]*loballs[g[1]][3] if sign(coliimpx)*sign(impimpx) >=0: #check ob beide Impulse aufeinander zu zeigen if sign(coliimpy)*sign(impimpy) >=0: coliimpx = (((ball[2]-loballs[g[1]][2])*colisionX + (ball[3]-loballs[g[1]][3])*colisionY)*colisionX)/(colisionX**2+colisionY**2) # dezentrale Kollision coliimpy = (((ball[2]-loballs[g[1]][2])*colisionX + (ball[3]-loballs[g[1]][3])*colisionY)*colisionY)/(colisionX**2+colisionY**2) loballs[g[1]][2]=loballs[g[1]][2]+0.5*coliimpx #Impuls neu zuweisung loballs[g[1]][3]=loballs[g[1]][3]+0.5*coliimpy ball[2]=ball[2]-coliimpx #Impuls neu zuweisung ball[3]=ball[3]-coliimpy #----------------------Fach-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) if ball[1]>=(sizey-40): #Zaehlung der Kugel im Fach c=int(ball[0]/(sizex/(struc+1)))-((struc)/2) zahlen=zahlen + " " + str(c) + " " #----------------------Endkriterien---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) loballs = [ ball for ball in loballs if ball[1]<sizey-40] #Ausschluss aller in Faecher gefallenen Kugeln if not loballs: #Abruch sobald alle Kugel in Faechern sind t=s if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) board(screen,xsc,sizey,bloblist,struc) #neuzeichnen des Bretts pygame.display.flip() #----------------------Auswertung-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if mode ==0: #Modus Kontrolle (0= Board-Mode, 0!= Testbench) f=open(filos+".txt", "w") while w<=(struc/2): #Zaehlung der Kugeln in den Faechern und schreiben der AAnzahlen in die Datei dt=" "+str(w) + " " a=zahlen.count(dt) dati= dati + str(w) + "\t" + str(a) +"\t" + "\n" w=w+1 f.write(dati) f.close() print "fin" filos="pygg_data3" #Dateiname main(500.0, 500.0, 12.0, 5, 200, 0, filos)