PingPong selber schreiben

Status
Nicht offen für weitere Antworten.

H3llGhost

Bekanntes Mitglied
Hallo Leute

ich habe vor das Spiel PingPong zu schreiben.
Bis jetzt noch kein Problem ...
Ich habe einen sehr leichten Code und der hilft mir aber nur bei einem waagrecht fliegenden Ball.
Nun möchte ich diesen gerne waagrecht und senkrecht gleichzeitig (schräg) fliegen zu lassen.
Aber ich weiß nicht wie ich das realisieren soll.
Könnt ihr mir helfen?

Danke im Voraus!
 

ARadauer

Top Contributor
nach rechts: x++
nach oben: y++

nach rechts oben: x++; y++

du änderst halt nicht nur die waagrechte position sondern auch die senkrechte.....
 

H3llGhost

Bekanntes Mitglied
Danke!
Das ist ja die simpelste Methode ... ;)

Was ist nun aber wenn ich sage er soll gegen eine Wand prallen und je nachdem wie er dagegen prallt, soll er wieder mit einem bestimmten Winkel, der errechnet werden soll, abprallen.
Wie sieht es dann aus?
 

Marco13

Top Contributor
Da Einfallswinkel==Ausfallswingkel ist, wirst du bei "x++ und y++" soweiso nie einen anderen Winkel als 0, 90 oder 45 grad haben, und das kann man notfalls mit "if" abfragen... Wenn du allgemeinere Bewegungen möglich machen willst, solltest du für die Kugel die Position UND die Geschwindigkeit speichern. Beides besteht aus jeweils 2 ints oder besser floats. Wenn du die Geschwindigkeit dann erstmal als schönen 2D-Vektor hast, kannst du damit die fiesesten Berechnungen machen...
 

H3llGhost

Bekanntes Mitglied
Hallo Marco,

danke für deine Hilfe.
Das mit dem Einfallswinkel==Ausfallswinkel habe ich mir so auch schon gedacht und das habe ich auch nun geschafft, dass es läuft ... :)

Aber wie würdest du überhaupt mit einem 2D Vector anfangen?
Eine Funktion move zum Beispiel schreiben die als Parameter die Position und Geschwindigkeit entgegennimmt?
 

Marco13

Top Contributor
Höm. Die Parameter braucht sie nichtmal unbedingt. Es würde sich evtl. anbieten, eine Klasse zu machen, die Position und Geschwindigkeit zusammenfasst. Die braucht dann nicht viel mehr als eine "move()"-Methode - vorausgesetzt, man will die Geschwindigkeit nicht von außen beeinflussen. Über Kollisionserkennung und -antwort muß man sich dann halt noch Gedanken machen....
 

0x7F800000

Top Contributor
ne. move(long millis) nimmt höchstens die vergangene zeit entgegen. Position und Geschwindigkeit sind doch eigenschaften des objektes => membervariablen, warum soll man die von außen angeben können?

[edit] *bezieht sich auf den vorletzten beitrag, an Marco13's beitrag hab ich nichts auszusetzen :D *
 

H3llGhost

Bekanntes Mitglied
@Marco13:
Was würdest du denn noch in die Klasse packen?
Also Positions- und Richtungsangaben ...
Und die Funktion move() wird dann von dem Thread ausgeführt oder?
 

Quaxli

Top Contributor
Alles was die Klasse braucht ;) ,das hängt u. a. davon ab, was Du alles realisieren willst. Und ja, die move-Methode würde periodisch vom Thread aufgerufen.

Für die Bewegungsänderung bei Kollision würde ich nicht unbedingt mit Vektoren anfangen. Im Prinzip ändert sich immer nur eine Bewegungskomponente. Wenn der Ball z. B. an die rechte Wand prallt, muß man nur die x-Bewegung negieren und die y-Bewegung gleich lassen (nach oben - also negativ). Schon hat man eine Umsetzung von Einfall- gleich Ausfallswinkel. Analog dazu ändert sich bei einer Kollision mit dem oberen Rand auch nur y-Bewegungsrichtung und die x-Bewegung bleibt gleich.
 

0x7F800000

Top Contributor
vielleicht noch ein paar informationen über das aussehen des balls, etwa radius, farbe, oder die referenz zu einem bild, das an seiner stelle gezeichnet wird. Evtl auch eine eigene methode, die den ball zeichnet...
 

H3llGhost

Bekanntes Mitglied
Also hier vielleicht mal mein Programm zum besseren Einblick:

GUI:
Code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class ppGUI extends JFrame implements ActionListener, MouseMotionListener
{
  private JPanel einPanel;
  private ppDraw ppd;
  public ppGUI()
  {
    setTitle("Ping Pong eXTr3m3");                             //Titel des Rahmen
    setSize(500,500);                                  //Größe des Rahmen in Pixel
    setDefaultCloseOperation(EXIT_ON_CLOSE);           //Schließt den Rahmen
    setResizable(false);

    einPanel = new JPanel();                           //Erzeugen der "Leinwand"
    einPanel.setLayout(null);
    einPanel.setBackground(Color.BLACK);
    
    ppd = new ppDraw();
    ppd.setBounds(50,50,400,300);
    
    addMouseMotionListener(this);

    //am Ende:
    einPanel.add(ppd);
    add(einPanel);
    setVisible(true);                                //Sichtbar machen
  }
  
  public void actionPerformed(ActionEvent evt)
  {

  }

  public void mouseDragged(MouseEvent e)
  {

  }

  public void mouseMoved(MouseEvent e)
  {
    ppd.setYKoordinate(e.getY()-110);
    System.out.println(ppd.getYKoordinate());
    ppd.repaint();
  }

  public static void main(String args[])
  {
    ppGUI pp = new ppGUI();
  }
}

Klasse, die für das Zeichnen zuständig ist:
Code:
import javax.swing.*;
import java.awt.*;

class ppDraw extends JPanel implements Runnable
{
  private int YKoordinate = 0;
  private int PositionX = 21, PositionY = 150;
  private int xd, yd;
  private Thread runner;
  public ppDraw()
  {
    setBackground(Color.WHITE);
    xd = 0;
    yd = 0;
    runner = new Thread(this);
    runner.start();
  }
  public void paintComponent(Graphics g)
  {
    super.paintComponent(g);
    g.fillRect(0,YKoordinate,9,80);
    g.setColor(Color.BLACK);
    g.fillOval(PositionX,PositionY,9,10);
    g.setColor(Color.BLACK);
  }
  public void setYKoordinate(int y)
  {
    YKoordinate = y;
    if (y < 0)
       YKoordinate = 0;
    if (y > 330)
       YKoordinate = 330;
  }
  public int getYKoordinate()
  {
    return YKoordinate;
  }
  public void startThread()
  {
    runner.start();
  }
  public void bmove(int xd, int yd)
  {
    if (xd == 0)
    {
      PositionX = PositionX + 3;
      if ((PositionX == 9) && (PositionY < (getYKoordinate()+80)) && ((getYKoordinate()-10) < PositionY))
         xd = 1;
      else if (PositionX > 390)
      {
        xd = 1;
        System.out.println("game over");
      }
    } else if (xd == 1)
    {
      PositionX = PositionX - 3;
      if ((PositionX == 9) && (PositionY < (getYKoordinate()+80)) && ((getYKoordinate()-10) < PositionY))
        xd = 0;
      else if (PositionX < 0)
      {
        xd = 0;
        System.out.println("game over");
      }
    }
    if (yd == 0)
    {
      PositionY = PositionY + 3;
    } else if (yd == 1)
    {
      PositionY = PositionY - 3;
    }
    try
    {
      Thread.sleep(20);
    }
    catch(InterruptedException e)
    {
      System.out.println("Thread Fehler");
    }
    repaint();
  }
  public void run()
  {
    while(true)
    {
     bmove(xd, yd);
    }
  }
}

Und so sollte es am Anfang mit der Grafik auch getan sein ... ;)
Für den Anfang reicht es ja wohl ...
 

Quaxli

Top Contributor
Nun ja, Klassennamen schreibt man schon mal groß. Und wenn jemand JPanels als Grafikelemente verwendet, stellen sich mir immer die Fußnägel auf (= persönliche Abneigung, man kann es schon verwenden...) ;)
Das Ganze ist etwas überfrachtet - meiner Ansicht nach und der Ball fliegt bei mir immer raus. Aber für einen ersten Versuch nicht schlecht.

Ich habe mal qick & dirty ein Gegenbeispiel zusammengefrickelt. Verwende es oder laß es ;)

Ein paar Anmerkungen dazu.
- Das Ganze ist in eine Klasse gequetscht, aber nicht uwesentlich unübersichtlicher als Dein Code ;). Üblicherweis würde man für Schläger und Ball wohl eigene Klassen als sinnvoll erachten (die könnten auch von Rectangle erben)
- die Ballbewegung ist einfach auf einen Integer-Wert festgebacken. Üblicherweise würde man die Zeit seit dem letzten Schleifendurchlauf mitberücksichtigen, wodurch die Bewegung flüssiger erscheint.
- es sind nicht alle Fehlerquelle ausgeschaltet - u. U. könnte der Ball auch rausfliegen.
- ein GameOver-Bedingung fehlt.
- und noch ein paar Unschönheiten mehr... . Aber es funzt ;)


Code:
package src;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Example extends JPanel implements Runnable, MouseMotionListener{
	//Klassenanmen schreibt man groß!!!!

	private static final long serialVersionUID = 1L;
	
	JFrame frame;   //das Fenster
	Rectangle bat;  //der Schläger
	Rectangle ball; // der Ball
	
	int dx = 2; //Bewegungsänderung in x
	int dy = 2; //Bewegungsänderung in y
	
	public static void main(String[] args){
		new Example(); //diese Klasse initialisieren
	}
	
	
	public Example(){
		
		//Fenster erzegeugen
		frame = new JFrame("Beispiel");
		frame.setSize(500,500);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(this);	//die Instanz dieses JPanels in Fenster packen
		
		bat = new Rectangle(10,250,10,60);  //Schläger initialisieren
		ball = new Rectangle(200,200,10,10); // Ball initialisieren

		setBackground(Color.black); //Panel-Hintergrudn schwarz
		addMouseMotionListener(this); //MouseMotionListener ins JPanel packen
		
		frame.setVisible(true); //alles anzeigen
		
		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(20);  //Päuschen
			} catch (InterruptedException e) {}
			
			repaint();  //Repaint
		}
		
	}
	
	private void checkCollision(){
		
		if(bat.intersects(ball)){  //Standard-Methode von Rectangle intersetcts(Rectangle r)
			dx *= -1;                //dx negieren, damit Ball wegfliegt
			ball.x += dx;            //einmal bewegen, damit Kollisionsabfrage nicht nochmal greift
		}
		
	}
	
	private void moveBall(){
		
		//wenn linke Seite des Balls nicht mehr sichtbar. X-Bewegung ändern
		if(ball.x<0){
			dx = 2;
		}
		
		//das selbe in Grün für die rechte Seite
		if(ball.x+ball.width >getWidth()){
			dx = -2;
		}
		
		//Beide Bedingung für analog für Y
		if(ball.y<0){
			dy = 2;
		}
		
		if(ball.y+ball.height>getHeight()){
			dy = -2;
		}

		//simple Ballbewegung - unabhängig vom GameLoop
		ball.x += dx;
		ball.y += dy;

	}


	@Override
	//Hier wird gemalt
	protected void paintComponent(Graphics g) {
		super.paintComponent(g); //super-Aufruf nicht vergessen.
		
		//Schläger
		g.setColor(Color.red);
		g.fillRect(bat.x, bat.y, bat.width, bat.height);
		
		//Ball
		g.setColor(Color.blue);
		g.fillOval(ball.x, ball.y, ball.width, ball.height);
		
	}


	//MouseMotionListener-Methoden
	public void mouseDragged(MouseEvent e) {
		
	}


	//einfache Übernahme y-Wert auch wenn Schläger nach unten verschwinden kann.
	public void mouseMoved(MouseEvent e) {
		bat.y = (int) e.getPoint().getY();
	}


	
	
	

}

<edit>
AAAARGH! Falschen Code kopiert. Ich Depp... . Jetzt paßt's
</edit>
 

H3llGhost

Bekanntes Mitglied
Hallo,

danke für den Code ... ;)
Der gefällt mir aber warum Rectangle?
Und was ist das überhaupt?

Desweiteren ruckelt der Ball beim Bewegen des schlägers ...
Woran kann das Liegen?
 
G

Guest

Gast
Quaxli hat gesagt.:
Und wenn jemand JPanels als Grafikelemente verwendet, stellen sich mir immer die Fußnägel auf (= persönliche Abneigung, man kann es schon verwenden...)

Begründ das mal bitte. Weil ich hab in meinem Game ne Menge JPanels drin, eventuell machst du mir nen Umstieg schmackhaft.

Danke schomal
 

0x7F800000

Top Contributor
Naja, wenn man nicht vorhat, irgendwelche weiteren Komponenten auf dem JPanel zu plazieren, dann kann man auch gleich die abstraktere JComponent klasse nehmen, dann verschwendet man keinen speicher für irgendwelche listen für child-komponenten, die man eh nicht braucht. Und dann ist die liste der alternativen bei der automatischen wort-ergänzungs-dingens kürzer, kann man ein bisschen schneller das nötige finden. Also, man braucht keine begründung gegen JPanels als reine grafikkomponenten, es gibt einfach keine argumente dafür. :)
 

Quaxli

Top Contributor
Du willst doch nur ein Rechteck zeichnen, daß den Schläger darstellt und die Kollision ermitteln? Warum als ein JPanel verwenden, daß dafür viel zu überfrachtet ist. Was bringt Dir die Klasse JPanel, was in Rectangle nicht drin ist? Sogar die Kollisionserkennung kriegst Du schon mitgeliefert - zumindest, wenn Sie auf Basis von Rectangles stattfindet und wenn Du pixelgenaue Kollision willst, ist ein JPanel auch nicht besser geeignet.

Die Bewegung ruckelt so, weil ich einen fixen Wert für die Veränderung der x- und y-Werte angegeben habe. Üblicherweise mißt man die Zeit, die der letzte Schleifendurchlauf benötigt hat und zieht diesen zur Berechnung der Bewegung heran. Nicht jeder GameLoop benötigt ja gleich lange für den Schleifendurchlauf, weil manchmal durch if-Bedingungen Code ausgeführt wird und manchmal nicht. Daher macht es Sinn, die Bewegung an die benötigte Zeit für den Schleifendurchlauf zu koppeln, damit die Bewegung flüssiger wird. (Soweit ich gesehen habe, ruckelt es bei Dir auch, nur verläßt der Ball zu schnell das Spielfeld).

Ich habe mal den Code verändert, so daß die Bewegung jetzt flüssiger läuft:


Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Example extends JPanel implements Runnable, MouseMotionListener{
   //Klassenanmen schreibt man groß!!!!

   private static final long serialVersionUID = 1L;
   private static int SPEED = 75;
   
   JFrame frame;   //das Fenster
   Rectangle bat;  //der Schläger
   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){
      new Example(); //diese Klasse initialisieren
   }
   
   
   public Example(){
      
      //Fenster erzegeugen
      frame = new JFrame("Beispiel");
      frame.setSize(500,500);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(this);   //die Instanz dieses JPanels in Fenster packen
      
      bat = new Rectangle(10,250,10,60);  //Schläger initialisieren
      ball = new Rectangle(200,200,10,10); // Ball initialisieren

      setBackground(Color.black); //Panel-Hintergrudn schwarz
      addMouseMotionListener(this); //MouseMotionListener ins JPanel packen
      
      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(20);  //Päuschen
         } catch (InterruptedException e) {}
         
         repaint();  //Repaint
      }
      
   }
   
   private void checkCollision(){
      
      if(bat.intersects(ball)){  //Standard-Methode von Rectangle intersetcts(Rectangle r)
         dx *= -1;                //dx negieren, damit Ball wegfliegt
      }
      
   }
   
   private void moveBall(){
      
      //wenn linke Seite des Balls nicht mehr sichtbar. X-Bewegung ändern
      if(ball.x<0){
         dx = SPEED;
      }
      
      //das selbe in Grün für die rechte Seite
      if(ball.x+ball.width >getWidth()){
         dx = -SPEED;
      }
      
      //Beide Bedingung für analog für Y
      if(ball.y<0){
         dy = SPEED;
      }
      
      if(ball.y+ball.height>getHeight()){
         dy = -SPEED;
      }

      

      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
   //Hier wird gemalt
   protected void paintComponent(Graphics g) {
      super.paintComponent(g); //super-Aufruf nicht vergessen.
      
      //Schläger
      g.setColor(Color.red);
      g.fillRect(bat.x, bat.y, bat.width, bat.height);
      
      //Ball
      g.setColor(Color.blue);
      g.fillOval(ball.x, ball.y, ball.width, ball.height);
      
   }


   //MouseMotionListener-Methoden
   public void mouseDragged(MouseEvent e) {
      
   }


   //einfache Übernahme y-Wert auch wenn Schläger nach unten verschwinden kann.
   public void mouseMoved(MouseEvent e) {
      bat.y = (int) e.getPoint().getY();
   }


   
   
   

}
 

Marco13

Top Contributor
@Andrey: JComponent erbt schon von Container. Tatsächlich ist es so, dass JPanel keine zusätzlichen Fields enthält, ausser denen, die schon von JComponent, Container und Component geerbt werden.
Aber das sind einige.
Irgendwann hatte ich das (genau in diesem Zusammenhang) schon mal rein interesshalber aufgedröselt. Darum nochmal die 83 Gründe, warum man NICHT "mal kurz" von JComponent erben sollte, weil man irgendeinen Furz-Sprite zeichnen will:
Code:
    private boolean isAlignmentXSet;
    private float alignmentX;
    private boolean isAlignmentYSet;
    private float alignmentY;
    protected transient ComponentUI ui;
    protected EventListenerList listenerList = new EventListenerList();
    private transient ArrayTable clientProperties;
    private VetoableChangeSupport vetoableChangeSupport;
    private boolean autoscrolls;
    private Border border;
    private int flags;
    private InputVerifier inputVerifier = null;
    private boolean verifyInputWhenFocusTarget = true;
    transient Component         paintingChild;
    private JPopupMenu popupMenu;
    private InputMap focusInputMap;
    private InputMap ancestorInputMap;
    private ComponentInputMap windowInputMap;
    private ActionMap actionMap;
    private boolean aaText;
    int ncomponents;
    Component component[] = new Component[0];
    LayoutManager layoutMgr;
    private LightweightDispatcher dispatcher;
    private transient FocusTraversalPolicy focusTraversalPolicy;
    private boolean focusCycleRoot = false;
    private boolean focusTraversalPolicyProvider;
    private transient Set printingThreads;
    private transient boolean printing = false;
    transient ContainerListener containerListener;
    transient int listeningChildren;
    transient int listeningBoundsChildren;
    transient int descendantsCount;
    transient ComponentPeer peer;
    transient Container parent;
    transient AppContext appContext;
    int x;
    int y;
    int width;
    int height;
    Color       foreground;
    Color       background;
    Font        font;
    Font        peerFont;
    Cursor      cursor;
    Locale      locale;
    transient GraphicsConfiguration graphicsConfig = null;
    transient BufferStrategy bufferStrategy = null;
    boolean ignoreRepaint = false;
    boolean visible = true;
    boolean enabled = true;
    boolean valid = false;
    DropTarget dropTarget;
    Vector popups;
    private String name;
    private boolean nameExplicitlySet = false;
    private boolean focusable = true;
    private int isFocusTraversableOverridden = FOCUS_TRAVERSABLE_UNKNOWN;
    Set[] focusTraversalKeys;
    private boolean focusTraversalKeysEnabled = true;
    Dimension minSize;
    boolean minSizeSet;
    Dimension prefSize;
    boolean prefSizeSet;
    Dimension maxSize;
    boolean maxSizeSet;
    transient ComponentOrientation componentOrientation = ComponentOrientation.UNKNOWN;
    boolean newEventsOnly = false;
    transient ComponentListener componentListener;
    transient FocusListener focusListener;
    transient HierarchyListener hierarchyListener;
    transient HierarchyBoundsListener hierarchyBoundsListener;
    transient KeyListener keyListener;
    transient MouseListener mouseListener;
    transient MouseMotionListener mouseMotionListener;
    transient MouseWheelListener mouseWheelListener;
    transient InputMethodListener inputMethodListener;
    transient RuntimeException windowClosingException = null;
    long eventMask = AWTEvent.INPUT_METHODS_ENABLED_MASK;
    private PropertyChangeSupport changeSupport;
    boolean isPacked = false;
    transient private Object privateKey = new Object();
    private int boundsOp = ComponentPeer.DEFAULT_OPERATION;

Ein Schläger oder ein Ball brauchen keine focusTraversalPolicy und keinen vetoableChangeSupport ... eigentlich brauchen sie fast NICHTS, ausser x,y,width,height....
 

0x7F800000

Top Contributor
OMFG :shock: nun ja, dass es soviel zeugs ist... doch, hab ich mir schon fast gedacht :D
Aber wenn ich irgendetwas zeichnen will, dann muss ich das doch auf einer Komponente machen, die wenigstens von JComponent erbt, ansonsten kann ich das nicht mal ins Fenster einfügen.
Ich hab mir die hier geposteten Codes nicht angegugt (zu lang) aber wenn der OP jeden sprite auf einem eigenen JPanel gezeichnet hat, statt alles auf einmal auf einem einzigen JComponent, dann ist das natürlich unsinn :toll:
 

Quaxli

Top Contributor
Über die Frage hast Du nicht ernsthaft nachgedacht, als Du sie hingeschrieben hast, oder? ;)
Bzw. hat es einen Unterschied gemacht, als Du es ausprobiert hast? ;)

Soviel zum Wink mit dem Zaun(pfahl)...
 

H3llGhost

Bekanntes Mitglied
Doch eigentlich schon ...
Und ich habe es gerade auch ausprobiert was passiert, also ich sehe keinen Unterschied.

Ich habe im Internet gelesen, dass man für das Spiel zwei Threads machen sollte, damit es ruckelfreier läuft.
Für mich ist aber die Frage wie ...
 

Quaxli

Top Contributor
Natürlich macht das keinen Unterschied, ob Du prüfst ob sich Ball und Schläger oder Schläger und Ball überschneiden b)

Nur weil es im Internet steht, muß es ja nicht stimmen ;)
2 wie im Beispiel reichen eigentlich.
 

H3llGhost

Bekanntes Mitglied
Du hast zwei Threads?
Habe ich garnicht gesehen ... :D

Also ich habe folgendes nun geschrieben, aber ich verstehe nicht warum der Ball nicht weiterläuft ...

EDIT:
Habe meinen Fehler gefunden ...
Ich habe vergessen eine While-Schleife einzubinden ... ;)
Werde mich nun um die Kollisionserkennung kümmern ...

Leider ruckelt es bei mir immer noch und die Kollsionserkennung ist auch nicht sauber ... :(
Woran kann das liegen?
Die Berechnung der Zeit und die Kollisionserkennung kommen von dir ... ;)
Die sind noch im Original Zustand ... :D

So hier nochmal der Code.
Mir ist aufgefallen, dass der Ball nicht immer mit gleicher Geschwindigkeit fliegt ... :shock:
Und ich habe keine Ahnung warum der so extreme Unterschiede hat ...

Hauptklasse:
Code:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class ppGUI extends JFrame implements MouseMotionListener
{
  private JPanel einPanel;
  private ppDraw ppd;
  public ppGUI()
  {
    setTitle("Ping Pong eXTr3m3");                             //Titel des Rahmen
    setSize(500,500);                                  //Größe des Rahmen in Pixel
    setDefaultCloseOperation(EXIT_ON_CLOSE);           //Schließt den Rahmen
    setResizable(false);

    einPanel = new JPanel();                           //Erzeugen der "Leinwand"
    einPanel.setLayout(null);
    einPanel.setBackground(Color.BLACK);
    
    ppd = new ppDraw();
    ppd.setBounds(50,50,400,300);
    
    addMouseMotionListener(this);

    //am Ende:
    einPanel.add(ppd);
    add(einPanel);
    setVisible(true);                                //Sichtbar machen
  }

  public void mouseDragged(MouseEvent e)
  {

  }

  public void mouseMoved(MouseEvent e)
  {
    ppd.bat.y=(e.getY()-100);
  }

  public static void main(String args[])
  {
    ppGUI pp = new ppGUI();
  }
}

Drawklasse:
Code:
import javax.swing.*;
import java.awt.*;

class ppDraw extends JPanel implements Runnable
{
  Thread runner;
  Thread runner2;
  Rectangle bat, ball;
  ppBall ppb;

  public ppDraw()
  {
    setBackground(Color.WHITE);

    bat = new Rectangle(0,250,10,60);  //Schläger initialisieren
    ball = new Rectangle(200,200,10,10); // Ball initialisieren

    ppb = new ppBall(ball, this);

    runner = new Thread(this);
    runner.start();
  }
  
  @Override protected void paintComponent(Graphics g)
  {
    super.paintComponent(g);
      if (bat.y < 0) bat.y = 0;
      //Schläger
      g.setColor(Color.red);
      g.fillRect(bat.x, bat.y, bat.width, bat.height);

      //Ball
      g.setColor(Color.blue);
      g.fillOval(ball.x, ball.y, ball.width, ball.height);
  }
  
   private void checkCollision(){

      if(bat.intersects(ball)){  //Standard-Methode von Rectangle intersetcts(Rectangle r)
         ppb.dxnega();                //dx negieren, damit Ball wegfliegt
      }

   }

  public void run()
  {
    while(true)
    {
     checkCollision();
     try {
     Thread.sleep(20);  //Päuschen
     } catch (InterruptedException e)
     {
      System.out.println(e);
     }
     repaint();
    }
  }
}

Ballklasse:
Code:
import javax.swing.*;
import java.awt.*;

public class ppBall implements Runnable
{

  private static int SPEED = 100;

  int dx = SPEED; //Bewegungsänderung in x
  int dy = SPEED; //Bewegungsänderung in y
  long time = 0;
  Rectangle ball;
  ppDraw p;
  Thread runner;

  public ppBall(Rectangle b, ppDraw pp)
  {
    ball = b;
    p = pp;
    time = System.nanoTime();
    runner = new Thread(this);
    runner.start();
  }

  public void dxnega()
  {
    dx *= -1;
  }

  public void run()
  {
      while (p.isVisible())
      {
      //wenn linke Seite des Balls nicht mehr sichtbar. X-Bewegung ändern
      if(ball.x<0){
         dx = SPEED;
      }

      //das selbe in Grün für die rechte Seite
      if(ball.x+ball.width>p.getWidth()){
         dx = -SPEED;
      }

      //Beide Bedingung für analog für Y
      if(ball.y<0){
         dy = SPEED;
      }

      if(ball.y+ball.height>p.getHeight()){
         dy = -SPEED;
      }

      long delta = System.nanoTime() - time;  //Zeit seit dem letzen Schleifendurchlauf
      time = System.nanoTime();  //für die nächste Runde Zeit merken

      System.out.println(delta/1e9);

      ball.x += dx*(delta/1e9); //Bewegung in Abhängigkeit der für den Loop benötigten Zeit.
      ball.y += dy*(delta/1e9);
     try {
     Thread.sleep(15);  //Päuschen
     } catch (InterruptedException e)
     {
      System.out.println(e);
     }
      }
  }
}
 

Quaxli

Top Contributor
Natürlich habe ich zwei Threads. Was macht wohl dieser Code:

Code:
    runner = new Thread(this);
    runner.start();

;)

Ich gucke mal bei dem anderen Problem. Übrigens Klassennamen werden immer noch GROSS geschrieben.
 

Quaxli

Top Contributor
So, hab's gefunden. Typischer Anfängerfehler -> zu viele Threads. ;) Ich habe mal bißchen was geändert, schau's Dir an:

Code:
import javax.swing.*;
import java.awt.*;

public class PPDraw extends JPanel implements Runnable{
  Thread runner;
  Thread runner2;
  Rectangle bat, ball;
  PPBall ppb;
  long time = 0;
  long delta = 0;

  public PPDraw(){
  	
    setBackground(Color.WHITE);

    bat = new Rectangle(0,250,10,60);  //Schläger initialisieren
    ball = new Rectangle(200,200,10,10); // Ball initialisieren

    ppb = new PPBall(ball, this);

    runner = new Thread(this);
    runner.start();
    
    time = System.nanoTime();
  }
 
  @Override protected void paintComponent(Graphics g)
  {
    super.paintComponent(g);
      if (bat.y < 0) bat.y = 0;
      //Schläger
      g.setColor(Color.red);
      g.fillRect(bat.x, bat.y, bat.width, bat.height);

      //Ball
      g.setColor(Color.blue);
      g.fillOval(ball.x, ball.y, ball.width, ball.height);
  }
 
   private void checkCollision(){

      if(bat.intersects(ball)){  //Standard-Methode von Rectangle intersetcts(Rectangle r)
         ppb.dxnega();                //dx negieren, damit Ball wegfliegt
      }

   }

  public void run()
  {
    while(true){
    	
     computeDelta();	//delta kann man öfter gebrauche und berechnet man zentral für alle Methoden
     checkCollision();
     ppb.moveBall(delta);
     
     
     try {
     Thread.sleep(20);  //Päuschen
     } catch (InterruptedException e)
     {
      System.out.println(e);
     }
     repaint();
    }
  }
  
  private void computeDelta(){
  	delta = System.nanoTime()-time;
  	time = System.nanoTime();
  }
}


Code:
import java.awt.*;

public class PPBall {

  private static int SPEED = 100;

  int dx = SPEED; //Bewegungsänderung in x
  int dy = SPEED; //Bewegungsänderung in y
  long time = 0;
  Rectangle ball;
  PPDraw p;
  Thread runner;

  public PPBall(Rectangle b, PPDraw pp)  {
    ball = b;
    p = pp;
  }

  public void dxnega()
  {
    dx *= -1;
  }

  public void moveBall(long delta){
  	
      //wenn linke Seite des Balls nicht mehr sichtbar. X-Bewegung ändern
      if(ball.x<0){
         dx = SPEED;
      }

      //das selbe in Grün für die rechte Seite
      if(ball.x+ball.width>p.getWidth()){
         dx = -SPEED;
      }

      //Beide Bedingung für analog für Y
      if(ball.y<0){
         dy = SPEED;
      }

      if(ball.y+ball.height>p.getHeight()){
         dy = -SPEED;
      }


      ball.x += dx*(delta/1e9); //Bewegung in Abhängigkeit der für den Loop benötigten Zeit.
      ball.y += dy*(delta/1e9);


  }
}
 

H3llGhost

Bekanntes Mitglied
Hallo,

danke für den Code!
Aber es sind immer noch so extreme Schwankungen in der Geschwindigkeit ...
Und warum funktioniert die Kollsionsabfrage nicht sauber? Ich verstehe das nicht ...
 

H3llGhost

Bekanntes Mitglied
So das Problem mit der Kollsionsabfrage habe ich nun gelöst, in dem ich einfach die checkCollision() in die Klasse PPBall gepackt habe und desweiteren die Funktion dxnega() angepasst.
Nun brauche ich aber nochmals deine Hilfe ...
Wenn der Ball die Wand berührt habe ich ja noch die dx- und dy-Werte mit denen kann ich ja den Winkel ausrechnen es müssten mit den trigonometrischen Funktionen gehen ...
Dann habe ich ja den Winkel und mit Hilfe des Winkels kann ich doch dx und dy neu ausrechnen nur halt mit richtigen Abprallwinkel oder? :)
Was meinst du?
 

