# Bälle abprallen lassen



## neotox (19. Jan 2011)

Hallo, 
ich bin gerade dabei ein Programm zu schreiben, wobei sich zwei Bälle innerhalb einer Leinwand bewegen.
Ich habe es soweit geschafft, dass beide Bälle den Rand der Leinwand erkennen und entsprechend abprallen. Beim auftreffen auf die Leinwand ändern sie auch die Farbe. 

Nun möchte ich, dass sie auch von einander abprallen. 
mein Ansatz ist folgender: 

```
if (xPosition.ball_1 + radius == xPosition.ball_2 + radius && yPosition_ball1 + radius == yPosition.ball_2 + radius)
      {

        xGeschwindigkeit = -xGeschwindigkeit ;
        yGeschwindigkeit = -yGeschwindigkeit;

      }
```

Mir ist klar, dass der Abprall so nicht gerade realistisch wirkt, aber darum geht es auch garnicht.

Aber dieser Code funktioniert auch so nicht. Mein Problem ist, dass ich nicht weiss, wie ich die Bedingung formulieren soll.
Die Bedingung soll in die Methode "bewegen".


Hier der ganze Code:

```
import java.awt.geom.Ellipse2D; // importiert die Möglichkeit 2D-Objekte zu zeichnen (für methode "zeichnen")


public class Ball extends Kreis{     // Ball erweitert Kreis

  // Anfang Attribute
  private int durchmesser;   // durchmesser als int (zahlenwert)
  private int xPosition;     // xPosition als int (zahlenwert)
  private int yPosition;     // yPosition als int (zahlenwert)
  private int xg;            // xGeschwindigkeit als int (zahlenwert)
  private int yg;            // yGeschwindigkeit als int (zahlenwert)
  private int xmax;          // maximale xPosition als int (zahlenwert)
  private int ymax;          // maximale yPosition als int (zahlenwert)
    private int radius;
  // Ende Attribute


public Ball (int xgS, int ygS, int xPositionS, int yPositionS){

super();

     // Werte von Ball
    durchmesser = 30; // Durchmesser des Balles
    xPosition = xPositionS;   // xPosition beim erstellen
    yPosition = yPositionS;   // yPosition beim erstellen
    farbe = "blau";   // farbe beim erstellen = blau
    radius = durchmesser/2;


    xg = xgS;    // Geschwindigkeit des Balles in x Richtung
    yg = ygS;    // Geschwindigkeit des Balles in y Richtung
    xmax = 300; // Größe des Applets in x Richtung
    ymax = 300; // Größe des Applets in y Richtung
    istSichtbar = false; // Ball ist beim erstellen unsichtbar

   }


    public static void main (String[] args) {
    Ball ball_1;
    Ball ball_2;

    ball_1= new Ball(3,3,140,30);
    ball_1.farbeAendern ("gelb");
    ball_1.sichtbarMachen();

    ball_2= new Ball(6,12,190,80);
    ball_2.farbeAendern ("rot");
    ball_2.sichtbarMachen();


  for (int i = 1; i < 300; i++){
    ball_1.bewegen();
    ball_2.bewegen();
  }
  }

  // Anfang Methoden


     // Methode um einem weiteren Ball neue Werte zu geben

   public void Ball2 (){             // klasse Ball2 is öffentlich

     // Werte von Ball2
    durchmesser = 30; // Durchmesser des Balles2
    xPosition = 40;   // xPosition beim erstellen
    yPosition = 80;   // yPosition beim erstellen
    farbe = "rot";   // farbe beim erstellen = blau

    xg = 2;    // Geschwindigkeit des Balles2 in x Richtung
    yg = 1;    // Geschwindigkeit des Balles2 in y Richtung

    istSichtbar = false; // Ball2 ist beim erstellen unsichtbar

   }




      // Methode um den Ball zu bewegen
  public void bewegen(){
   xPosition += xg;
   yPosition += yg;


      // Solange true ist läuft der Thread weiter

      // Wenn der Ball den rechten Rand berührt, dann prallt er ab
      if (xPosition > xmax - durchmesser)
      {
        // Ändern der Richtung des Balles
        xg = -xg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Rot
        farbe = ("rot");
      }
      // Ball berührt linken Rand und prallt ab
      else if ( xPosition < 0)
      {
        // Ändern der Richtung des Balles
        xg = -xg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Blau
        farbe = ("blau");
      }

      // Verändern der x- Koordinate
      xPosition += xg;

      // Neuzeichnen des Applets
      zeichnen();



      // Wenn der Ball unten den Rand berührt, dann prallt er ab
      if (yPosition > ymax - durchmesser)
      {
        // Ändern der Richtung des Balles
        yg = -yg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Gelb
        farbe = ("gelb");

      }
      // Ball berührt den oberen Rand und prallt ab
      else if ( yPosition < 0)
      {
        // Ändern der Richtung des Balles
        yg = -yg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Grün
        farbe = ("gruen");
      }


         //zeichne mit neuen Werten
      zeichnen();
}


    public void Kreis (double deltaX, double deltaY){
        //um 180 Grad drehen

         xg = -xg;
         yg = -yg;

    }

       // "rot", "gelb", "blau", "gruen", "lila" und "schwarz".
  public void farbeAendern(String neueFarbe) {
    farbe = neueFarbe;
    zeichnen();
  }


      public void zeichnen() {
    if (istSichtbar) {
      Leinwand leinwand = Leinwand.gibLeinwand();
      leinwand.zeichne(this, farbe, new Ellipse2D.Double(xPosition,
          yPosition, durchmesser, durchmesser));
      leinwand.warte(10);
    }
  }

// Ende Methoden

 }
```


mfG,
neotox


----------



## Marco13 (19. Jan 2011)

Nicht getestet, aber... mit den "==" vergleichen wird's schwierig, sofern die Bälle sich nicht mit einer (relativen) Geschwindigkeit von 1 bewegen. Du solltest evtl. eine Prüfung machen wie
if (abstandDerMittelpunkte < radius1+radius2) kollision();


----------



## neotox (19. Jan 2011)

stimmt, das habe ich nicht bedacht.

wie kann ich eigentlich die variable von einem festen Objekt ansprechen ? 
z.B. die Variable der xPosition von ball1 wäre das sowas wie ball_1.xPosition ?
da es ja zwei verschiedene xPositionen gibt, die Bälle aber bei der Methode auf eine zugreifen.


----------



## JavaForever (19. Jan 2011)

ma frage am rande:
Welche ide benutzt du?


----------



## neotox (19. Jan 2011)

Java Editor 9.15


----------



## Marco13 (20. Jan 2011)

Du hattest jetzt vor, den ersten Codeschnipsel in die "bewegen"-Methode einzubauen ... oder ... ???:L häm. Also, der der die Kollisionen auflösen soll, müßte schon beide Bälle kennen... oder ggf. sowas wie

```
class Ball
{
    int x, y;

    public void collideWith(Ball other)
    {
        if (this.x == other.x) ....
        
    }
```
aber ... das müßte man sich erstmal genauer ansehen.


----------



## neotox (20. Jan 2011)

habe nun folgende methode hinzugefügt: 

```
public void kollision (Ball ball_1, Ball ball_2){
   if (Math.sqrt((ball_2.xPosition - ball_1.xPosition)^2 + (ball_2.yPosition - ball_1.yPosition)^2) < radius + radius);
   {
  farbe = ("lila");
  xg = -xg;
  yg = -yg;
}
 }
```

Aber trotzdem wird der Aufprall der beiden Bälle nicht erkannt. Ich sehe nicht warum. 
Jemand von euch ? 

Ganzer Quelltext:

