# Torquemada´s erstes Game (Pong)



## Torquemada (13. Jul 2011)

Hallo

Also ich dachte mir, da ich ja ein Spiel programmiere (programmieren ist vlt etwas übertrieben  ) kann ich das ja mal hier reinschreiben. Erstmal was das für ein Spiel ist: Das Spiel soll einen Ball in der Mitte haben und 2 Spieler, die sich den über jeweils einen JButton zuspielen, bis der Ball bei einem auf der Seite landet und der Spieler damit die Runde verliert. 

Dinge die noch integrieren möchte muss:

1. Den Ball
     1.1 Der Ball an sich.
     1.2 Die Bewegung des Balls
2. Beide JButtons sollen sich gleichzeitig bewegen können.
3. Die Felder der jeweiligen Spieler in die der Ball nicht reinkommen darf.
4. Ein Punktezähler

Integriert habe ich:

1. JButtons 
2. Die Bewegung der JButtons.

Wie ihr seht es steht noch ordentlich was aus für mich, was ich erledigen muss/möchte.

Der Code (wird immer in diesem Beitrag aktualisiert) :


```
package javaapplication2;
 
import java.awt.Color;
import java.awt.Container;
import java.awt.Insets;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import javax.swing.JPanel;
 
public class Ball extends JPanel implements KeyListener{
            JFrame frame = new JFrame("Fliegender Ball");
            JButton b1 = new JButton();
            JButton b2 = new JButton();
    
  public Ball() throws IOException
  {
showJFrame();
  }
 
    public void addComponentsToPane(Container pane) throws IOException {
        System.out.println("Player 1: Type your name in please(max. 16 signs)");
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);
        String Spieler1 = br.readLine();
        
        System.out.println("Player 2: Type your name in please(max. 16 signs)");
        String Spieler2 = br.readLine();
        
        pane.setLayout(null);
        
        Insets insets = pane.getInsets();
        
        b1.setText(Spieler1);
        pane.add(b1);
        Dimension size = b1.getPreferredSize();
        b1.setBounds(350 , 20,
                     150, 20);
 
        b2.setText(Spieler2);
        pane.add(b2);
        size = b2.getPreferredSize();
        b2.setBounds(350 ,511,
                    150, 20);
    }
    public void showBall (Graphics g){  //Der Problemfall    
            int x_pos = 30;     // x - Position des Balles
            int y_pos = 100;        // y - Position des Balles
            int radius = 20;        // Radius des Balles
            g.setColor  (Color.red);    //Farbe des Balles
            g.fillOval (x_pos - radius, y_pos - radius, 2 * radius, 2 * radius);
    }
    
    private void showJFrame() throws IOException {
        JFrame frame = new JFrame("Flying Ball");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addComponentsToPane(frame.getContentPane());
        ; //Die Zeile die den Problemfall aufruft
        Insets insets = frame.getInsets();
        frame.setSize(800 + insets.left + insets.right,
                      578 + insets.top + insets.bottom);
        frame.setVisible(true);
        frame.requestFocus();
        frame.addKeyListener(this);
        frame.getContentPane().setBackground(Color.BLACK);      
    }
    
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
 
    @Override
    public void keyTyped(KeyEvent e) {
           if (e. getKeyChar()== 'a') {
           b1.getLocation().getX();
           int a = (int) b1.getLocation().getX();
           int b = a-10;
           if (a -10 < 0) {}
           else {
           b1.setLocation(b, 20);
           b1.setVisible(true);
           }
                }
           if (e. getKeyChar()== '4') {
           b2.getLocation().getX();
           int a = (int) b2.getLocation().getX();
           int b = a-10;
           if (a -10 < 0) {}
           else {
           b2.setLocation(b, 511);
           b2.setVisible(true);
           }
                }
    }
            @Override
    public void keyPressed(KeyEvent e) {
        if (e. getKeyChar()== 'd') {
           b1.getLocation().getX();
           int a = (int) b1.getLocation().getX();
           int b = a+10;
           if (a +30 > 660) {}
           else {
           b1.setLocation(b, 20);
           b1.setVisible(true);
           }
        }    
        if (e. getKeyChar()== '6') {
           b2.getLocation().getX();
           int a = (int) b2.getLocation().getX();
           int b = a+10;
           if (a +30 > 660) {}
           else {
           b2.setLocation(b, 511);
           b2.setVisible(true);
           }
        }   
}
    @Override //muss (leider) drin beleiben
    public void keyReleased(KeyEvent e) {
    }
}
```

Nun was meint ihr? ???:L Zu der Idee (ich weiß das das Game etwas abgebrannt ist) und zu der bisherigen Umsetzung? ???:L Wenn ihr wollt auch gerne Tipps zur Umsetzung. :toll:


----------



## Sonecc (13. Jul 2011)

Ich verweise mal auf die Naming Conventions und möchte dir wirklich raten, deutsche Wörter als Bezeichner zu vermeiden, vor allem wenn du deutsche und englische Wörter als Bezeichner verwendest wird das ganze schnell unübersichtlich.


----------



## Torquemada (13. Jul 2011)

Ok wird umgesetzt ist auch sehr unlogisch 2 Sprachen reinzumachen und englisch ist da wohl genrell die sinnvollere. Was hab ich dabei nur wieder gedacht (wahrscheinlich nix).


----------



## Torquemada (19. Jul 2011)

Update:

Nicht erledigt:
1. Ein Punktezähler
Erledigt:
1. Den Ball
1.1 Der Ball an sich.
1.2 Die Bewegung des Balls
2. Rectangles(Schläger) und deren Bewegung.
3. Die Felder der jeweiligen Spieler in die der Ball nicht reinkommen darf.

Aktueller Code (für die Copy and Paster  ) :

```
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import javax.swing.*;

public final class Example extends JPanel implements Runnable, KeyListener, ActionListener{

   private static final long serialVersionUID = 1L;
   private static int SPEED = 125;
   
   JFrame frame;        //das Fenster
   Rectangle s;
   Rectangle bat1;      //Spieler 1
   Rectangle bat2;      // Spieler 2
   Rectangle ball;      // der Ball
   
   int dx = SPEED; //Bewegungsänderung in x
   int dy = SPEED; //Bewegungsänderung in y
   long time = 0;
   
   public static void main(String[] args) throws IOException{

      new Example();
}
   
   public Example() throws IOException{
      
      frame = new JFrame("Flying Ball");
      frame.setSize(800,578);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(this);   //die Instanz dieses JPanels in Fenster packen
      
      
      bat1 = new Rectangle(370,30,60,10);
      bat2 = new Rectangle(370,511,60,10);
      ball = new Rectangle(200,200,10,10);
      
      bat1.toString();
      
      setBackground(Color.black);
      frame.addKeyListener(this);
      
      frame.setVisible(true); //alles anzeigen
      
      time = System.nanoTime();
      
      Thread t = new Thread(this); //GameLoop in eingenem Thread
      t.run();
    }

   public void run() {
   
      while(frame.isVisible()){  //Thread so lange ausführen, wie Fenster sichtbar ist.
         
         moveBall();       //Ball bewegen
         checkCollision(); //Schläger-Ball-Kollision
         
         try {
            Thread.sleep(26);  //Päuschen
         } catch (InterruptedException e) {}
         
         repaint();  //Repaint
      }
      
   }
   
   
   private void checkCollision(){
      
      if(bat1.intersects(ball)){  
         dy *= -1;                
      }
      if(bat2.intersects(ball)){  
         dy *= -1;                
      }
   }
   
   private void moveBall(){
       
      if(ball.x<0){
         dx = SPEED;
      }

      if(ball.x+ball.width >getWidth()){
         dx = -SPEED;
      }

      if(ball.y<0){
         dy = SPEED;
      }
      
      if(ball.y+ball.height>getHeight()){
         dy = -SPEED;
      }
      
          if(ball.y < 25) {
          System.out.println("Spieler 1 hat verloren!");
          System.out.println("Spieler 2 hat gewonnen! Glückwunsch!");
          ball.y = 300;
          ball.x = 400;
          dx = 0;
          dy = 0;
          bat1.setLocation(370, 30);
          bat2.setLocation(370, 511);
          System.out.println("Drücke 'r' um erneut zu spielen.");  
   }
          
          if(ball.y > 516) {
          System.out.println("Spieler 2 hat verloren!");
          System.out.println("Spieler 1 hat gewonnen! Glückwunsch!");
          ball.y = 300;
          ball.x = 400;
          dx = 0;
          dy = 0;
          bat1.setLocation(370, 30);
          bat2.setLocation(370, 511);
          System.out.println("Drücke 'e' um erneut zu spielen.");  
   }

      long delta = System.nanoTime() - time;  //Zeit seit dem letzen Schleifendurchlauf
      time = System.nanoTime();  //für die nächste Runde Zeit merken
  		 
      ball.x += dx*(delta/1e9); //Bewegung in Abhängigkeit der für den Loop benötigten Zeit.
      ball.y += dy*(delta/1e9);


   }


   @Override
   protected void paintComponent(Graphics g) {
       
      super.paintComponent(g);
      
      g.setColor(Color.green);
      g.fillRect(bat1.x, bat1.y, bat1.width, bat1.height);
      
      g.setColor(Color.red);
      g.fillRect(bat2.x, bat2.y, bat2.width, bat2.height);
      
      g.setColor(Color.blue);
      g.fillOval(ball.x, ball.y, ball.width, ball.height);
      
   }


    @Override
    public void keyTyped(KeyEvent e) {
        
           if (e. getKeyChar()== 'd') {
           bat1.getLocation().getX();
           int a = (int) bat1.getLocation().getX();
           int b = a+10;
           if (a +30 > 750) {}
           else {
           bat1.setLocation(b, 30);
           } 
      } 
           
           if (e. getKeyChar()== 'a') {
           bat1.getLocation().getX();
           int a = (int) bat1.getLocation().getX();
           int b = a-10;
           if (a-10  < 0) {}
           else {
           bat1.setLocation(b, 30);
           }
        } 
           
           if (e. getKeyChar()== '4') {
           bat2.getLocation().getX();
           int a = (int) bat2.getLocation().getX();
           int b = a-10;
           if (a - 10 < 0) {}
           else {
           bat2.setLocation(b, 511);
           }
        } 
                      
           if (e. getKeyChar()== '6') {
           bat2.getLocation().getX();
           int a = (int) bat2.getLocation().getX();
           int b = a+10;
           if (a +30 > 750) {}
           else {
           bat2.setLocation(b, 511);   
           }
        } 
    }



    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void keyPressed(KeyEvent e) {
        
        if (e. getKeyChar() == 'r'){
          dx = 125;
          dy = 125;
        }
        if (e. getKeyChar() == 'e'){
          dx = -125;
          dy = -125;
        }
    }



}
```


----------



## Quaxli (19. Jul 2011)

Mein Finger ist abgebrochen, als ich wie wild auf die D-Taste eingedroschen habe. 
Mal im Ernst: Dir ist doch hoffentlich selbst klar, daß das so nicht spielbar ist?

Statt die Tastatur-Abfrage über keyTyped abzufangen, solltest Du keyPressed und keyReleased verwenden. Und dort aber dann keine Logik hinterlegen, sondern nur booleans auf true oder false setzen.
Also zum Beispiel so für den unteren Schläger:


```
public void keyReleased(KeyEvent e) {
    	
       if(e.getKeyCode()==KeyEvent.VK_A){
      	 lowerleft = false;
       }
       
       if(e.getKeyCode()==KeyEvent.VK_D){
      	 lowerright = false;
       }
       
    }
```

Analog mußt die booleans dann in keyPressed auf true setzen. 
Die booleans fragst Du dann im GameLoop ab. Solange der entsprechende boolean auf true gesetzt ist, bewegst Du den Schläger in die jeweilige Richtung. 
Damit reicht ein Tastendruck, um den Schläger in die gewünschte Richtung zu bewegen (anstelle von gefühlten 100 )


Die Bewegung der Schläger solltest Du dann analog zum Ball realiseren, den Du ja schon in Abhängigkeit von der Zeit des letzten GameLoops bewegst, damit auch die Schläger flüssig laufen.

Was ich noch ändern würde:

1. Die folgende Logik hat meines Erachtens nichts in der Methode moveBall verloren:


```
if (ball.y < 25) {
			System.out.println("Spieler 1 hat verloren!");
			System.out.println("Spieler 2 hat gewonnen! Glückwunsch!");
			ball.y = 300;
			ball.x = 400;
			dx = 0;
			dy = 0;
			bat1.setLocation(370, 30);
			bat2.setLocation(370, 511);
			System.out.println("Drücke 'r' um erneut zu spielen.");
		}
```

Das würde ich in eine eigene Logik-Methode packen und in moveBall wirklich nur die Bewegung des Balls ausführen bzw. die Methode allgemeiner halten und noch die Schläger mit reinpacken.

2. Das throwsIOException beim Konstruktor ist unnötig. 

3. Und was mich noch brennend interessiert:


```
try {
				Thread.sleep(26); // Päuschen
			} catch (InterruptedException e) {
			}
```

Warum ausgerechnet 26 ms??? 


Alles in allem vom Ansatz her ist Dein Programm aber schon ganz gut aufgebaut. Moment verhindert nur die Tastatur-Abfrage, daß es vernünftig spielbar ist, alles andere fällt dann unter "Feinschliff".
Weiter so! :toll:


----------



## Torquemada (7. Dez 2012)

Hallo liebe Gemeinde

nach langer Zeit melde ich mich auch mal zurück. Ich habe das Programmieren ewig liegen lassen, aber jetzt wieder die Lust und Zeit gefunden mein altes Werk zu vollenden und neue zu schaffen.

nun habe ich nur eine Frage und zwar habe ich die Geschwindigkeit des Balls definiert, aber ich weiß nicht mehr was die Befehle bedeuten und wie sie funktionieren. Könnt ihr mir helfen?

Teilcode:


```
long delta = System.nanoTime() - time;  
      time = System.nanoTime();
         
      ball.x += dx*(delta/1e9); 
      ball.y += dy*(delta/1e9);
```

Gesamter (neuer) Code:


