Simulation macht nicht was sie soll

Hi,
ich habe eine kleine Simulation geschrieben, bei der sich kleine Punkte (Partikel) gegenseitig anziehen.
Es funktioniert auch eigentlich soweit ganz gut, aber gerade wollte ich spaßeshalber die Punkte in einer Linie anordnen, d.h. alle haben den gleichen y-Wert.
Im Prinzip sollte der y-Wert bei allen Punkten ja gleich bleiben, und die Linie sollte sich nicht nach oben oder unten verschieben (was sie aber tut). Ich verstehe nur leider nicht warum.
Komisch ist auch dass oben links ein Punkt war, der da nicht sein dürfte. Die Methode um die Linie zu erzeugen ist denkbar simpel, und ich bezweifel dass da der Fehler stecken wird, hier trotzdem mal:

   	Particle[] p = new Particle[800];
   	
   	for(int i = 0; i < p.length; i++) {
   		p** = new Particle(i+50, 50, p);
   	}
   	return p;
   }```

Wenn ich die x- und y-Werte zufällig generiere funktioniert alles. (Zumindest sieht es dannach aus)

Gerade nochmal getestet, und das komische ist dass es auf die Anzahl der Punkte bzw. die Länge des Arrays ankommt.

Bei 2 funktioniert es, bei 4 auch, bei 5 taucht dann das erste mal der Punkt oben links auf, die nächsten geraden Zahlen funktionieren auch, aber 40, 50 oder 800 nicht mehr.
Ich bezweifel dass ich alleine auf den Fehler, ich hoffe ihr könnt mir helfen.

Hier ist auch noch die Update-Methode der Partikel falls es hilft:
	for(int i = 0; i < otherParticles.length; i++) {
		
		if(otherParticles** != this) {
			float a = f_posx - otherParticles**.getX();
			float b = f_posy - otherParticles**.getY();
			
			float c = (float) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
			
			float vecA = a/c;
			float vecB = b/c;
			
			f_speedx -= vecA;
			f_speedy -= vecB;
			
			
		}
		
		if(f_posx > Gui.screensize.width) {
			f_posx = Gui.screensize.width;
			f_speedx *= -1;
		} else if(f_posx < 0) {
			f_posx = 0;
			f_speedx *= -1;
		}
		if(f_posy > Gui.screensize.height) {
			f_posy = Gui.screensize.height;
			f_speedy *= -1;
		} else if(f_posy < 0) {
			f_posy = 0;
			f_speedy *= -1;
		}
		
		
	}
	
		f_posx += f_speedx*0.1*timeSinceLastFrame;
		f_posy += f_speedy*0.1*timeSinceLastFrame;
		bounding.x = (int) f_posx;
		bounding.y = (int) f_posy;```

Im Code habe ich nichts entdeckt was dieses Verhalten erklären könnte. Bei this handelt es sich um das aktuelle Partikel, dessen Position berechnet wird?
Beobachte mal die Werte von b, vecB und f_speedy, ob die sich merkwürdig verhalten. Evtl. kommt es aufgrund der Verwendung von float zu Werten != 0. Evtl. mal Zeile 38 auskommentieren um sicher zu gehen, dass der y Wert nicht bereits an anderer Stelle manipuliert wird…
Sonst wird nur (auf das wesentliche beschränkter) ausführbarer Code helfen, das Problem weiter einzugrenzen.

Offtopic:

//float c = (float) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
float c = (float) Math.sqrt(a*a+b*b);
...
// f_speedy *= -1;
f_speedy = -f_speedy;

Und ein
if (c < someSmallEpsilon) dontDivideByC()
könnte auch nicht schaden.

Ansonsten sieht man an dem Code nicht so viel, und ich spontan keine mögliche Fehlerursache.

@_Michael
Nachdem ich Zeile 38 auskommentiert habe tritt das Problem immernoch auf, nur dass der Punkt nicht mehr oben links ist, sondern links auf der Höhe der anderen Punkte wo er auch sein sollte. Der x-Wert stimmt nur immernoch nicht.
Aber das heißt ja schonmal dass es an der Update-Methode liegen muss, denn wenn ich den x-Wert auch noch auskommentiere ist der Punkt wo er sein sollte.
Wird wohl im ersten updaten nach oben links geschoben, nur warum?

@Marco13
Warum nicht so?
float c = (float) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
Dachte es wäre schöner Math.pow() zu benutzen. Gibt es einen Grund warum man das nicht machen sollte oder ist es einfach nur schöner?

In erster Linie ist “pow” in diesem Fall wesentlich ineffizienter als eine einfache Multiplikation. Bei 800 Punkten wird das 640000 mal berechnet, da macht sich das mit Sicherheit schon bemerkbar. Um es wirklich effizient zu machen, gibt es aber dann ausgefeiltere Methoden… http://http.developer.nvidia.com/GPUGems3/gpugems3_ch31.html

Ok ganz so professionell wollte ich es dann doch nicht machen. :smiley:
Aber danke für den Tipp, hab es gerade mal getestet. Jetzt läuft es bei 2000 Punkten so flüssig wie vorher bei 1000. :wink: