Bewegung von Partikeln in einem Partikelsystem.

Kamil

Mitglied
Hey Leute,

ich hänge seit einigen Stunden an einem Problem, das ich als Anfänger anscheinend nicht alleine lösen kann. Aufbauend auf der LWJGL Umgebung schreibe ich an einem simplen Partikelsystem. In diesem erzeuge ich in meinem Testprogramm 3 einzelne Partikel (Vectoren), die sich von der Bildmitte her mit jedem Frame

Java:
loc.x += (float) myRandom(-10,10);
loc.y += (float) myRandom(-10,10);

bewegen sollen. myRandom -> siehe unten. Zwar bewegen sich diese auch mit der Zeit quer durch den Bildschirm, jedoch bleiben sie sich immer sehr nahe. Bilden also eine Art Gruppe. Nach meinem Verständnis müssten sie sich doch mit der Zeit auch mal von einander weg bewegen? Auch bei 30000 Partikeln, scheint es, als würde sich ein zusammenhängender, lückenloser Fleck über den Bildschirm bewegen. Ich hatte den Code vorher ohne Vectoren in Processing geschrieben mit folgender Funktion innerhalb der Partikelklasse:

Java:
void drive() {
    xpos += random(-1,1);
    ypos += random(-1,1);
}

Hier verhalten sich meine Partikel wie erwartet. Sie starten in der Mitte und breiten sich in alle Richtungen aus.

Hier mein Code:

ParticleSystem.java

Java:
package com.lwjgl.experiments;

import java.util.ArrayList;
import org.lwjgl.util.vector.Vector2f;

public class ParticleSystem {

	 ArrayList<Particle> particles;    // An arraylist for all the particles Wieso <Particle> ???
	  Vector2f origin;        // An origin point for where particles are birthed
	  
	  ParticleSystem(int num, Vector2f v) {
	    particles = new ArrayList<Particle>();   // ArrayList
	    origin = v;                 
	    
	    for (int i = 0; i < num; i++) {
	      particles.add(new Particle(origin));    // Anzahl an festgelegten Partikeln hinzufügen
	    }
	   
	    System.out.println("originVector: " + origin);
	    System.out.println("Number of added Particles: " + particles.size());
	    System.out.println("-----------------------------------------------");
	  }

	  void run() {
	    //Cycle through the ArrayList backwards b/c we are deleting <- ? 
	    for (int i = particles.size()-1; i >= 0; i--) {
	      Particle p = particles.get(i);
	      p.run();
	    }
	  }
	  
	  void addParticle(Particle p) {
		    particles.add(p);
		  }

	  void addParticle() {
	    particles.add(new Particle(origin));
	  }

	  boolean dead() {
	    if (particles.isEmpty()) {
	      return true;
	    } else {
	      return false;
	    }
	  }
}

Particle.java

Java:
package com.lwjgl.experiments;

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector2f;

public class Particle {
	  Vector2f loc;
	  Vector2f vel;
	  
	  double step = 3;
	  int count = 0;
	
	  // Constructor 1
	  Particle(Vector2f a, Vector2f v, Vector2f l) {
	    vel = v;
	    loc = l;
	  }

	  // Constructor 2 - Benutzen wir
	  Particle(Vector2f origin) {
	    vel = new Vector2f(0,0);
	    loc = origin;
	  }

	  void run() {
	    update_simple();
	    render();
	  }

	  void update_simple() {
		 
				loc.x += (float) myRandom(-10,10);
				loc.y += (float) myRandom(-10,10);

			//System.out.println("x: " + loc.x + " / y: " + loc.y);
		    //System.out.println("---------------------------------");
	  }
	  
	  // Display
	  void render() {
		    GL11.glColor4f(1.0f,1.0f,1.0f,1.0f);
			GL11.glBegin(GL11.GL_QUADS);
			GL11.glVertex2d(loc.x,loc.y);
			GL11.glVertex2d(loc.x+step,loc.y);
			GL11.glVertex2d(loc.x+step,loc.y+step);
			GL11.glVertex2d(loc.x,loc.y+step);
			GL11.glEnd();	
	  }