```
import java.awt.geom.Ellipse2D; // importiert die Möglichkeit 2D-Objekte zu zeichnen (für methode "zeichnen")


public class Ball extends Kreis{     // Ball erweitert Kreis

  // Anfang Attribute
  private int durchmesser;   // durchmesser als int (zahlenwert)
  private int xPosition;     // xPosition als int (zahlenwert)
  private int yPosition;     // yPosition als int (zahlenwert)
  private int xg;            // xGeschwindigkeit als int (zahlenwert)
  private int yg;            // yGeschwindigkeit als int (zahlenwert)
  private int xmax;          // maximale xPosition als int (zahlenwert)
  private int ymax;          // maximale yPosition als int (zahlenwert)
          Thread animator;
    private int radius;
    private  boolean please_stop;
  // Ende Attribute


public Ball (int xgS, int ygS, int xPositionS, int yPositionS){

super();

     // Werte von Ball
    durchmesser = 30; // Durchmesser des Balles
    xPosition = xPositionS;   // xPosition beim erstellen
    yPosition = yPositionS;   // yPosition beim erstellen
    farbe = "blau";   // farbe beim erstellen = blau
    radius = durchmesser/2;


    xg = xgS;    // Geschwindigkeit des Balles in x Richtung
    yg = ygS;    // Geschwindigkeit des Balles in y Richtung
    xmax = 300; // Größe des Applets in x Richtung
    ymax = 300; // Größe des Applets in y Richtung
    istSichtbar = false; // Ball ist beim erstellen unsichtbar

   }


    public static void main(String[] args) {
    Ball ball_1;
    Ball ball_2;

    ball_1= new Ball(3,3,140,30);
    ball_1.farbeAendern ("gelb");
    ball_1.sichtbarMachen();

    ball_2= new Ball(6,12,190,80);
    ball_2.farbeAendern ("rot");
    ball_2.sichtbarMachen();


  for (int i = 1; i < 300; i++){
    ball_1.bewegen();
    ball_2.bewegen();
  }
  }

  // Anfang Methoden


     // Methode um einem weiteren Ball neue Werte zu geben

   public void Ball2 (){             // klasse Ball2 is öffentlich

     // Werte von Ball2
    durchmesser = 30; // Durchmesser des Balles2
    xPosition = 40;   // xPosition beim erstellen
    yPosition = 80;   // yPosition beim erstellen
    farbe = "rot";   // farbe beim erstellen = blau

    xg = 2;    // Geschwindigkeit des Balles2 in x Richtung
    yg = 1;    // Geschwindigkeit des Balles2 in y Richtung

    istSichtbar = false; // Ball2 ist beim erstellen unsichtbar

   }




      // Methode um den Ball zu bewegen
  public void bewegen(){
   xPosition += xg;
   yPosition += yg;


      // Solange true ist läuft der Thread weiter

      // Wenn der Ball den rechten Rand berührt, dann prallt er ab
      if (xPosition > xmax - durchmesser)
      {
        // Ändern der Richtung des Balles
        xg = -xg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Rot
        farbe = ("rot");
      }
      // Ball berührt linken Rand und prallt ab
      else if ( xPosition < 0)
      {
        // Ändern der Richtung des Balles
        xg = -xg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Blau
        farbe = ("blau");
      }

      // Verändern der x- Koordinate
      xPosition += xg;

      // Neuzeichnen des Applets
      zeichnen();



      // Wenn der Ball unten den Rand berührt, dann prallt er ab
      if (yPosition > ymax - durchmesser)
      {
        // Ändern der Richtung des Balles
        yg = -yg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Gelb
        farbe = ("gelb");

      }
      // Ball berührt den oberen Rand und prallt ab
      else if ( yPosition < 0)
      {
        // Ändern der Richtung des Balles
        yg = -yg;
        // Wenn die Bedingung erfüllt wird, ändere Farbe in Grün
        farbe = ("gruen");
      }


         //zeichne mit neuen Werten
      zeichnen();
}

 public void kollision (Ball ball_1, Ball ball_2){
   if (Math.sqrt((ball_2.xPosition - ball_1.xPosition)^2 + (ball_2.yPosition - ball_1.yPosition)^2) < radius + radius);
   {
  farbe = ("lila");
  xg = -xg;
  yg = -yg;
}
 }


    public void Kreis (double deltaX, double deltaY){
        //um 180 Grad drehen

         xg = -xg;
         yg = -yg;

    }

       // "rot", "gelb", "blau", "gruen", "lila" und "schwarz".
  public void farbeAendern(String neueFarbe) {
    farbe = neueFarbe;
    zeichnen();
  }


      public void zeichnen() {
    if (istSichtbar) {
      Leinwand leinwand = Leinwand.gibLeinwand();
      leinwand.zeichne(this, farbe, new Ellipse2D.Double(xPosition,
          yPosition, durchmesser, durchmesser));
      leinwand.warte(10);
    }
  }

  // Ende Methoden

 }
```


----------



## Marco13 (20. Jan 2011)

Böse Falle: ^ ist ein Bitweises, exklusives OR, und hat mit "hoch zwei" nichts zu tun. Statt
someValue^2
muss man
someValue*someValue
schreiben, oder mit Math.pow arbeiten. In diesem Fall gibts aber auch schon die fix-und-fertige Math (Java Platform SE 6)


----------



## neotox (21. Jan 2011)

Gut, hab ich nun beachtet. 
mein Problem liegt jez in der Methode:

```
public void kollision (ball_1, ball_2){

     if(ball_1xPosition <= ball_2xPosition){
    deltax = ball_2.xPosition - ball_1.xPosition;
   }

    else if(ball_2xPosition <= ball_1xPosition){
    deltax = ball_1xPosition - ball_2xPosition;
   }

   if(ball_1yPosition <= ball_2yPosition){
    deltay = ball_2yPosition - ball_1yPosition;
   }
   else if(ball_2.yPosition <= ball_1.yPosition){
    deltay = ball_1.yPosition - ball_2.yPosition;
   }


   if (Math.hypo(deltax + deltay)<= radius - radius);
   {
  farbe = (schwarz);
  xg = -xg;
  yg = -yg;
  }
```

aus irgend einem grund, ist die letzte Bedingung immer erfüllt.
Was mache ich falsch ?


----------



## Marco13 (21. Jan 2011)

Die Fallunterscheidung braucht man nicht. x^2 ist immer positiv.

```
public void kollision (Ball ball_1, Ball ball_2)
{
    double dx = ball_2.xPosition - ball_1.xPosition;
    double dy = ball_2.yPosition - ball_1.yPosition;
    double distance =  Math.hypot(deltax, deltay);
    if (distance <= 2*radius)
    {
        farbe = ("schwarz");
        xg = -xg;
....
```

Ansonsten solltest du mal das Semikolon ";" hinter der if-Abfrage wegmachen.


----------



## neotox (21. Jan 2011)

Marco13 hat gesagt.:


> Die Fallunterscheidung braucht man nicht. x^2 ist immer positiv.
> 
> ```
> public void kollision (Ball ball_1, Ball ball_2)
> ...



Danke dir. Es hat funktioniert alles einwandfrei. Das ";" hat mich viele Stunden lang zur verzweiflung gebracht, bin aber ca. 40 minuten bevor du gepostet hast drauf gekommen 

werde mich nun mit einer realistischeren berechnung der Kollision befassen.


----------

