dappdada Geschrieben 21. Februar 2012 Teilen Geschrieben 21. Februar 2012 Servus, ich habe gestern angefangen mich ein wenig mit der Applet-Programmierung in Java zu beschäftigen. Habe dazu ein Tutorial gemacht in dem man ein Spiel mit einem Ball programmieren sollte. Ich hab das Programm etwas ausgebaut und wollte damit ein PingPong-Spiel basteln. Das Spiel funktioniert an sich sehr gut. Das einzige Problem ist, dass die Funktion bounds() (in der Klasse ball) sehr zufällige Ergebnisse, beim berechnen der neuen Flugrichtung ergibt. Beim einen mal funktioniert es tadellos bei zweiten mal bleibt der Ball in der Wand hängen... Kann jemand meinen Fehler entdecken??? Vielen Dank schon mal. Anbei mein Code: Main Klasse: import java.applet.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; @SuppressWarnings("serial") public class Main extends Applet implements Runnable, KeyListener, MouseListener, MouseMotionListener{ // Instanzvariablen private int speed; // Threadgeschwindigkeit public int mausYPosition; boolean isStoped = true; // Zeigt an, ob das Spiel gestopt ist (true) oder läuft (false) // Thread Thread th; // Thread in dem das Spiel läuft // Audiodateien AudioClip shotnoise; // Speichert die Wav - Datei Gun, die nach Schuss abgespielt wird AudioClip hitnoise; // Speichert die Wav - Datei hit, die nach einem Treffer abgespielt wird AudioClip outnoise; // Speichert die Wav - Datei error, die nach einem Treffer abgespielt wird // Neue Schrift Font f = new Font ("Serif", Font.BOLD, 20); // Variablen für die Doppelpufferung private Image dbImage; private Graphics dbg; // Deklaration der Objektreferenzen Player player1; Player player2; Ball ball; // init - Methode wird beim Laden des Applets aufgerufen public void init(){ this.setSize(800, 800); // Setzen der Hintergrundfarbe setBackground (Color.black); // Setzten der Schrift setFont (f); // Speed wird von Parameter speed des Applets bestimmt if (getParameter ("speed") != null){ speed = Integer.parseInt(getParameter("speed")); } else speed = 15; // Laden der Bilder und Audiodateien und einmaliges Abspielen, um längere Ladezeiten während des Spiels zu vermeiden hitnoise = getAudioClip (getCodeBase() , "gun.au"); hitnoise.play(); hitnoise.stop(); shotnoise = getAudioClip (getCodeBase() , "miss.au"); shotnoise.play(); shotnoise.stop(); outnoise = getAudioClip (getCodeBase() , "error.au"); outnoise.play(); outnoise.stop(); player1 = new Player("Player1", 20, this.getHeight()/2, 20, 80, Color.GREEN); player2 = new Player("Player2", this.getWidth()-40,this.getHeight()/2,20,80,Color.ORANGE); ball = new Ball(10, this.getWidth()/2, this.getHeight()/2, 4, Color.YELLOW, outnoise, player1, player2); addKeyListener(this); addMouseListener(this); addMouseMotionListener(this); } // Start - Methode, hier beginnt das Applet zu laufen public void start (){ // Schaffen eines neuen Threads, in dem das Spiel läuft th = new Thread (this); th.start (); } // Stop - Methode, hier wird das Applet gestopt public void stop (){ th.interrupt(); } // Destroy - Methode wird beim endgültigen Verlassen der Internetseite aufgerufen public void destroy() { } /** Paint - Methode dient dem Zeichnen von Elementen im Applet und wird z.B. bei Bewegung des Browserfensters und durch den Aufruf repaint() aufgerufen */ public void paint (Graphics g){ // Wenn noch Leben übrig sind if (player1.getLives() >= 1 && player2.getLives() >= 1){ //Ränder malen g.setColor(Color.gray); //oben g.fill3DRect(0, 0, this.getWidth(), 20, true); //unten g.fill3DRect(0, this.getHeight()-20, this.getWidth(), 20, true); //links g.fill3DRect(0, 0, 20, this.getHeight(), true); //rechts g.fill3DRect(this.getWidth()-20, 0, 20, this.getHeight(), true); //Tore malen g.setColor(getBackground()); //links g.fillRect(0, this.getHeight()/2-(this.getHeight()/2/2), 20, this.getHeight()/2); //rechts g.fillRect(this.getWidth()-20, this.getHeight()/2-(this.getHeight()/2/2), 20, this.getHeight()/2); // Punktestand und übrige Leben g.setColor (Color.yellow); //Spieler 1 g.drawString (player1.getName() + "Score: " + player1.getScore(),100, 17); g.drawString ("Lives: " + player1.getLives(),250, 17); player1.DrawPlayer(g); //Spieler 2 g.drawString (player2.getName() + "Score: " + player2.getScore(),500, 17); g.drawString ("Lives: " + player2.getLives(),650, 17); player2.DrawPlayer(g); ball.DrawBall(g); } // Wenn alle Leben verbraucht sind else if (player1.getLives() <= 0 || player2.getLives() <= 0){ g.setColor (Color.yellow); // Erreichte Punkte und game over if(player1.getLives() > player2.getLives()){ g.drawString ("Game over!", 130, 100); g.drawString ("You won", 90, 140); } else{ g.drawString ("Game over!", 130, 100); g.drawString ("You loose", 90, 140); } g.drawString ("Doubleclick on the Applet, to play again!", 20, 220); isStoped = true; // Zurücksetzen der isStoped Variablen, um wieder neu beginnen zu können } } @Override public void run() { // Erniedrigen der ThreadPriority um zeichnen zu erleichtern Thread.currentThread().setPriority(Thread.MIN_PRIORITY); while (true){ if ((player1.getLives() >= 1 && player2.getLives() >= 1) && !isStoped){ player1.setPosition(mausYPosition); ball.move(); ball.printBallPosition(); } repaint(); try{ // Stoppen des Threads für 10 Millisekunden Thread.sleep (speed); } catch (InterruptedException ex){ // do nothing } // Zurücksetzen der ThreadPriority auf Maximalwert Thread.currentThread().setPriority(Thread.MAX_PRIORITY); } } // Update - Methode, Realisierung der Doppelpufferung zur Reduzierung des Bildschirmflackerns public void update (Graphics g){ // Initialisierung des DoubleBuffers if (dbImage == null){ dbImage = createImage (this.getSize().width, this.getSize().height); dbg = dbImage.getGraphics (); } // Bildschirm im Hintergrund löschen dbg.setColor (getBackground ()); dbg.fillRect (0, 0, this.getSize().width, this.getSize().height); // Auf gelöschten Hintergrund Vordergrund zeichnen dbg.setColor (getForeground()); paint (dbg); // Nun fertig gezeichnetes Bild Offscreen auf dem richtigen Bildschirm anzeigen g.drawImage (dbImage, 0, 0, this); } @Override public void keyPressed(KeyEvent ev1) { } @Override public void keyReleased(KeyEvent ev2) { } @Override public void keyTyped(KeyEvent ev3) { } @Override public void mouseClicked(MouseEvent arg0) { // Spiel läuft if (!isStoped) { // machnix } // Wenn Spiel noch nicht gestartet ist, oder wieder gestartet wird else if (isStoped) { // Alle wichtigen Werte zurücksetzen isStoped = false; init (); } } @Override public void mouseEntered(MouseEvent arg0) { } @Override public void mouseExited(MouseEvent arg0) { } @Override public void mousePressed(MouseEvent arg0) { } @Override public void mouseReleased(MouseEvent arg0) { } @Override public void mouseDragged(MouseEvent arg0) { } @Override public void mouseMoved(MouseEvent evt) { mausYPosition = evt.getY(); } } Klasse Player: import java.awt.Color; import java.awt.Graphics; public class Player { // Deklaration der Variablen private int pos_x; // Variable für die X - Position des Balles private int pos_y; // Variable für die Y - Position des Balles private int breite; private int hoehe; private int score; // Punkte des Spielers private int lives; // Leben des Spielers private String name; // Name des Players // Farbe des Spielers Color color; /* Konstruktor */ public Player(String name, int pos_x, int pos_y, int breite, int hoehe, Color color){ lives = 10; score = 0; this.pos_x = pos_x; this.pos_y = pos_y; this.breite = breite; this.hoehe = hoehe; this.color = color; this.name = name; } /* Liefert den Namen zurück */ public String getName(){ return name; } /* Liefert die Punkte zurück */ public int getScore (){ return score; } /* Liefert die Leben zurück */ public int getLives (){ return lives; } /* Fügt Punkte hinzu */ public void addScore (int plus){ score += plus; } /* zieht Leben ab */ public void looseLife (){ lives --; } /* Liefert den x_wert zurück */ public int getX(){ return pos_x; } /* Liefert den y_wert zurück */ public int getY(){ return pos_y; } /* Setzt die Position */ public void setPosition(int y){ this.pos_y = y; } // Diese Methode zeichnet den Ball in das Spielfeld public void DrawPlayer (Graphics g){ g.setColor (color); g.fill3DRect(pos_x, pos_y, breite, hoehe, true); } } Klasse Ball: import java.applet.AudioClip; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.Random; public class Ball { /** Diese Klasse enthält alle Funktionen, die für die Bewegung, Konstruktion, Positionsbestimmung, Graphik und Abschiesen des Ball - Objektes von Bedeutung sind. */ // Deklaration der Variablen private Point koord; // Variable für die X und Y - Position des Balles private int radius; // Radius des Balles private double richtung; private int first_x; // Start x - Position private int first_y; // Start y - Position private int maxspeed; // Gibt den Maximalen Speed des Balles an // Deklaration der Konstanten (Grenzen des Applets bei einer Gesamtgröße von 380 x 380) private final int x_leftout = 30; private final int x_rightout = 770; private final int y_upout = 30; private final int y_downout = 770; // Farbe des Balles Color color; // AudioClip out AudioClip out; // Refferenz auf das Playerobjekt des Spiels Player player1; Player player2; // Erzeugen des zum Erzeugen von Zufallszahlen nötigen Objektes Random rnd = new Random (); // Construktor public Ball (int radius, int x, int y, int ms, Color color, AudioClip out, Player player1, Player player2){ // Initialisierung der Variablen this.radius = radius; koord = new Point(x,y); first_x = x; first_y = y; maxspeed = ms; richtung = richtung(); this.color = color; this.out = out; this.player1 = player1; this.player2 = player2; } private void bounds(boolean horizontal){ if(horizontal == true) { richtung = (Math.PI * 2) - richtung; } if(horizontal == false) { richtung = Math.PI - richtung; } while(richtung > (2 * Math.PI)){ richtung = richtung - (2 * Math.PI); } while(richtung < 0) { richtung = richtung + (2 * Math.PI); } } // Move - Methode, berechnet die Bewegung des Balls public void move (){ kiMove(); koord.x = (int) (koord.x + (maxspeed * Math.sin(Math.PI - richtung - (Math.PI / 2.0) / Math.sin((Math.PI / 2.0))))); koord.y = (int) (koord.y + (maxspeed * Math.sin(richtung) / Math.sin((Math.PI / 2.0)))); isOut(); } private double richtung(){ richtung = Math.random() * (Math.PI * 2); while((richtung > 1 && richtung < 2) || (richtung > 4 && richtung < 5) || (richtung > 2.5 && richtung < 3.5) || (richtung > 5.5 && richtung < 0.5)) richtung = Math.random() * (Math.PI * 2); return richtung; } public void ballStart(){ richtung = richtung(); koord.x = first_x; koord.y = first_y; } private boolean isOut (){ // Ball trifft Player1 if(koord.x <= 50 && (koord.y > player1.getY() && koord.y < player1.getY() + 80)){ bounds(false); return true; } // Ball trifft Player2 else if(koord.x >= 750 && (koord.y > player2.getY() && koord.y < player2.getY() + 80)){ bounds(false); return true; } // Tor für Player2 else if(koord.x <= 30 && (koord.y > 800/2/2 && koord.y < 800-(800/2/2))){ // Leben verlieren player1.looseLife(); ballStart(); return true; } // Tor für Player1 else if(koord.x >= 770 && (koord.y > 800/2/2 && koord.y < 800-(800/2/2))){ // Leben verlieren player2.looseLife(); ballStart(); return true; } // Ball im Linken Aus else if (koord.x < x_leftout){ bounds(false); out.play(); return true; } // Ball im rechten Aus else if (koord.x > x_rightout){ bounds(false); // Abspielen des Audioclips out.play(); return true; } // Ball im oberen Aus else if (koord.y < y_upout){ bounds(true); // Abspielen des Audioclips out.play(); return true; } // Ball im unteren Aus else if (koord.y > y_downout){ bounds(true); // Abspielen des Audioclips out.play(); return true; } else return false; } private void kiMove(){ int kiSpeed = 2; if((richtung > 3.93 && richtung < 4.71) || (richtung > 1.57 && richtung < 2.37)) kiSpeed += 1; if((koord.y) < player2.getY()+40) player2.setPosition(player2.getY() - kiSpeed); else player2.setPosition(player2.getY() + kiSpeed); } public void printBallPosition(){ System.out.println("Ball -> X: " + koord.x + " Y: " + koord.y); System.out.println("Play -> x: " + player1.getX() + " y: " + player1.getY()); } // Diese Methode zeichnet den Ball in das Spielfeld public void DrawBall (Graphics g){ g.setColor (color); g.fillOval (koord.x - radius, koord.y - radius, 2 * radius, 2 * radius); } } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 21. Februar 2012 Teilen Geschrieben 21. Februar 2012 Ohne das jetzt im Detail zu prüfen: Es reicht nicht, bei der Erkennung einer Kollision die Richtung zu ändern. Du musst auch die Position neu berechnen. Zur Berechnung: Math.sin((Math.PI / 2.0)) ist eine umständliche Schreibweise für 1, deine Koordinatenberechnung ließe sich vereinfachen zu koord.x = (int) (koord.x + maxspeed * Math.cos(richtung)); koord.y = (int) (koord.y + maxspeed * Math.sin(richtung)); [/code] Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dappdada Geschrieben 21. Februar 2012 Autor Teilen Geschrieben 21. Februar 2012 Ah ich glaube ich habe jetzt verstanden wie du das meinst. Es müsste doch auch funktionieren wenn ich in der Kollisionskontrolle sicherstelle, dass die Kollision die gerade aufgetreten ist (also zum Beispiel Kollision oben) erst wieder auftreten darf sobald eine andere Kollision aufgetreten ist. D.h. das Problem ist wenn der Ball zu weit in den Rand rutsch die Kollisionskontrolle unkontrolliert öfters hintereinander ausgeführt wird und der Ball so ins Abseits rutscht oder? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
dappdada Geschrieben 22. Februar 2012 Autor Teilen Geschrieben 22. Februar 2012 Oke ich habe die Methode isOut() (die Kollisionskontrolle) angepasst jetzt läuft es schon um einiges runder. Vielen Dank für den Denkanstoß. Falls jemand lust zu zoggen hat einfach die Klasse Ball im obigen Code ersetzten: import java.applet.AudioClip; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.Random; public class Ball { /** Diese Klasse enthält alle Funktionen, die für die Bewegung, Konstruktion, Positionsbestimmung, Graphik und Abschiesen des Ball - Objektes von Bedeutung sind. */ // Deklaration der Variablen private Point koord; // Variable für die X und Y - Position des Balles private int radius; // Radius des Balles private double richtung; private int first_x; // Start x - Position private int first_y; // Start y - Position private int maxspeed; // Gibt den Maximalen Speed des Balles an private String lastEvt = ""; // Speichert das zuletzt aufgetretene Event // Deklaration der Konstanten (Grenzen des Applets bei einer Gesamtgröße von 380 x 380) private final int x_leftout = 30; private final int x_rightout = 770; private final int y_upout = 30; private final int y_downout = 770; // Farbe des Balles Color color; // AudioClip out AudioClip out; // Refferenz auf das Playerobjekt des Spiels Player player1; Player player2; // Erzeugen des zum Erzeugen von Zufallszahlen nötigen Objektes Random rnd = new Random (); // Construktor public Ball (int radius, int x, int y, int ms, Color color, AudioClip out, Player player1, Player player2){ // Initialisierung der Variablen this.radius = radius; koord = new Point(x,y); first_x = x; first_y = y; maxspeed = ms; richtung = richtung(); this.color = color; this.out = out; this.player1 = player1; this.player2 = player2; } private void bounds(boolean horizontal){ if(horizontal == true) { richtung = (Math.PI * 2) - richtung; } if(horizontal == false) { richtung = Math.PI - richtung; } while(richtung > (2 * Math.PI)){ richtung = richtung - (2 * Math.PI); } while(richtung < 0) { richtung = richtung + (2 * Math.PI); } } // Move - Methode, berechnet die Bewegung des Balls public void move (){ kiMove(); koord.x = (int) (koord.x + maxspeed * Math.cos(richtung)); koord.y = (int) (koord.y + maxspeed * Math.sin(richtung)); isOut(); } private double richtung(){ richtung = Math.random() * (Math.PI * 2); while((richtung > 1 && richtung < 2) || (richtung > 4 && richtung < 5) || (richtung > 2.5 && richtung < 3.5) || (richtung > 5.5 && richtung < 0.5)) richtung = Math.random() * (Math.PI * 2); return richtung; } public void ballStart(){ richtung = richtung(); koord.x = first_x; koord.y = first_y; } private boolean isOut (){ // Ball trifft Player1 (evt = HPL) if(koord.x <= 50 && (koord.y > player1.getY() && koord.y < player1.getY() + 80) && !lastEvt.equals("HPL")){ lastEvt = "HPL"; bounds(false); return true; } // Ball trifft Player2 (evt = HPR) else if(koord.x >= 750 && (koord.y > player2.getY() && koord.y < player2.getY() + 80) && !lastEvt.equals("HPR")){ lastEvt = "HPR"; bounds(false); return true; } // Tor für Player1 (evt = GPL) else if(koord.x <= 30 && (koord.y > 800/2/2 && koord.y < 800-(800/2/2)) && !lastEvt.equals("GPL")){ lastEvt = "GPL"; // Leben verlieren player1.looseLife(); ballStart(); return true; } // Tor für Player2 (evt = GPR) else if(koord.x >= 770 && (koord.y > 800/2/2 && koord.y < 800-(800/2/2)) && !lastEvt.equals("GPR")){ lastEvt = "GPR"; // Leben verlieren player2.looseLife(); ballStart(); return true; } // Ball im Linken Aus (evt = BLEFT) else if (koord.x < x_leftout && !lastEvt.equals("BLEFT")){ lastEvt = "BLEFT"; bounds(false); out.play(); return true; } // Ball im rechten Aus (evt = BRIGHT) else if (koord.x > x_rightout && !lastEvt.equals("BRIGHT")){ lastEvt = "BRIGHT"; bounds(false); // Abspielen des Audioclips out.play(); return true; } // Ball im oberen Aus (evt = BTOP) else if (koord.y < y_upout && !lastEvt.equals("BTOP")){ lastEvt = "BTOP"; bounds(true); // Abspielen des Audioclips out.play(); return true; } // Ball im unteren Aus (evt = BBOTTOM) else if (koord.y > y_downout && !lastEvt.equals("BBOTTOM")){ lastEvt = "BBOTTOM"; bounds(true); // Abspielen des Audioclips out.play(); return true; } else return false; } private void kiMove(){ int kiSpeed = 2; if((richtung > 3.93 && richtung < 4.71) || (richtung > 1.57 && richtung < 2.37)) kiSpeed += 1; if((koord.y) < player2.getY()+40) player2.setPosition(player2.getY() - kiSpeed); else player2.setPosition(player2.getY() + kiSpeed); } public void printBallPosition(){ System.out.println("Ball -> X: " + koord.x + " Y: " + koord.y); System.out.println("Play -> x: " + player1.getX() + " y: " + player1.getY()); } // Diese Methode zeichnet den Ball in das Spielfeld public void DrawBall (Graphics g){ g.setColor (color); g.fillOval (koord.x - radius, koord.y - radius, 2 * radius, 2 * radius); } } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.