Hey Leute und zwar versuche ich gerade ein 2D Spiel zu Programmieren aber die Figur will sich nicht nach links oder rechts bewegen :(

Nenad2001

Mitglied
Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.Timer;

public class Frame extends JFrame implements ActionListener , KeyListener {

final private int screenWitdh = 800;
final private int screenHeight = 500;
private int maxJumpHeight;
private int jumpHeight;
private int gravitation;
private int spielerSpeed;
private int senkRechteGeschwindkeit;
private boolean isJumping;
private boolean isMovingLeft;
private boolean isMovingRight;
private boolean isShooting;
private Timer timer;
private List<Projektil> projektile;


Spieler spieler;   
Boden boden;   
Decke decke;
SeiteLinks links;
SeiteRechts rechts;


public Frame() {

    this.setSize(screenWitdh, screenHeight);
    this.setTitle("Shooting Game");
    this.setLayout(null);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.addKeyListener(this);
    this.setResizable(false);
    this.setLocationRelativeTo(null);
    this.setVisible(true);
    
    spieler = new Spieler(50 , 50 , 50 , 350);
    boden = new Boden(200, 800 , 0 , 400);
    decke =  new Decke(50 , 800 , 0 , 0);
    links = new SeiteLinks(355 ,10 , 5 , 50);
    rechts = new SeiteRechts(355 ,  50 , 785, 50);
    
    senkRechteGeschwindkeit = 15;
    maxJumpHeight = 50;
    jumpHeight = 20;
    gravitation = 20;
    spielerSpeed = 30;
    timer = new Timer(10, this);
    timer.start();
     projektile = new ArrayList<>();
}
    
    


public void paint(Graphics g) {
      super.paint(g);
      Graphics2D g2D = (Graphics2D) g;
    
      g2D.setPaint(Color.BLUE);
      g2D.drawRect(0, 0, screenWitdh, screenHeight);
      g2D.fillRect(0, 0, screenWitdh, screenHeight);

      g2D.setPaint(Color.BLACK);
      g2D.drawRect(spieler.getSpielerX(), spieler.getSpielerY(), spieler.getBreiteSpieler(), spieler.getHöheSpieler());
      g2D.fillRect(spieler.getSpielerX(), spieler.getSpielerY(), spieler.getBreiteSpieler(), spieler.getHöheSpieler());

      g2D.setPaint(Color.GREEN);
      g2D.drawRect(boden.getBodenx(), boden.getBodenY(), boden.getBreite(), boden.getHöhe());;
      g2D.fillRect(boden.getBodenx(), boden.getBodenY(), boden.getBreite(), boden.getHöhe());;

      g2D.setPaint(Color.WHITE);
      g2D.drawRect(decke.getDeckeX(), decke.getDeckeY(), decke.getBreite(), decke.getHöhe());
      g2D.fillRect(decke.getDeckeX(), decke.getDeckeY(), decke.getBreite(), decke.getHöhe());
      
      g2D.setPaint(Color.GREEN);
      g2D.drawRect(links.getSeiteLinksX(), links.getSeiteLinksY(), links.getBreite(), links.getHöhe());
      g2D.fillRect(links.getSeiteLinksX(), links.getSeiteLinksY(), links.getBreite(), links.getHöhe());
      
       g2D.setPaint(Color.GREEN);
      g2D.drawRect(rechts.getSeiteRechtsX(), rechts.getSeiteRechtsY(), rechts.getBreite(), rechts.getHöhe());
      g2D.fillRect(rechts.getSeiteRechtsX(), rechts.getSeiteRechtsY(), rechts.getBreite(), rechts.getHöhe());
    

      g2D.setPaint(Color.RED);
      for (Projektil projektil : projektile) {
          g2D.drawRect(projektil.getX(), projektil.getY(), projektil.getBreite(), projektil.getHöhe());
          g2D.fillRect(projektil.getX(), projektil.getY(), projektil.getBreite(), projektil.getHöhe());
      }

}






    @Override
    public void actionPerformed(ActionEvent e) {
        timer.start();
        Springen();
        MoveLeft();
        MoveRight();
        Kolision();   
        repaint();
       shoot();
    }


    @Override
    public void keyTyped(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_A) {
        isMovingLeft = false;
        
        }
        if(e.getKeyChar() == KeyEvent.VK_D) {
        isMovingRight = false;
        }
        if(e.getKeyChar() == KeyEvent.VK_SPACE) {
        isJumping = true;   
        }
        if(e.getKeyChar() == KeyEvent.VK_ENTER) {
        isShooting = true;   
        }
        
    }

    
    @Override
    public void keyPressed(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_A) {
            isMovingLeft = true;   
            
        }
            if(e.getKeyChar() == KeyEvent.VK_D) {
            isMovingRight = true;
            
            }
            if(e.getKeyChar() == KeyEvent.VK_SPACE) {
            isJumping = true;   
            
            }
            if(e.getKeyChar() == KeyEvent.VK_ENTER) {
            isShooting = true;   
            
            }
             repaint();   
    }
        
    
    @Override
    public void keyReleased(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_A) {
            isMovingLeft = false;
                
        }
            if(e.getKeyChar() == KeyEvent.VK_D) {
            isMovingRight = false;
            }
            if(e.getKeyChar() == KeyEvent.VK_SPACE) {
            isJumping = false;
            }
            if(e.getKeyChar() == KeyEvent.VK_ENTER) {
            isShooting = true;
            }
        
    }

    
public void Springen() {
    
if(isJumping ) {
spieler.setspielerY(spieler.getSpielerY() - jumpHeight - gravitation);

}

}
    
            



public void MoveLeft() {
    
if(isMovingLeft) {
    spieler.setspielerX(spieler.getSpielerX() -  spielerSpeed);
System.out.println("linksgedrückt");
}

}

public void MoveRight() {
    timer.start();
    if (isMovingRight) {
        spieler.setspielerX(spieler.getSpielerX() + spielerSpeed);
   System.out.println("rechtsgedrückt");
    }
    


}








public void Kolision() {

if( spieler.getSpielerY() < decke.getDeckeY() || spieler.getSpielerX() < decke.getDeckeX()) {
System.out.println("Du hast die decke getroffen");   
spieler.setspielerY(350);
}

if(spieler.getSpielerX() < links.getSeiteLinksX() && spieler.getSpielerX() > rechts.getSeiteRechtsX()) {
spieler.setspielerY(350);
}



}




// das ist bullshit das ist von chatgpt
public void shoot() {
    int projektilX = spieler.getSpielerX() + spieler.getBreiteSpieler() / 2;
    int projektilY = spieler.getSpielerY() + spieler.getHöheSpieler() / 2;
    int projektilSpeed = 5;

    Projektil projektil = new Projektil(projektilX, projektilY, projektilSpeed);
    projektile.add(projektil);
}





}
 

Jw456

Top Contributor
Eine deiner Methoden moverecht oder links ruft du ja gar nicht auf, wenn eine Taste gedrückt wird.
Die Ausgabe auf der Konsole wird somit auch nicht kommen.
 

Jw456

Top Contributor
Wo hast du das?
Du hast den listener, arber auf eine view hast du denn nicht gesetzt. Der wird mit sicherheit nie aufgrufen.
 

Nenad2001

Mitglied
Wo hast du das?
Du hast den listener, arber auf eine view hast du denn nicht gesetzt. Der wird mit sicherheit nie aufgrufen.
Achso tut mir leid ich dachte weil die Jump Methode auch klappt müssen die auch funktionieren weil die ja im selben listener stehen. Kannst du mir das genauer erklären wie ich das löse wäre echt korrekt :)
 

KonradN

Super-Moderator
Mitarbeiter
Also der Code ist extrem schwer lesbar, da Du alles in einer Klasse hast und dazu die Interfaces so überschreibst, so dass die Methoden halt unlesbare Namen haben. Hinzu kommt, dass Du Dich teilweise nicht an die Naming Conventions hältst. (Methoden fangen bitte alle klein an!)

Der Aufbau ist ja:
  • Deine Game-Loop hast Du mit dem Timer und der actionPerformed Methode. Das, was hier etwas auffällt: Warum startest Du den Timer öfters? Einmal gestartet sollte es doch ok sein.
  • Durch die Tastendrücke setzt Du dann Variablen, die in der Gameloop dann ausgewertet werden.

Was auffällt, ist die keyPressed Methode. Da setzt Du die move Variablen auf false. Das Jump wird wohl klappen, da Du da dort ein true setzt.

Du solltest Dir die Beschreibung ansehen von KeyEvent: KeyEvent (Java SE 17 & JDK 17) (oracle.com)
Dort findest Du die Reihgenfolge, die die Events ausgelöst werden:
KEY_PRESSED
KEY_TYPED (is only generated if a valid Unicode character could be generated.)
KEY_RELEASED

Ich vermute, dass Du bei den A / D Tasten sofort ein KEY_PRESSED bekommst, was die Variable erst auf true setzt. Es kommt aber auch direkt ein KEY_TYPED und da setzt Du es dann direkt wieder auf false.
Wenn der Timer dann kommt, dann ist die Variable halt direkt auf false.

Ich schreibe noch im Anschluss ein paar Tipps für Veränderungen - das mache ich aber in einem anderen Post, damit erst einmal der Hinweis auf den eigentlichen Fehler (aus meiner Sicht) gepostet ist und da nicht in falsche Richtung weiter analysiert wird.
 

KonradN

Super-Moderator
Mitarbeiter
a) Wie kann man sowas finden? Was man da immer machen kann, ist ein "Tracing für Anfänger" - wir machen einfach deutlich mir Ausgaben. Also einfach in den Methoden jeweils ausgeben, was gemacht wird. Also etwas wie:
Java:
    @Override
    public void keyTyped(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_A) {
            isMovingLeft = false;
            System.out.println("keyTyped: A. isMovingLeft = false");
        }
        
        if(e.getKeyChar() == KeyEvent.VK_D) {
            isMovingRight = false;
            System.out.println("keyTyped: D. isMovingRight = false");
        }

Dann kannst Du es testen und solltest dann in der Ausgabe sehen, wann welches Event kommt (oder eben nicht!)

b) Lesbareren Code mit Hilfe von Lambda Expressions / Method references:

Statt in der Klasse ActionListener zu implementieren kannst Du
  • dieses implements heraus nehmen
  • Die Methode umbenennen - das kann dann z.B. einfach gameLoop oder so sein.
  • Das wird dann in dem Timer so gesetzt: timer = new Timer(10, this::gameLoop); (Dann hättest Du eine Methodenreferenz angegeben) oder als: timer = new Timer(10, () -> this.gameLoop()); (Dann hättest Du eine Lambda Expression)

Dadurch wird dann klar, dass die Methode die GameLoop ist und so.

Das funktioniert aber nur bei sogenannten funktionalen Interfaces. KeyListener ist kein funktionales Interface, daher geht es da leider nicht. Aber damit es da deutlich besser lesbarer ist, wäre eine eigene Klasse nur dafür evtl. interessant.
 

Nenad2001

Mitglied
a) Wie kann man sowas finden? Was man da immer machen kann, ist ein "Tracing für Anfänger" - wir machen einfach deutlich mir Ausgaben. Also einfach in den Methoden jeweils ausgeben, was gemacht wird. Also etwas wie:
Java:
    @Override
    public void keyTyped(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_A) {
            isMovingLeft = false;
            System.out.println("keyTyped: A. isMovingLeft = false");
        }
        
        if(e.getKeyChar() == KeyEvent.VK_D) {
            isMovingRight = false;
            System.out.println("keyTyped: D. isMovingRight = false");
        }

Dann kannst Du es testen und solltest dann in der Ausgabe sehen, wann welches Event kommt (oder eben nicht!)

b) Lesbareren Code mit Hilfe von Lambda Expressions / Method references:

Statt in der Klasse ActionListener zu implementieren kannst Du
  • dieses implements heraus nehmen
  • Die Methode umbenennen - das kann dann z.B. einfach gameLoop oder so sein.
  • Das wird dann in dem Timer so gesetzt: timer = new Timer(10, this::gameLoop); (Dann hättest Du eine Methodenreferenz angegeben) oder als: timer = new Timer(10, () -> this.gameLoop()); (Dann hättest Du eine Lambda Expression)

Dadurch wird dann klar, dass die Methode die GameLoop ist und so.

Das funktioniert aber nur bei sogenannten funktionalen Interfaces. KeyListener ist kein funktionales Interface, daher geht es da leider nicht. Aber damit es da deutlich besser lesbarer ist, wäre eine eigene Klasse nur dafür evtl. interessant.
Danke für deine Tipps nur das Problem war selbst als ich moveleft und right auf true gesetzt hat war es trotzdem falsch hatte chatgpt nach rat gefragt haha 😂
 

Nenad2001

Mitglied
a) Wie kann man sowas finden? Was man da immer machen kann, ist ein "Tracing für Anfänger" - wir machen einfach deutlich mir Ausgaben. Also einfach in den Methoden jeweils ausgeben, was gemacht wird. Also etwas wie:
Java:
    @Override
    public void keyTyped(KeyEvent e) {
        if(e.getKeyChar() == KeyEvent.VK_A) {
            isMovingLeft = false;
            System.out.println("keyTyped: A. isMovingLeft = false");
        }
        
        if(e.getKeyChar() == KeyEvent.VK_D) {
            isMovingRight = false;
            System.out.println("keyTyped: D. isMovingRight = false");
        }

Dann kannst Du es testen und solltest dann in der Ausgabe sehen, wann welches Event kommt (oder eben nicht!)

b) Lesbareren Code mit Hilfe von Lambda Expressions / Method references:

Statt in der Klasse ActionListener zu implementieren kannst Du
  • dieses implements heraus nehmen
  • Die Methode umbenennen - das kann dann z.B. einfach gameLoop oder so sein.
  • Das wird dann in dem Timer so gesetzt: timer = new Timer(10, this::gameLoop); (Dann hättest Du eine Methodenreferenz angegeben) oder als: timer = new Timer(10, () -> this.gameLoop()); (Dann hättest Du eine Lambda Expression)

Dadurch wird dann klar, dass die Methode die GameLoop ist und so.

Das funktioniert aber nur bei sogenannten funktionalen Interfaces. KeyListener ist kein funktionales Interface, daher geht es da leider nicht. Aber damit es da deutlich besser lesbarer ist, wäre eine eigene Klasse nur dafür evtl. interessant.
Hast du sonst noch Tipps zu Verbesserungen im Code das würde mir sehr helfen 😀?
 

Nenad2001

Mitglied
Also der Code ist extrem schwer lesbar, da Du alles in einer Klasse hast und dazu die Interfaces so überschreibst, so dass die Methoden halt unlesbare Namen haben. Hinzu kommt, dass Du Dich teilweise nicht an die Naming Conventions hältst. (Methoden fangen bitte alle klein an!)

Der Aufbau ist ja:
  • Deine Game-Loop hast Du mit dem Timer und der actionPerformed Methode. Das, was hier etwas auffällt: Warum startest Du den Timer öfters? Einmal gestartet sollte es doch ok sein.
  • Durch die Tastendrücke setzt Du dann Variablen, die in der Gameloop dann ausgewertet werden.

Was auffällt, ist die keyPressed Methode. Da setzt Du die move Variablen auf false. Das Jump wird wohl klappen, da Du da dort ein true setzt.

Du solltest Dir die Beschreibung ansehen von KeyEvent: KeyEvent (Java SE 17 & JDK 17) (oracle.com)
Dort findest Du die Reihgenfolge, die die Events ausgelöst werden:


Ich vermute, dass Du bei den A / D Tasten sofort ein KEY_PRESSED bekommst, was die Variable erst auf true setzt. Es kommt aber auch direkt ein KEY_TYPED und da setzt Du es dann direkt wieder auf false.
Wenn der Timer dann kommt, dann ist die Variable halt direkt auf false.

Ich schreibe noch im Anschluss ein paar Tipps für Veränderungen - das mache ich aber in einem anderen Post, damit erst einmal der Hinweis auf den eigentlichen Fehler (aus meiner Sicht) gepostet ist und da nicht in falsche Richtung weiter analysiert wird.
Habe mehrere Klassen aber halt nur für die getter und Wetter der gezeichneten Objekte
 

Jw456

Top Contributor
Tipp schaue dir mal an wann die Methode keyTyped aufgrufen wird und wie du da deine Variable isMovingLeft setzt.
Die Methode wird vom System aufgrufen wenn ein Zeichen von der Tastatur erkannt wurde.

Ich hatte mir deine imports nicht angesehen nicht gesehen das du den timer von swing benutzt.
Somit sollte der Listener actionPerformed aufgrufen werden.
 
Zuletzt bearbeitet:

Nenad2001

Mitglied
Tipp schaue dir mal an wann die Methode keyTyped aufgrufen wird und wie du da deine Variable isMovingLeft setzt.
Die Methode wird vom System aufgrufen wenn ein Zeichen von der Tastatur erkannt wurde.

Ich hatte mir deine imports nicht angesehen nicht gesehen das du den timer von swing benutzt.
Somit sollte der Listener actionPerformed aufgrufen werden.
Danke die für denn tipp 👍🏻
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
Bademeister007 Hallo Leute ich hab eine Frage zur ArrayList Java Basics - Anfänger-Themen 8
Z Blutiger Anfänger sucht nette Leute die gern helfen Java Basics - Anfänger-Themen 49
K Brauche nur Tipps Leute habe keine plan wie ich dass machen Java Basics - Anfänger-Themen 4
T moin leute hab ein kleines aber pikantes problem Java Basics - Anfänger-Themen 10
P Mein Programm wird zwar erfolgreich Compiliert, öffnet sich aber nicht Java Basics - Anfänger-Themen 6
B Screenshots machen und zwar viele und speichern Java Basics - Anfänger-Themen 12
H datei wird zwar erstellt, aber nichts geschrieben Java Basics - Anfänger-Themen 2
berserkerdq2 Habe eine Klasse, welche public ist, diese hat eine public Methode, die nicht static ist. Wenn ich nun versuche aufzurufen Probleme? Java Basics - Anfänger-Themen 8
3 OOP erste Versuche, OOP zu verstehen. Probleme mit gettern und settern Java Basics - Anfänger-Themen 4
E jProgressbar, 6 Versuche, welche value angeben ? Java Basics - Anfänger-Themen 3
L Erste Schritte Erste Versuche mit Server und Client Java Basics - Anfänger-Themen 7
Z Erste Schritte Versuche ein Labyrinth in einem Terminal zu erstellen, aber kann die properties Datei nicht einlesen Java Basics - Anfänger-Themen 3
Farbenfroh Erste GUI Versuche Java Basics - Anfänger-Themen 1
O Erste Versuche eine Art "EventHandler" zu bauen.. Java Basics - Anfänger-Themen 8
M meine ersten versuche Java Basics - Anfänger-Themen 8

Ähnliche Java Themen


Oben