Pong - Spiel Ball Geschwindigkeit Problem

Robinson97

Grünschnabel
Hallo Forum :),

ich bin dabei ein Pong - Spiel mit Java zu Programmieren, was auch ganz gut funktioniert. Das Problem ist nur, dass mein Ball jede Runde schneller wird, obwohl ich an der Geschwindigkeit des Balles nicht verändere.
Hier ist mein Quellcode:

Main:
Java:
 public static void main(String[] args) {
    new ping("ping");
   
    while(spielablauf) {
      try {
        if (tor) {
          start = false;
          start = countdown();
          tor = false;
        }  

        if (start) {
          start_to_move_ball = true;
          set_ball_to_start();
          tor = gameplay();
          start = false;
        }
       
      } catch (IllegalStateException e) {
        System.err.printf("\fEin Problem ist mit dem Timer aufgetreten !!!%n" +
        e);
      }
    }
  }

Die Funktion Gameplay:

Java:
 public static boolean gameplay() {
    //jede Sekunde bewegt sich der Ball vorwäts
   
    TimerTask action = new TimerTask() {
      public void run() {
        if (start_to_move_ball) {
          speed = 1;
          y1 -= speed;
          x1 += speed;                
        }
       
        if (ball_up == false) {
          start_is_over();
          y1 += speed;
          x1 += speed;
          System.out.println("Apprall");  
        }
       
        if (y1 <= 0) {
          ball_up = false;
        }
       
        ball.setBounds(x1, y1, 35, 41);
       
        if (ball.getX() == 560) {
          tor = true;
          player_1.point();
          lab_3.setText(player_1.getPoints());
          set_ball_to_start();
        }
       
        if (ball.getX() == 0) {
          tor = true;
          player_2.point();
          points_p2.setText(player_2.getPoints());
        }    
        if (tor) {
          set_ball_to_start();
          ball_up=true;
        }
        //ball.setBounds(x,y,width,height);
      }
    };
   
    Timer caretaker = new Timer();
    caretaker.schedule(action, 1000, 15);
   
    if(tor){
      timer.cancel();
    }
    return tor;
  }

Sobald das Spiel startet wird die Main ausgeführt und das gesamte Spiel wird durch eine dauerschaleife ausgeführt. Tor ist am Anfang auf True gesetzt und somit startet das Spiel am Anfang einen Countdown über eine Funktion. Ín der Funktion befindet sich ein Countdown der vpn 3 auf 0 zählt und anschleißend start auf true setzt. Somit fängt die Funktion Gameplay an zu laufen...

Die funktion startet immer damit den Ball anhand der Koordinaten nach rechts oben zu bewegen. Da ich noch keine richtige funktion zum Aprallen sowohl von der Wand. als auch von dem Schläger habe, regelt das nur eine if Bedingung. Sonst gibt es halt nur noch die Funktion zum Tor von Spieler 1 oder 2 und eine zurücksetzung des Balles nach einem Tor

Ich hoffe ihr könnt mir weiterhelfen ! Danke;)
 
Code:
if(tor){
      timer.cancel();
}

was macht denn der Timer den du da cancels ? Wenn dein Spiel nach jedem Tor schneller wird ist hier die Ursache zu finden.
 
Danke für den Hinweis :)
Mit dieser if Bedingung habe ich versucht die Timertask anzuhalten, um zu versuchen ob dadurch der Ball langsamer wird, hat aber nichts gebracht. Außerdem fällt mir gerade auch auf, dass diese if Bedingung unnötig ist ;)
 
Frage: wann wird das Spiel schneller ?
Wenn es ein Tor gibt (meine vermutung)
wenn dar Ball abprallt und richtungswechsel macht oder
ohne verbindung zum Spielgeschehen - also eine geichmässige Beschleunigung ?
 
Der Ball wird immer dann schneller, wenn ein Tor gefallen ist.

Ich habe es in der Zwischenzeit hinbekommen die Aprallfunktion von der Wand und dem Schläger einzubauen (Code siehe unten), nur Leider hat sich das Problem dadurch leider nicht gelöst :(

Update der gameplay-funktion

Java:
public static boolean gameplay() {
   
    TimerTask action = new TimerTask() {
      public void run() {
        if(start_to_move_ball)  {
         
          if ((y1+70) > 400) {
            speed_y=-2;
          }    
         
          if(y1<0) {
            speed_y=2;
          }
         
         
          if ((ball.getX()+35) >= 560) {
            tor = true;
            player_1.point();
            lab_3.setText(player_1.getPoints());
            set_ball_to_start();
          }
         
          if (ball.getX() <= 0) {
            tor = true;
            player_2.point();
            points_p2.setText(player_2.getPoints());
            set_ball_to_start();
          }
         
          y1 += speed_y;
          x1 += speed_x; 
          ball.setBounds(x1, y1, 35, 41);
          check_collision_with_label(ball);
         
          if (tor) {
            start_to_move_ball=false;
            set_ball_to_start();
          }
        }
      }
    };
   
    Timer caretaker = new Timer();
    caretaker.schedule(action, 1000, 20);
   
    if(tor){
       action.cancel();
      }
    return tor;
  }

public static void set_ball_to_start() {
    x1= 248;
    y1= 160;
    ball.setBounds(x1,y1, 35, 41);
  }
 
 
  public static void check_collision_with_label(JLabel ball){
    Rectangle ball_wall = new Rectangle(ball.getX(),ball.getY(),35,41);
    Rectangle player_wall_1 =  new Rectangle(40,player_bat_1.getY(),bat_width,bat_heigth);
    Rectangle player_wall_2 =  new Rectangle(500,player_bat_2.getY(),bat_width,bat_heigth);
   
    if(player_wall_2.intersects(ball_wall) || player_wall_1.intersects(ball_wall)){
      speed_x=speed_x*-1;
    }
  }
 
Erlich ich hätte es verstanden wenn das System pro Tor langsamer wird :)

aber ok ich denke das problem ist das du pro Ballwechsel immer eine neue Timertask aufmachst.

Ich würde für die TimerTask eine eigene Classe schreiben.

Code:
class BallTimer extends TimerTask {
public void run() {
// dein code
}
public void setFlags(boolean a, boolean b ) {
//übergebe hier deine abfragewerte
}
public boolean getTor() {
//werte zurück geben
}
}

und im Main das :
Code:
// snipp
new ping("ping");
    BallTimer action = new BallTimer();

    while(spielablauf) {
//
tor = gameplay(action);
//

den eventuell auch aus gameplay auslagern, mal testen

Timer caretaker = new Timer();
caretaker.schedule(action, 1000, 15);


Warnung keine begründbare logische entscheidung - der Bauch spricht :)

Nachtrag : nach längeren nachdenken: nach dem ersten Tor doppel so schnell beim zweiten Tor dreifach usw.
Begründung alle laufenden TaskTimer greifen auf gleiche Variablen zu und machen daher das System schneller :)
 
Zuletzt bearbeitet:
Stimmt, klingt logisch !;)
Das mit der neuen Klasse werde ich morgen mal ausprobieren. Bei dem Hinweis mit dem Nachtrag habe ich erstmal versucht die Timertask (also den caretaker) zu chanceln, damit diese sich nicht mehr überschreiben, aber irgendwie klappt das nicht. Nur mal so als Frage nebenbei, falls du sie mir beantworten kannst, warum funktioniert das eigentlich nicht ?
Wenn ich die Timertask beende ,dürfte sie doch eigentlich im Programm gar nicht mehr aktiv sein und somit müsste doch eigentlich beim erneuten Aufruf der Funktion gameplay() eine ganz neue TimerTask gestartet werden, damit währe doch ein mehrfach zugriff auf Variabeln unmöglich oder ?o_O
 
Erklärung:
Unerwartetes Verhalten. Ich vermute mal das es so läuft:
Dadurch das der TimerTask ein HintergrundThread ist, läuft der weiter auch wenn Bezugsvariable
action eigentlich schon einen neuen wert hat und läuft einfach weiter bis Java den Speicher
neu nutzt.
Oder Java räumt nie den eigendlich freien Speicher auf, da die Methode static ist.

Aber wissen nee - nur wilde Vermutungen :)
 
Vielen Dank @melmager für deine Hilfe :)

Es lag tatsächlich daran wie du gesagt hast, dass die Timertask immer wieder auf die selben Variablen zugreift und der Ball dadurch immer schneller wird. Die Lösung hierfür war eigentlich gar nicht mal so schwer ich musste nur den Codeblock:
if(tor){
caretaker.cancel();
}

in die Timertask action hineinverschieben und schon hats funktioniert. Ohne deinen Hinweis wäre ich aber nicht soweit gekommen :cool:

Danke
 
Zurück