Entwickler-Ecke

Alle Sprachen - Alle Plattformen - Java Pong


LINUS19 - So 12.11.17 20:23
Titel: Java Pong
Hallo,
Ich habe in Java ein Pong Spiel programmiert, das Problem ist das der Ball manchmal vom Schläger abprallt und manchmal nicht.
Ich hoffe das jemand helfen kann.

LINUS19


Palladin007 - So 12.11.17 21:13

Also, ich denke, dir kann sicher jemand helfen ;)


Symbroson - So 12.11.17 22:26

Wir wissen ja nicht, wie genau du Pong implementiert hast, wie groß alles ist, wie du zeichnest etc. Es wäre also sinnvoll, wenn du deinen Quellcode hier teilen würdest.


Palladin007 - So 12.11.17 23:11

In kurz:
Wir wissen nichts.
Wir wissen nicht einmal, was das Problem ist, nur das Resultat des Problems.
Entsprechend hoch ist auch die Wahrscheinlichkeit, hier eine Antwort auf die Frage zu bekommen ;)

Ein Tipp: Debugging ;)
Gerade bei solchen Problemen ist das das beste Hilfsmittel


LINUS19 - Mo 13.11.17 19:13

Hier der Code :


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Pong extends JPanel {
     
      int x = 30, y = 300; // Anfangskoordinaten Schläger 1
      int Px = 200, Py = 200; //Anfangskoordinaten Ball
      int x2 = 770, y2 = 300; //Anfangskoordinaten Schläger 2
      int dPx = 10, dPy = 10; // Geschwindigkeit Ball
      boolean Spieler1o = false; // Pfeiltaste oben am Anfang Taste nicht gedrückt
      boolean Spieler1u = false; // Pfeiltast unten
      boolean Spieler2o = false;
      boolean Spieler2u = false;

      public Pong() {
          setPreferredSize(new Dimension(800, 600)); // Fenstergröße

          Ball neu = new Ball();
          neu.start(); // Thraed Ball wird gestartet
          Schläger s = new Schläger(); // Thread Schläger wird gestartet
          s.start();
      }

      public void paint(Graphics gr) { // beiden Schläger und Ball
          Graphics2D g = (Graphics2D) gr; // werden gezeichnet
          g.setColor(Color.WHITE);
          g.fill(g.getClipBounds()); // damit die Zeichnung überschrieben wird
          g.setColor(Color.BLACK);
          g.fillRect(x, y, 10, 80); // Ball und Schläger werden gezeichnet
          g.fillOval(Px, Py, 30, 30);
          g.fillRect(x2, y2, 10, 80);
      }

      public void PositionSchläger1() { // wird auf AnfangsPosition gesetzt
          x = 30;
          y = 300;
          repaint();
      }

      public void PositionBall() { // AnfangsPosition
          Px = 200;
          Py = 200;
          repaint();

      }

      public void PositionSchläger2() // Anfangsposition{
          x2 = 760;
          y2 = 300;
          repaint();
      }

      class Ball extends Thread { // thread für Ball
          void bewegen() {
              Px = Px + dPx; //die Bewegung
              Py = Py + dPy;

              if (Px < 0) { // Ball prallt von der Wand ab
                  Px = 0;
                  dPx = -dPx;
              }
              if (Py < 0) {  // Ball prallt von der Wand ab
                  Py = 0;
                  dPy = -dPy;
              }
              if (Py > 570) { // Ball prallt von der Wand ab
                  Py = 570;
                  dPy = -dPy;
              }
              if (Px > 770) { // Ball prallt von der Wand ab
                  Px = 770;
                  dPx = -dPx;
              }

              if (Px == 40 && Py >= y && Py <= y + 80) { // Hier soll er vom Schläger1 abprallen
                  Px = 40;
                  dPx = -dPx;                
              }

              if (Px == 740 && Py >= y2 && Py <= y2 + 80) {//// Hier soll er vom Schläger2 abprallen
                                                             
                  Px = 740;
                  dPx = -dPx;
                  dPy = -dPy;
              }
              repaint();
          }

          public void run() { // Thread für Ball

              while (!isInterrupted()) {

                  bewegen();
                  try {
                      Thread.sleep(50);
                  } catch (InterruptedException e) {
                      return;
                  }
              }
          }
      }

      class Schläger extends Thread implements KeyListener {
          Schläger() {
              addKeyListener(this); // KeyListenr wird hinzugefügt
          }

          public void run() {

              while (true) { // solange Spieler Taste drückt
                                  //wird Schläger bewegt
                if (Spieler1o == true) { // Bewegung Schläger1
                      y -= 12;
                  }
                  if (Spieler1u == true) {
                      y += 12;
                  }
                  if (Spieler2o == true) { // Bewegung Schläger2
                      y2 -= 12;
                  }
                  if (Spieler2u == true) {
                      y2 += 12;
                  }
                 
                    if (y2 > 520) { // 600-80 wegen Schlägerlänge
                      y2 = 520; // Damit die Schläger nicht aus dem Bild verschwinden
                  }
                  if (y2 < 0) {
                      y2 = 0;
                  }
                  if (y < 0) {
                      y = 0;
                  }
                  if (y > 520) {
                      y = 520;
                  }
                  repaint();
                  try {
                      Thread.sleep(50);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }

          public void keyPressed(KeyEvent e) { // Spieler 1 hier wird geguckt ob Taste gedrückt
              if (e.getKeyCode() == KeyEvent.VK_W) {
                  Spieler1o = true;
              }
              if (e.getKeyCode() == KeyEvent.VK_S) {
                  Spieler1u = true;
              }
             
              if (e.getKeyCode() == KeyEvent.VK_UP) { // Spieler2 hier wird geguckt ob Taste gedrückt
                  Spieler2o = true;
              }
              if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                  Spieler2u = true;
              }
          }

          public void keyReleased(KeyEvent e) { // Hier ob Taste wieder losgelassen
              // wenn ja stoppt Schlägerbewegung
            if (e.getKeyCode() == KeyEvent.VK_W) {
                  Spieler1o = false;
              }
              if (e.getKeyCode() == KeyEvent.VK_S) {
                  Spieler1u = false;
              }
              if (e.getKeyCode() == KeyEvent.VK_UP) {
                  Spieler2o = false;
              }
              if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                  Spieler2u = false;
              }
          }

          public void keyTyped(KeyEvent e) {
          }
      }
}


