0

So I have been following a 2D game development tutorial for Java and I am using IntelliJ with java 1.8.0_201 and the program seems to ignore my inputs randomly when running the program.

Like for example, I can run it once and the inputs will work fine and when I properly terminate the code and then try to test it again it will then ignore my inputs entirely.

As far as I can tell this issue began happening when I was first implementing the KeyHandler.java but it could have been happening before. I have tried re-writing all of KeyHandler.java 3 times and done both delta and the try and catch methods of game loops as well to see if that was the issue and the same problem occurred with both.

This program is composed of 3 java files all in the main package within the src folder, the code for these java files is shown below:

Main.java:

package main;

import javax.swing.*;

public class Main {
    public static void main(String[] args){
        JFrame window = new JFrame();
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setResizable(true);
        window.setTitle("2D Game Test");
        window.setLocationRelativeTo(null);
        window.setVisible(true);

        GamePanel gamePanel = new GamePanel();
        window.add(gamePanel);
        window.pack();
        gamePanel.startGameThread();
    }
}

GamePanel.java:

package main;

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

public class GamePanel extends JPanel implements Runnable{
    // SCREEN SETTINGS
    final int originalTileSize = 16; // 16x16 tile
    final int scale = 3;
    final int tileSize = originalTileSize * scale; //48x48 tiles
    final int maxScreenCol = 16;
    final int maxScreenRow = 12;
    final int screenWidth = tileSize * maxScreenCol; //768 pixels
    final int screenHeight = tileSize * maxScreenRow; //576 pixels

    //FPS
    double FPS = 60.0;

    KeyHandler keyH = new KeyHandler();

    Thread gameThread;

    //Set player's default position
    int playerX = 100;
    int playerY = 100;
    int playerSpeed = 4;

    public GamePanel(){
        this.setPreferredSize(new Dimension(screenWidth, screenHeight));
        this.setBackground(Color.black);
        this.setDoubleBuffered(true);
        this.addKeyListener(keyH);
        this.setFocusable(true);
    }

    public void startGameThread(){
        gameThread = new Thread(this);
        gameThread.start();
    }

    @Override
    public void run() {

        double drawInterval = 1000000000/FPS;
        double delta = 0;
        long lastTime = System.nanoTime();
        long currentTime;

        while(gameThread != null){
            //System.out.println("The game loop is running!");
            currentTime = System.nanoTime();
            delta += (currentTime - lastTime)/drawInterval;
            lastTime = currentTime;
            if(delta >= 1){
                //1 UPDATE: update info such as character pos
                update();
                //2 DRAW: draw the screen with the updated info
                repaint();
                delta--;
            }
        }
    }
    public void update(){
        if(keyH.upPressed){
            playerY -= playerSpeed;
        }
        else if(keyH.downPressed){
            playerY += playerSpeed;
        }
        else if(keyH.leftPressed){
            playerX -= playerSpeed;
        }
        else if(keyH.rightPressed){
            playerX += playerSpeed;
        }
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setColor(Color.white);
        g2.fillRect(playerX, playerY, tileSize, tileSize);
        g2.dispose();
    }
}

KeyHandler.java:

package main;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyHandler implements KeyListener{

    public boolean upPressed, downPressed, leftPressed, rightPressed;

    @Override
    public void keyTyped(KeyEvent e){
    }

    @Override
    public void keyPressed(KeyEvent e){
        int code = e.getKeyCode();
        if(code == KeyEvent.VK_W){
            upPressed = true;
        }
        if(code == KeyEvent.VK_S){
            downPressed = true;
        }
        if(code == KeyEvent.VK_A){
            leftPressed = true;
        }
        if(code == KeyEvent.VK_D){
            rightPressed = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent e){
        int code = e.getKeyCode();
        if(code == KeyEvent.VK_W){
            upPressed = false;
        }
        if(code == KeyEvent.VK_S){
            downPressed = false;
        }
        if(code == KeyEvent.VK_A){
            leftPressed = false;
        }
        if(code == KeyEvent.VK_D){
            rightPressed = false;
        }
    }
}
Sylhare
  • 5,907
  • 8
  • 64
  • 80
Matthew
  • 41
  • 2
  • Don't use `KeyListener`, use [key bindings](https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html), it's generally more reliable an easier to control the focus requirements need to activate them – MadProgrammer Nov 20 '21 at 04:24
  • If you're going to use `Thread` as the main game engine, you shouldn't be using Swing's painting workflow, but should instead make use of [`BufferStrategy`](https://stackoverflow.com/questions/47603643/breaking-out-of-a-loop-with-key-bindings/47603893#47603893) instead, this will give you full control of the painting process and remove any issues with Swings threading issues. Alternatively, you could use a Swing `Timer` instead – MadProgrammer Nov 20 '21 at 04:30

0 Answers0