	// erzeugt zuffalszahlen zwischen low und high
	public static double myRandom(double low, double high) {  
			   return Math.random() * (high - low) + low;  
	}
	}

Im Hauptprogramm wird zunächst initialisiert:

Java:
Vector2f origin = new Vector2f(windowWidth/2,windowHeight/2);
ps = new ParticleSystem(numberOfParticles, origin);

und im Loop gestartet:

Java:
ps.run();

partikel.jpg

10 Partikel, nach etwa 150 Frames. Ich habe random überprüft und es erzeugt zufällig alles mögliche zwischen -10 und 10 also kann ich mir das Verhalten nicht erklären.

Was übersehe ich? Ich bin nicht geübt im Probleme schildern, falls etwas unklar, bitte nachfragen! Vielen Dank! 🙂
 
Zuletzt bearbeitet:
Ahhh, ich merke gerade, dass der loc.x und loc.y Wert immer an den nächsten Partikel weitergegeben wird. Erhöhe ich also jeweils um 1, hat der 1 Partikel beispielsweise die Position 250, der zweite dann 251, der dritte 252... ich weiß nur nicht wieso?!?

Es muss hieran liegen:

Java:
	  void run() {
	    //Cycle through the ArrayList backwards b/c we are deleting <- ? 
	    for (int i = particles.size()-1; i >= 0; i--) {
	      Particle p = particles.get(i);
	      p.run();
	    }
	  }

EDIT:

Okay, liegt es daran, dass ich mir mit Particle p = particles.get(i); nur eine Kopie aus den Ursprungsobjekten hole und nur in dieser einen Kopie den Positionsvektor verändere? Andererseits wird doch p immer wieder neu initialisiert? Und wieso kann ich nicht einfach über particles.run() das ganze starten? Er meckert dann rum: The type of the expression must be an array.
 
Zuletzt bearbeitet:
Ahhh, ich merke gerade, dass der loc.x und loc.y Wert immer an den nächsten Partikel weitergegeben wird. Erhöhe ich also jeweils um 1, hat der 1 Partikel beispielsweise die Position 250, der zweite dann 251, der dritte 252... ich weiß nur nicht wieso?!?
Weil du jedes Particle mit der selben Instanz von Vector2f ("origin") instantiierst, daher änderst du in jeder Particle#update_simple Methode den selben Vektor, daher sind deine Partikel auch zu jeder Zeit alle an der selben Stelle (du zeichnest sie nur zu verschiedenen Zeiten, daher beträgt der Abstand immer maximal +-10)

Und wieso kann ich nicht einfach über particles.run() das ganze starten? Er meckert dann rum: The type of the expression must be an array.

Weil particles kein array ist geht particles nicht
 
An welcher Stelle genau? Ich verstehe es leider nicht ganz. Ich weiß nur, dass ich das beim initialisieren des ParticleSystem tue, bzw. beim adden der einzelnen Particle, aber auch nur einmal.

Mit

Java:
Vector2f loc;

	  Particle(Vector2f origin) {
	    vel = new Vector2f(0,0);
	    loc = origin;
	  }

erstelle ich doch für jeden Partikel eine eigene Kopie von Origin?
 
Zuletzt bearbeitet:
Du sagst
particles.add(new Particle(origin));
Damit haben alle Partikel den selben Positionsvektor. Egal in welcher Particle Instanz du deine loc.x/loc.y änderst: weil alle anderen Partikel den selben Positionsvektor haben, änderst du die Position aller anderen Partikel immer mit. schreibe
particles.add(new Particle(new Vector2f(origin)));
dann sollte das Problem gelöst sein.
 
Oha, tatsache! Es funktioniert. Oh mann... 11 Stunden später läuft es dann endlich. Hab vielen Dank. Ich schau mir das ganze jetzt nochmal in Ruhe an. Ich dachte, dass immer eine Kopie übergeben wird...

:rtfm::rtfm::rtfm:

EDIT

Läuft! Mit 75.000 Quads mit Alpha Wert sogar noch recht flüssig. Juhuu.

partikel2.png
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben