I've recently started to try to learn java. I thought maybe making small games would be the best way to get familiar with java, so that's what I'm doing. So, I started my first game, and it's looking good. It's just a grid with a player in the center. Once I tried adding player movement I realized I'd need a game loop to check for key presses. That's what I tried. All I can say is that I've never made a game loop before, so this is what I attempted:
public static void main(String[] args) {
GamePanel panel = new GamePanel();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGui();
double ns = 1000000000.0 / 60.0;
double delta = 0;
long lastTime = System.nanoTime();
long timer = System.currentTimeMillis();
while (true) {
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
while (delta >= 1) {
panel.checkKeys();
delta--;
}
}
}
});
}
Here's the issue... When I run this, my game just crashes. It doesn't even let me close out of the game. What is going on? Just in case, I will show more of the GamePanel
code (please tell me if you need any more code).
public GamePanel() {
setLayout(new GridLayout(tiles_count, tiles_count));
setBackground(Color.gray);
setFocusable(true);
addKeyListener(this);
tile_size = 40;
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_A) {
System.out.println("A PRESSED");
player.x += 40;
left = true;
}
}
@Override
public void keyReleased(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_A) {
System.out.println("A RELEASED");
left = false;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
public void checkKeys() {
if(left) {
System.out.println("LEFT");
} else {
System.out.println("!LEFT");
}
}
The game structure is like this: I have a Main
class, which runs a GamePanel
class as the main(String args) {}
function. This issue might have to be with the fact that im using the run
method in the Main
class instead of the GamePanel
class.
What am I doing wrong? Any help is very much appreciated!
Your while
loop will never exit, and thus your program can never repaint, etc.
However, for a game loop like this, you do want an infinite loop --- you just want to run it in a different thread. In this way, the rest of your program is not blocked by the infinite loop, however you are still able to run your game loop tasks.
To do this, we make a new thread, and run our loop in there instead. Note also that after each loop we sleep for a little while (ideally you'd want to do this with time deltas, etc, this is just an example) --- this means that we cap the amount of frames per second, meaning that we don't overwork the processor for no good reason.
Thread t = new Thread(new Runnable(){
public void run() {
while (true) {
// your update logic here
try {
Thread.sleep(16);
}
catch(InterruptedException) {}
}
}
});
t.start();