H3llGhost

Bekanntes Mitglied
Hallo Leute,

ich bins mal wieder ...
ich habe vor das Spiel über Netzwerk laufen zu lassen und dazu habe ich einen eigenen Server geschrieben.
Dieser Server läuft auch eigentlich ganz gut ... :)
Aber nun meine Frage:
Sollte man für jeden Client einen eigenen Thread erstellen?
Oder wir würdet ihr das machen?
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
I QR code in Java selber generieren Java Basics - Anfänger-Themen 5
T code so schreiben das er von sich selber anpasst (code soll die anzahl aller bustaben bestimmen) Java Basics - Anfänger-Themen 16
J Methode selber schreiben Java Basics - Anfänger-Themen 5
W Einfachen, ein beliebiges Zeichen oft erkennenden Regex Parser selber schreiben - wie vorgehen? Java Basics - Anfänger-Themen 12
P Selber Programmieren lernen oder Uni? Java Basics - Anfänger-Themen 12
M Erste Schritte Ordner im selber Verzeichnis wählen Java Basics - Anfänger-Themen 1
J Kann eine .jar sich selber Löschen? Java Basics - Anfänger-Themen 5
hello_autumn Potenz selber berechnen, Rekursiv. Java Basics - Anfänger-Themen 6
B Variablen im Java-Code selber "ausrechnen" Java Basics - Anfänger-Themen 8
G Erste Schritte Galerie mit Ajax selber schreiben Java Basics - Anfänger-Themen 23
B Datentypen Wurzel auf n stellen nach dem Komma selber zeihen -> double zu schlecht Java Basics - Anfänger-Themen 19
Anfänger2011 selber geschriebene Programme nutzen Java Basics - Anfänger-Themen 11
K Erste Schritte Kalender selber erstellen? Java Basics - Anfänger-Themen 3
S Rückgabetyp - Objekt gibt sich selber zurück Java Basics - Anfänger-Themen 4
B zwei Jar Dateien selber paketname Java Basics - Anfänger-Themen 9
S Generics - CaseInsensitiveMap selber schreiben? Java Basics - Anfänger-Themen 5
S Welche Collection kann sich selber sortieren? Java Basics - Anfänger-Themen 8
M Alle Objecte mit selber Vairable Java Basics - Anfänger-Themen 3
C Exception selber schreiben Java Basics - Anfänger-Themen 4
H2SO3- wie kennt ein button sich selber? Java Basics - Anfänger-Themen 21
TiME-SPLiNTER mehrere HTTPRequests mit selber Verbindung Java Basics - Anfänger-Themen 2
G Gleichzeitiges Verarbeiten von Variablen 2er Obj. selber Kl. Java Basics - Anfänger-Themen 5
C Objekt soll sich selber einer Variablen zuweisen. Java Basics - Anfänger-Themen 6
G Die Klasse Stack selber schreiben. Java Basics - Anfänger-Themen 2
P Button selber entwerfen bzw. suchen Java Basics - Anfänger-Themen 3
U Klasse ruft sich selber auf? Java Basics - Anfänger-Themen 2
M Eine Klasse die sich selber öffnen kann. Java Basics - Anfänger-Themen 4
P Gibt es einen anderen Weg um "{}" in IntelliJ zu schreiben? Java Basics - Anfänger-Themen 5
M Daten aus errechneter Methode in Datenbank(SQLite) schreiben Java Basics - Anfänger-Themen 60
W Objekte einer ArrayList in txt-datei schreiben mit Paths? Java Basics - Anfänger-Themen 2
M Test auf Exceptions schreiben Java Basics - Anfänger-Themen 11
F Wie kann ich eine Funktion schreiben, die nur in bestimmten Fällen einen Wert zurückgibt? Java Basics - Anfänger-Themen 5
HolyFUT JSON String in Java Object schreiben - Anführungszeichen rauskriegen? Java Basics - Anfänger-Themen 17
java-starter Erste Schritte Mit While Schleifen Programme schreiben Java Basics - Anfänger-Themen 4
berserkerdq2 Wo ist der SInn, dass man den Stream, den ich zum Schreiben nutze, outputstream nenne? Java Basics - Anfänger-Themen 5
viktor1 Methoden Methode schreiben static void readText (String filename) {...} zu WordHistogramSample.java Java Basics - Anfänger-Themen 13
D JAVA Programm schreiben Java Basics - Anfänger-Themen 46
S In Datei schreiben in Java? Java Basics - Anfänger-Themen 1
J Dateien lesen und schreiben Java Basics - Anfänger-Themen 5
berserkerdq2 IO Streams logfile erstellen und Sachen schreiben wie? Java Basics - Anfänger-Themen 2
M Text in Datei schreiben Java Basics - Anfänger-Themen 9
berserkerdq2 Wie würde man einen regulären Ausdruck in Java schreiben, der prüft, dass zwei bestimtme Zahlen nicht nebeneinadner sind? Java Basics - Anfänger-Themen 3
S Bot schreiben Java Basics - Anfänger-Themen 1
J Kann ich mein Programm so schreiben? Java Basics - Anfänger-Themen 4
C Brauche Hilfe beim Schreiben eines Programmes :/ Java Basics - Anfänger-Themen 1
C Brauche Hilfe um ein Programm zu schreiben Java Basics - Anfänger-Themen 8
C XML Datei schreiben Java Basics - Anfänger-Themen 14
S Objekte von zwei klassen in zwei verschiedene Textdateien schreiben Java Basics - Anfänger-Themen 5
T Methode schreiben, die einem Array ein Stringelement hinzufügt, wenn dieses noch nicht enthalten ist. Java Basics - Anfänger-Themen 6
T Inhalt aus TextField in Attribut einer Instanz schreiben Java Basics - Anfänger-Themen 5
NeoLexx Datenströme Lesen und Schreiben einer Textdatei Java Basics - Anfänger-Themen 2
B Inputstream in file schreiben? Java Basics - Anfänger-Themen 23
L Test-Methoden schreiben Java Basics - Anfänger-Themen 13
L x und y Koordinaten in ein Array schreiben Java Basics - Anfänger-Themen 7
J Programm schreiben Java Basics - Anfänger-Themen 5
G In Datei schreiben Java Basics - Anfänger-Themen 1
B Werte aus einem Unterprogramm in ein Array schreiben Java Basics - Anfänger-Themen 2
J Methode zur Ausgabe eines Dreiecks aus Sternen schreiben? Java Basics - Anfänger-Themen 2
M Plateau Prgramm schreiben Java Basics - Anfänger-Themen 2
G Programm schreiben: Zahl (n) eingeben, 1+1/n+2/n+3/n+....+n/n Java Basics - Anfänger-Themen 8
J String in Datei schreiben Java Basics - Anfänger-Themen 4
L Kleine Hilfe beim Schreiben eines Programmes benötigt :D Java Basics - Anfänger-Themen 40
J Lesen und schreiben in eine Datei(Anfänger- Dateizugriffe) Java Basics - Anfänger-Themen 3
S JSON Datei schreiben und lesen Java Basics - Anfänger-Themen 3
B CSS Klassen in eine Liste schreiben Java Basics - Anfänger-Themen 4
H projekt 1 code schöner schreiben. Java Basics - Anfänger-Themen 25
O findRoot Methode schreiben in einem Intervall Java Basics - Anfänger-Themen 31
O Erste Schritte Eigene charAt(i) Methode schreiben Java Basics - Anfänger-Themen 10
X Arrays untereinander schreiben Java Basics - Anfänger-Themen 4
K Probleme beim Programm schreiben - Lesen von Dateiinhalten -zaehlen von Wörtern/ Buchstaben Java Basics - Anfänger-Themen 4
A Erste Schritte Bitte helfen sie mir diese Programm zu schreiben Java Basics - Anfänger-Themen 12
L Input/Output Konsole in Farben schreiben Java Basics - Anfänger-Themen 4
P Strings in String Array schreiben Java Basics - Anfänger-Themen 13
Y kann jemand die Terme mit Zahlen schreiben ?? Java Basics - Anfänger-Themen 4
L Input/Output In Farben schreiben Java Basics - Anfänger-Themen 3
x-tshainge In gespeicherter Datei schreiben? Java Basics - Anfänger-Themen 7
F Schreibprogramm nur markierten Text in kursiv oder fett schreiben Java Basics - Anfänger-Themen 3
A JSON Lesen und Schreiben. Java Basics - Anfänger-Themen 3
L Eigene Exception schreiben bei zu langem Array Java Basics - Anfänger-Themen 10
karlmasutra Ausgabe in ein Array schreiben Java Basics - Anfänger-Themen 14
T Zufällige Matrix in neue Matrix schreiben Java Basics - Anfänger-Themen 6
F Mehrere Zeilen zu einer Zeile zusammenfügen und in eine Datei schreiben Java Basics - Anfänger-Themen 1
J Mit JSF Formular in Datenbank schreiben Java Basics - Anfänger-Themen 3
amazinglife77 Input/Output Lesen/Schreiben Properties: in eclipse geht, als JAR nicht Java Basics - Anfänger-Themen 4
S Wie muss ich die Generische Methode schreiben? Java Basics - Anfänger-Themen 6
R Input/Output Dateinamen aus Verzeichnis in Datei schreiben Java Basics - Anfänger-Themen 3
E Wert in Textfeld schreiben Java Basics - Anfänger-Themen 1
P Erste Schritte Schreiben in eine Datei Java Basics - Anfänger-Themen 9
M Java Roboter schreiben mit Eclipse Java Basics - Anfänger-Themen 3
J Probleme beim schreiben von Dateien Java Basics - Anfänger-Themen 5
M Rekursion schreiben Java Basics - Anfänger-Themen 16
M In einer Datei schreiben - Java Java Basics - Anfänger-Themen 3
D Eine einfache Verschlüsselung schreiben Java Basics - Anfänger-Themen 3
X Streams und Ausgabe - lässt sich das einfacher schreiben oder schöner schreiben? Java Basics - Anfänger-Themen 5
T Erste Schritte Schreiben Sie eine Klasse Zeit, die eine Zeitdauer in Minuten beschreibt. Die Anzahl Minuten verwalt Java Basics - Anfänger-Themen 3
G Java Objektorientiert schreiben Java Basics - Anfänger-Themen 1
D Daten mit Apache POI in eine Excel Datei schreiben Java Basics - Anfänger-Themen 5
N Lambda Ausdrücke richtig schreiben Java Basics - Anfänger-Themen 4
B Schreiben von zu vielen Einträgen in einer Datenbank Java Basics - Anfänger-Themen 9
F Wert in Linux auf die Konsole schreiben Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben