# Ball Problem



## siser (11. Jul 2009)

Hi, ich möchte mit Java einen Ball in einem JPanel mit der A und Enter Taste bewegen bzw die Farbe ändern etc. In der Schule hatten wir dafür ein Packet namens StiftundCo. Nun möchte ich es aber mit graphics machen, doch der KeyListener funktioniert nicht wenn ich ihn in einen JFrame packe. Kann mir vlt einer helfen?

Zeichenpanel.java <- Kreis und Ereignisanwendungen.

```
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;

public class ZeichenPanel extends JPanel implements KeyListener{

private Kreis kreis;
private int xPos=100;
private int yPos=100;


public ZeichenPanel(){
super();
this.addKeyListener(this);
kreis=new Kreis();
}

public void paint(Graphics g){
kreis.zeichne(g);
}



    public void keyTyped(KeyEvent e) {
       int quelle= e.getKeyCode();
        if(quelle==KeyEvent.VK_ENTER){
       kreis.setPosition(xPos+10, yPos+10);
       kreis.setFarbe(Color.red);
       repaint();
        }
       if(quelle==KeyEvent.VK_A)
       {
       kreis.setPosition(xPos+10, yPos+10);
       repaint();
       }
       System.out.println();
    }

    public void keyPressed(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void keyReleased(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
```
NewClass.java <-Frame damit wenigstens der Kreis richtig angezeigt wird sonst sieht man garnichts.

```
import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
import java.awt.Graphics;

import java.awt.event.KeyListener;

public class NewClass extends JFrame{

private Kreis kreis;
private int xPos=100;
private int yPos=100;
JPanel jp;

public NewClass(){
super();
kreis=new Kreis();
setBackground(Color.white);
setBounds(0, 0, 600, 600);
setVisible(true);
jp=new ZeichenPanel();
add(jp);
}
}
```

Kreis.java

```
import java.awt.Color;
import java.awt.Graphics;
import stiftUndCo.*;
public class Kreis{

    // Attribute
   
    private int radius;
    private int xPos;
    private int yPos;
    private Color farbe;
    private Stift stift;

   
    // Konstruktor
    
    public Kreis() {
        xPos=10;
        yPos=10;
        farbe = Color.black;
        stift=new Stift();
        radius = 50;

        
    }
public void zeichne (Graphics g) {
// Setzten der Zeichenfarbe auf Rot
g.setColor (farbe);
// Zeichen eines gefüllten Kreises
g.fillOval (xPos, yPos, radius, radius);
}
    // Methoden
    
     /**
     *  Der Radius des Kreises wird neu festgelegt. 
     *  Der alte Kreis wird vorher nicht automatisch geloescht, 
     *  der neue Kreis wird nachher nicht automatisch gezeichnet.
     *  @param  pRadius (neuer Radius des Kreises)
     */ 
    public void setRadius(int pRadius) {
        radius = pRadius;
    }
    
    public double getRadius() {
       return radius;
    }
    /**
     *  Der Kreis wird gezeichnet. 
     */ 
  
    

    
     public void setPosition(int pX, int pY) {
        xPos=pX;
        yPos=pY;


    }
    public void setFarbe(Color pFarbe) {
        farbe=pFarbe;


    }
    
       /**
      *  Die x-Koordinate des linken oberen Eckpunkts wird zurŸckgegeben.
      */
     public double getX() {
         return xPos;
 
     }
     /**
      *  Die y-Koordinate des linken oberen Eckpunkts wird zurŸckgegeben.
      */
     public double getY() {
             return yPos;
 
     }
    
   
    
    public void loeschen(Graphics g) {
       g.setColor(Color.white);
       g.fillOval(xPos, yPos, radius, radius);
       
    }
    
      }
```


----------



## André Uhres (11. Jul 2009)

setVisible(true) macht man gewöhnlich zum Schluss, oder noch besser in der main Methode, statt im Konstruktor:

```
public static void main(final String[] args) {
        Runnable gui = new Runnable() {

            @Override
            public void run() {
                new NewClass().setVisible(true);
            }
        };
        //GUI must start on EventDispatchThread:
        SwingUtilities.invokeLater(gui);
    }
```
Ein setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); kann auch nützlich sein.

Für die Reaktion auf KeyEvents muss ZeichenPanel fokusierbar sein: setFocusable(true);
Auch machst du deinen Code am besten in keyPressed (oder keyReleased), statt in keyTyped.