```
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Set;

import javax.swing.*;
 
public final class KeinPlanmehr extends JPanel implements Runnable, KeyListener {
 
   private static int SPEED = 125; 
   
   JFrame frame;        // Fenster		
   Rectangle bat1;      // Spieler 1
   Rectangle bat2;      // Spieler 2
   Rectangle ball;      // der Ball
   
   int dx = 0; //Bewegungsänderung in x
   int dy = 0; //Bewegungsänderung in y
   long time = 0; // eine Variable, die nicht viele Nachkommastellen hat aber was tut sie?
   
   public static void main(String[] args) throws IOException{
 
      new KeinPlanmehr();
}
   
   public KeinPlanmehr() throws IOException{
      
      frame = new JFrame("Flying Ball");  // Frame wird benannt
      frame.setSize(800,578);	// Framegrößen werden definiert
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	// ESC führt zum schließen des Progs
      frame.add(this);   //die Instanz dieses JPanels in Fenster packen
      
      
      bat1 = new Rectangle(370,30,60,10);   // Schläger Koordinaten und Größen
      bat2 = new Rectangle(370,511,60,10);	// s.o.
      ball = new Rectangle(200,200,10,10);	// Ball Koordinaten und Größen
      
      bat1.toString();  // Ansätze zur Benennung der Bats
      
      setBackground(Color.black);    // Hintergrund Farbe
      frame.addKeyListener(this);	 // Er soll auf die Tastatur achten
      
      frame.setVisible(true); //alles anzeigen
      
      time = System.nanoTime();
      
      Thread t = new Thread(this); //GameLoop in eingenem Thread
      t.run();
    }
 
   public void run() {
   
      while(frame.isVisible()){  //Thread so lange ausführen, wie Fenster sichtbar ist.
         
    	 checkCollision(); //Schläger-Ball-Kollision
         moveBall();       //Ball bewegen
         
         
            try {
				Thread.sleep(25);
			} catch (InterruptedException e) {}
			
         
         repaint();  //Repaint
      }
      
   }
   
   
   private void checkCollision(){
      
      if(bat1.intersects(ball)){  
         dy = -dy;                
      }
      if(bat2.intersects(ball)){  
         dy = -dy;     //    Ball wird zurückgestoßen, da er sonst das Feld verlässt
      }
   }
   
   private void moveBall(){
       
      if(ball.x<0){
         dx = SPEED;   	// Speed ist ein postiver Wert also wird, wenn der Ball.X = 0 ist der Ball ins positive (nach rechts) bewegt
      }
 
      if(ball.x+ball.width >getWidth()){
         dx = -SPEED;	// s.o.
      }
          if(ball.y < 25) {  // Ball.Y für die Bestimmung des Siegesfelds
          System.out.println("Spieler 1 hat verloren!");
          System.out.println("Spieler 2 hat gewonnen! Glückwunsch!");
          ball.y = 300;   // Ball Posi auf Anfangswert
          ball.x = 400;
          dx = 0;    		// Ball Geschwindigkeit = 0
          dy = 0;
          bat1.setLocation(370, 30);
          bat2.setLocation(370, 511);
          System.out.println("Drücke 'r' um erneut zu spielen.");  
   }
          
          if(ball.y > 516) {  // Ball.Y für die Bestimmung des Siegesfelds
          System.out.println("Spieler 2 hat verloren!");
          System.out.println("Spieler 1 hat gewonnen! Glückwunsch!");
          ball.y = 300;
          ball.x = 400;
          dx = 0;
          dy = 0;  
          bat1.setLocation(370, 30);
          bat2.setLocation(370, 511);
          System.out.println("Drücke 'e' um erneut zu spielen.");  
   }
 
          // Nun folgt die Bewegung des Balls die verstanden werden muss!
          
          
      long delta = System.nanoTime() - time;  
      time = System.nanoTime();
         
      ball.x += dx*(delta/1e9); 
      ball.y += dy*(delta/1e9);
 
   }
 
   @Override
   protected void paintComponent(Graphics g) { // "Malen" der Schläger und des Balls
       
      super.paintComponent(g);
      
      g.setColor(Color.green);
      g.fillRect(bat1.x, bat1.y, bat1.width, bat1.height);
      
      g.setColor(Color.red);
      g.fillRect(bat2.x, bat2.y, bat2.width, bat2.height);
      
      g.setColor(Color.blue);
      g.fillOval(ball.x, ball.y, ball.width, ball.height);
      
   }
 
    @Override
    public void keyTyped(KeyEvent e) {
        
           if (e. getKeyChar()== 'd') {
           bat1.getLocation().getX();
           int a = (int) bat1.getLocation().getX();
           int b = a+10;
           if (a +30 > 750) {}
           else {
           bat1.setLocation(b, 30);
           } 
      } 
           
           if (e. getKeyChar()== 'a') {
           bat1.getLocation().getX();
           int a = (int) bat1.getLocation().getX();
           int b = a-10;
           if (a-10  < 0) {}
           else {
           bat1.setLocation(b, 30);
           }
        } 
           
           if (e. getKeyChar()== '4') {
           bat2.getLocation().getX();
           int a = (int) bat2.getLocation().getX();
           int b = a-10;
           if (a - 10 < 0) {}
           else {
           bat2.setLocation(b, 511);
           }
        } 
                      
           if (e. getKeyChar()== '6') {
           bat2.getLocation().getX();
           int a = (int) bat2.getLocation().getX();
           int b = a+10;
           if (a +30 > 750) {}
           else {
           bat2.setLocation(b, 511);   
           }
        } 
    }
 
    @Override
    public void keyReleased(KeyEvent e) {
 
    }
 
    @Override
    public void keyPressed(KeyEvent e) {
    	if (dx == 0){ // Damit die Spieler nicht durch einen e bzw. r Klick die Richtung des Balls ändern können
    		if (e. getKeyChar() == 'r'){
    			dx = SPEED;
    			dy = SPEED;
        	}
        }
    	if (dx ==0){
        	if (e. getKeyChar() == 'e'){
        		dx = -SPEED;
        		dy = -SPEED;
        	}
    	}
    }

 
}
```


----------