und die Hauptklasee:

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

public class Fenster extends JFrame {
   private Pong pong = new Pong();

   public Fenster() {
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
     getContentPane().add(pong);

     pong.PositionBall();
     pack();
     getRootPane();setVisible(true);

     pong.PositionSchläger2();
     pong.PositionSchläger1();
     pong.setFocusable(true);

   }

   public static void main(String[] args) {
     new Fenster();

   }
}


hoffe ihr könnt damit was anfangen.

VG
LINUS19

Moderiert von user profile iconChristian S.: Code-Tags hinzugefügt


Christian S. - Mo 13.11.17 21:02

Du prüfst exakt auf Px == 40. Was passiert, wenn der Ball so schnell ist, dass er bereits "hinter" dem Schläger ist?


LINUS19 - Mo 13.11.17 21:11

Ok, danke und wie soll ich das am besten beheben?


Christian S. - Mo 13.11.17 21:16

Welche Idee hast Du denn dazu? Tipp: Schau mal, wie das drum herum in Deinem Sourcecode gemacht wird.


LINUS19 - Mo 13.11.17 21:47

Ich komme gerade wirklich nicht darauf, habe schon einige Sachen probiert so z.B Px>=30 && Px <= 40, hat aber auch nichts genützt.


LINUS19 - Mo 13.11.17 22:05

Habs jetzt hinbekommen danke nochmal für die Mühen.

LINUS19


Symbroson - Mo 13.11.17 22:28

Selbst wenn es jetzt (anscheinend) funktioniert, befürchte ich immernoch, dass deine Kollisionsabfrage(n) nicht stimmen. Am meisten zwischen dem Ball und den Schlägern, aber auch bei den Oberen und unteren Wänden. Da musst du nämlich den Durchmesser des Balles noch mit einbeziehen, sonst können Ball und Schläger/Wand sich noch immer überlappen.

Außerdem solltest du evtl für die Größen aller Objekte variablen anlegen - also Ballradius bzw. Durchmesser, Schlägerhöhe und Breite und evtl auch Fensterhöhe und Breite.
Ich hab leider noch nie mit Java ernsthaft gearbeitet, deswegen weiß ich nicht wie es mit Makros steht - dann bräuchtest du nichtmal extra Variablen.

Da ich jetzt aber eine sehr sehr hilfreiche Vorlage habe, kann ich deinen Code mal für mich so modifizieren, wie ich das umsetzte. Wenn du willst, kann ich dann den modifizierten Code auch mal posten, aber ich will dir ja nichts vorschreiben oder so ;)

LG,
Symbroson


LINUS19 - Mo 13.11.17 22:33

Den Radius des Balls hatte ich mit einberechnet, das abprallen vom Rand hatte vorher ja auch schon funktioniert.


LINUS19 - Mo 13.11.17 22:39

Aber poste dann gerne mal deine Code.


LINUS19 - Mo 13.11.17 22:49

Das habe ich auch noch verändert, falls der Ball sehr weit an den Rand vom Schläger kommt.

if(Px <= 40 && Py >= y-15 && Py <= y +95) vorher :if(Px <= 40 && Py >= y && Py <= y +80)
if(Px>=740 && Py>=y2-15 && Py<= y2+95 vorher: if(Px <= 740 && Py >= y && Py <= y +80)


Symbroson - Mo 13.11.17 23:04

Warum hast du eigentlich die Tastatur und die Bewegung in zwei separate Threads ausgelagert? du kannst doch die Tastatur auch vor der Bewegung abfragen, oder nicht?
Zusätzlich renderst du das Bild unnötig oft und das wirkt sich hart auf die Performance aus. Das kann auch einmalig nach der Bewegung aller Objekte geschehen.
Also Frage ist warum du das so gemacht hast


Symbroson - Di 14.11.17 02:36

Ich hab es endlich geschafft. :D
Ich muss dir auf jeden Fall sehr Danken, weil du mir die gelegeneit gegeben hast mal 'was richtiges' mit Java zu machen. Sonst hab ich mich ehrlich gesagt eher geweigert Java auch nur anzugucken :roll:
Hab also einige Erkenntnisse aufgrund deines Programms gewinnen können ^^

Ich habe versucht das unverständlichste so gut wie möglich zu erklären, solltest du aber dennoch irgendwelche Fragen haben, frag natürlich!
Auch wenn du oder jemand anderes irgendwelche Vorschläge bzgl. des Codes machen möchte - warum man zB dies und jenes nicht machen sollte uä. - immer her damit!

Was du auf jeden Fall noch implementieren solltest ist der Score, was damit einhergeht das Spiel zu resetten wenn der Ball die linke bzw rechte Wand Berührt. Aber das überlasse ich deiner Kreativität ;)

LG,
Symbroson


Christian S. - Di 14.11.17 08:35

Zwischenbemerkung: Ich habe .java gerade als Dateianhangserweiterung erlaubt, sodass man die nicht mehr als .txt anhängen muss.


LINUS19 - Di 14.11.17 15:27

Hallo,
Das ist mein erstes Java Programm mit Grafik und Animation und dementsprechend noch ziemlich unausgereift. Könntest du das mit dem Bild rendern nochmal genauer erklären, wie ich es verbessern kann. Der Punkte Zähler usw. sollte ja nicht so schwer sein.

Ich hatte auch noch die Idee wenn ich das Spiel fertig habe, das ganze über ein Netzwerk zumachen für 2 Spieler an beliebigen Orten,doch ein Problem könnte dann sein mit den schnellen Bewegungen und der Zeitverzögerung( anders als z.B. bei Tictactoe).
Ist das ganze dann überhaupt für einen Anfänger machbar ?.

LG
LINUS19


Symbroson - Di 14.11.17 15:54

Bzgl dem Rendern: ursprünglich hattest du ja zwei Threads, einen für den Ball und einen für die Tastatur.
Beispiel: Ich drücke eine Beliebige Taste -> die Callback-Funktion wird aufgerufen. Die bewegt dann den Schläger, und Zeichnet (Rendert) alles. Dabei hat sich nur ein bis 2 Objekte bewegt - der Ball, die Score-Anzeige usw haben sich aber nicht verändert.
Der Ball aber wird ebenfalls periodisch bewegt und rendert alles, aber die Schläger bleiben nach wie vor an derselben Position.
Da die mit Abstand am zeitaufwändigste Methode das Zeichnen ist, wird die Framerate an sich nicht verändert, aber es werden eben manchmal nur halb so viele Aktionen pro Rendervorgang ausgeführt wie eigentlich möglich wären.
Deshalb solltest du erst alle Objekte bewegen, Kollisionsabfrage etc. und danach alles mit einem Mal rendern.

Außerdem wäre es in Zukunft sinnvoll die Zeitdifferenz zwischen dem letzten und dem Aktuellen Rendervorgang einzukalkulieren, da diese erstens zwischen verschiedenen Grafikkarten und Rechnern sehr stark variieren kann.
Wenn dein Rechner zB. etwas langsamer ist, erhöhst du die Geschwindigkeiten etwas, wenn dann aber jemand anderes mit einem besonders leistungsstarken Rechner dein Spiel spielt ist es viel zu schnell und unspielbar.
Aber auch zT. durch andere Prozesse kann das Spiel unregelmäßig gebremst werden.
Die Zeitdifferenz dient also dann dazu, diese Unterschiede und Unregelmäßigkeiten auszugleichen.
Da das aber wie du sagtest dein erstes Grafische Spiel ist, solltest du das vorerst missachten, aber später mal auf jeden Fall einhalten.
Außerdem mal ein Lob dafür, dass dein erstes entwickeltes Spiel nicht Minecraft oder so werden soll :D Ist ja ein allgemein bekanntes Problem, dass Einsteiger in die Spieleentwicklung gleich RPG, 3D, Multiplayer und alles Mögliche umsetzen wollen. ^^


Mit dem Nezwerkzeug bzw online multiplayer hab ich selber nicht viel am Hut. Ich hab nur mal mit Bluetooth ein Multiplayerspiel für Android gemacht. Das zumindest war relativ schnell.
Wenn du aber mal logisch überlegst was bei deinem PC für Netzwerkgeschwindigkeiten stehen, von kB (1000) oder sogar MB (Mio Byte) pro Sekunde - ist es relativ Wahrscheinlich, dass das keine Hürde für dein Spiel darstellen sollte. Viele Spiele im Internet bzw. aus dem Play/Appstore beweisen das. Und wenn man bedenkt, dass viele Tools auch über Internet Sprache in Echtzeit übermitteln...

Die Programmatische umsetzung ist natürlich wieder ein ganz anderes Problem - Da müsstest du mal nachschauen was es für Java-Module dafür gibt - 'Sockets' kannst du beispielsweise suchen. Ansonsten hat vielleicht jemand hier andere tolle Vorschläge für Java-Bibliotheken.

Sorry dass das so ein Roman geworden ist ^^ Hoffentlich ist es dadurch wenigstens etwas Verständlicher.

LG,
Symbroson


LINUS19 - Di 14.11.17 18:35

Ok, danke das hat mir wirklich sehr weiter geholfen. Mit der Netzwerkprogrammierung schaue ich mir dann einfach ein paar Tutorials an.

LG
LINUS19


LINUS19 - Mi 15.11.17 16:24

Hallo,
Könntet ihr mir noch ein paar Ideen für Spiele geben?
Symbroson, nur aus Interesse was hast du schon für Spiele programmiert?

LG
LINUS19


Symbroson - Mi 15.11.17 17:23

Nunja, ich hab mich an ziemlich vielen probiert. Ich kann dir ja mal den Link zu dem DropBox-Ordner mit den Projekten geben:
https://www.dropbox.com/sh/0i6c7w50elnu1s6/AABo5e4n_EMkmadcg-NAL5S5a?dl=0

(Hab im Folgenden bisschen Lebensgeschichte, sowie ne kleine Werbung verpackt, hoffe das macht niemandem was aus ^^)

Allerdings muss ich anmerken, dass das weder mit Delphi, noch mit C, C++ oder Java, sondern mit JavaScript programmiert wurde. Das liegt größtenteils daran, dass ich in den Anfängen meines Entwicklerdaseins nur ein Smartphone hatte. Nagut ganz zu beginn hatte ich nen programmierbaren, grafischen Taschenrechner den ich in der 7. Klasse glaube ich bekommen hatte. Der ist aber sehr langsam, aber trotzdem von mir sehr strapaziert worden ^^ (daher Casio Basic in meiner Sprachen-Liste)
Dann hatte ich irgendwann mal eine App namens DroidScript entdeckt, mit der man sehr einfach und überall programmieren, Apps entwickeln und als apk exportieren konnte. (Ja ich mach jetzt mal ein wenig Werbung ;)
Damit hab ich dann lange gearbeitet, zT auch heute noch, weil es bisher die einzige Möglichkeit für mich ist, überall zu Programmieren und einfach Apps zu schreiben. Dadurch sind viele Projekte entstanden. Zu Beginn natürlich einfache Dinge - das erste war glaube ich EatIt, sone Art agar.io, nur ganz primitiv ^^ (Man steuert einen Kreis der andere kleine Kreise 'verschlingen' muss um groß zu werden) Dann natürlich auch die 'Standard-Minigames wie TicTacToe, Pong, Snake, MineSweeper, Tetris und zwei Varianten des Spiels, bei dem gleichartige Objekte sich zerstören (bei mir Polygons) einmal mit 3 gleichen nebeneinander, und einmal mit gleiche verbinden.
Dann war ich schon ziemlich gut und hab etwas komplexere Kachelbasierte Spiele gemacht - dazu Zählen aus dem DB-Ordner zB. RPGDemo bzw Labyrinth und Tanks, außerdem die durch Wettbewerbe entstandenen Spiele Tankerous, PipeTracker und Icey. Das sind dann schon sozusagen eigens erfundene Spiele.

Ich hoffe, ich hab dich durch diese Fülle nicht abgeschreckt, eigentlich soll das ja irgendwie inspirieren ^^
Ich gehe davon aus, dass du ein Smartphone hast - da kannst du dir ja einfach mal paar .apk dateien aus dem DropBox Ordner /APKs/Games/ herunterladen, ausprobieren und dir welche aussuchen zum nachprogrammieren. Die Quellcodes sind in den anderen Ordnern, ein bisschen nach Themen sortiert. Die Spiele speziell unter /Games/
Dort sind .spk Dateien drin - das sind nichts mehr als .zip Dateien. Also einfach umbenennen und entpacken. Die Hauptquelldatei hat den gleichen Namen wie das Projekt selbst, die ganzen Ressourcenalso Bilder, (Sprites, ) Sound etc. Sind in Unterordnern zu finden. Wie gesagt gedchrieben ist das alles in JavaScript, die IDE bietet aber noch ein 'app' Objekt an mit dem man alles Android-Spezifische machen kann, also Layouts, Buttons, Images, Bluetooth und vieles vieles mehr. Du kannst das also nicht so einfach im Browser ausführen ;) (Ausnahme Icey - da gibts noch ne extra Version dafür)
Natürloch ist alles da drin ohne Lizenz, bzw. WTFPL lizensiert ;)

es gilt natürlich wieder 'Fragen? Fragen!

LG,
Symbroson


LINUS19 - Mi 15.11.17 18:44

Hab mir mal ein paar von deinen Apps aufs Handy geladen und bin echt beeindruckt, weisst du ob s für Java auch so einen Apk Konverter gibt? Ich habe irgendwie schon ziemliche Probleme dabei Java Programme auf den Desktop zu exportieren und von dort zu starten...

LG
LINUS19


Symbroson - Mi 15.11.17 19:00

Also apks bekommst du mit Java nur relativ schwierig, wenn du keine IDE benutzt. Das Ausführen ist aber eigentlich ganz einfach: öffne die Eingabeaufforderung, wechsle zum Ordner mit deinen .java Dateien ('CD C:\<pfad>') umd kompiliere die java-Dateien mit javac (javac Main.java). Damit werden .class Dateien generiert, deren Haiptklasse (aus der Haupt-Quelldatei) die dann mit java ausführen kannst (java Main.class)
Setzt natürlich voraus, dass du javac und java in nem PATH Ordner hast


LINUS19 - Mi 15.11.17 19:06

Ich benutzte eclipse als IDE


Symbroson - Mi 15.11.17 19:10

Eclipse müsste Java eigentlich auch so ausführen können - wenn du die Java-Version hast. Kommt denn da ne Fehlermeldung oder irgendwas? Oder was ist da genau das Problem?


LINUS19 - Mi 15.11.17 19:15

Ich exportiere das Programm als Jar file, es erscheint dann auf dem Desktop, doch wenn ich drauf klicke passiert nichts.


Symbroson - Mi 15.11.17 19:19

Hm da kann ich dir im Moment leider nicht weiterhelfen, Ich kenne nur den Weg über die Konsole oder eben durch die IDE selbst.


Christian S. - Mi 15.11.17 19:22

Hallo,

für separate Fragen bitte auch separate Topics erstellen, damit wir hier ein bisschen die Ordnung wahren. Vielen Dank! :)

Viele Grüße
Christian