Für das eigentliche Zeichnen überschreibt man in Swing meist nicht die paint() Methode.
Siehe Malen in Swing Teil 1: der grundlegende Mechanismus - Byte-Welt Wiki


----------



## siser (11. Jul 2009)

super. das hat geklappt.
Wie krieg ich denn den Ball kontinuirlich laufend? 
Ich habs mit extends Runnable und
 public void run() {
        while(true){
        xPos++;
        kreis.setPosition(xPos, yPos);
        repaint();
        try{t.sleep(1000);}catch(Exception e){}
        }
    }
versucht, klappt aber nicht.


```
import java.awt.*;
import java.awt.event.KeyEvent;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.event.KeyListener;

public class ZeichenPanel extends JPanel implements KeyListener,Runnable{

private Kreis kreis;
private int xPos=100;
private int yPos=100;
private Thread t;

public ZeichenPanel(){
super();
setFocusable(true);
this.addKeyListener(this);
t=new Thread();
t.start();
kreis=new Kreis();
}

    @Override
public void paintComponent(Graphics g){
kreis.zeichne(g);
}


    public void keyTyped(KeyEvent e) {
      
    }

    public void keyPressed(KeyEvent e) {
        int quelle= e.getKeyCode();
        if(quelle==KeyEvent.VK_ENTER){
       kreis.setPosition(xPos+=10, yPos+=10);
       kreis.setFarbe(Color.red);
  
     
        }
       else if(quelle==KeyEvent.VK_A)
       {
       kreis.setPosition(xPos+10, yPos+10);
       
       }
repaint();
    }

    public void keyReleased(KeyEvent e) {
        
    }

    @SuppressWarnings("static-access")
    public void run() {
        while(true){
        xPos++;
        kreis.setPosition(xPos, yPos);
        repaint();
        try{t.sleep(1000);}catch(Exception e){}
        }
    }

}
```


----------



## André Uhres (11. Jul 2009)

new Thread(this).start();


----------



## siser (11. Jul 2009)

Danke

Jetzt hab ich ncoh ne dumme Frage wie kann ich den Kreis in einer kurvenartigen Bahn laufen lassen.
Bis jetzt hab ich nru die Möglichkeit x und y Pos einmal zu verändern. Bei einer Kurver ändern die sich ja immer anders


----------



## André Uhres (12. Jul 2009)

Um eine Kurve zu bekommen, erzeugen wir die Bewegung mit einem variablen Wert. Beispiel:
Ersetze "private int yPos = 100;" durch dies:
private int yPos = 500;
private double vy = -25;

Ersetze "xPos++;" durch dies:
xPos += 7;
yPos += vy;//variabler Wert
vy += 1;//der Wert wird verändert


----------



## siser (12. Jul 2009)

Ok thx. Wie kann ich den bei Rechtecken eine Kolision entdecken? Also das Rehcteck bewegt sich über den Schrim sodass es eine Schlange bildet. Wenn es seinen Schwnaz berührt soll das Spiel beendet sein. An den Bildschirnrändern krieg ich es hin aber nicht beim Schwanz.



```
public ArrayList<String> aL; //Liste
 radius = 6; // Größe der Schlange
 aL=new ArrayList();

public boolean getroffen2(){
           double x_=this.getX()+2.5;
           double y_=this.getY()+2.5;
       if(aL.contains(x_+":"+y_)){return true;}
       else{return false;}
       }


public void zeichne () {
//    for(int i=0;i<=geschwindigkeit;i++){
  int x=this.getX()+3;
        int y=this.getY()+3;
//        aL.add(x+":"+y);
//    }
    aL.add(x+":"+y);
    
    stift.hoch();
    stift.bewegeUm(geschwindigkeit);
    stift.runter();
    stift.fuelleRechteck(radius,radius);
```



getX() und getY() liefern mir die aktuelle Position. Diese speicher ich in die ArrayList und frage dann bei getroffen ab ob die Schlange da schonmal war. Dennoch klappt es zu 90% nicht.


----------



## André Uhres (17. Jul 2009)

Für Spiele haben wir das Tutorial von Quaxli "Einstieg in die Spieleprogrammierung mit Java": http://www.java-forum.org/buecher-tutorials-und-links/14545-tutorials-von-mitgliedern.html


----------

