Archived

This topic is now archived and is closed to further replies.

MattieB

Game loop (Tetris in Java)

Recommended Posts

MattieB    126
Hi, I''m working on a tetris application in Java. I''m able to draw a block on a canvas and move it with the arrows. Everything works fine ("collision detection", tumbling, moving,...), so i began working on the game loop. The initial idea was: //pseudo-code while (notEndOfGame) { while(blockStillCanFall) { block.fall Thread.sleep(time) } generateNewBlock } //pseudo-code Now I''ve got some problems: 1) Can the player use the keyboard when the thread is sleeping? Will there be a keyEvent generated? Is that event able to interrupt the thread and let the block do his movement? 2) It seems like I can''t acces my canvas repaint() method (i tested it with System.out.println("..")) when I use the while-loop (even without the thread). I tried an infinite loop in which the canvas calls it''s repaint() method, but no block was drawn (the first block is initialised right before the loop; without the loop the block is drawn). I couldn''t even acces the repaint() method right before the loop. Could it be that the repaint() method is too slow? That it is not finished before going into the loop and so it is not executed (that sounds strange to me, but i''ve got no other explenation)? 3)Is this a good way for letting the block wait to fall, are there other/better ways? Thanks, Jan

Share this post


Link to post
Share on other sites
yaroslavd    150
First of all, you should think about switching to Swing. Secondly, I think that your program will still read input because while your GameThread sleeps, your InputThread will work. I dunno about repaint().

Share this post


Link to post
Share on other sites
Zahlman    1682
quote:
Original post by MattieB
Now I''ve got some problems:
1) Can the player use the keyboard when the thread is sleeping? Will there be a keyEvent generated? Is that event able
to interrupt the thread and let the block do his movement?



Yes; the keyEvents are generated from a separate thread.

quote:

2) It seems like I can''t acces my canvas repaint() method (i tested it with System.out.println("..")) when I use the while-loop (even without the thread). I tried an infinite loop in which the canvas calls it''s repaint() method, but no block was drawn (the first block is initialised right before the loop; without the loop the block is drawn).
I couldn''t even acces the repaint() method right before the loop.
Could it be that the repaint() method is too slow? That it is not finished before going into the loop and so it is not executed (that sounds strange to me, but i''ve got no other explenation)?



Uh? Where is the Canvas trying to call its repaint() from? You want to call it from somewhere outside the method. Also, when you say *your* canvas repaint() method... repaint() isn''t really meant to be overloaded unless you know what you''re doing; and even then you should probably include a super.repaint() somewhere to make sure that it actually is able to generate a paint() request. Your drawing logic goes in paint() (BTW, never put game logic in paint() - you''ll regret it eventually) and the API does some magic and routing between repaint() and paint(Graphics g) (which includes generating that Graphics object!), rather like it does between start() and run() for Threads.

Also keep in mind that repaint()s are just a *request* - the system is allowed to wait to process them, and/or batch them together.

quote:

3)Is this a good way for letting the block wait to fall, are there other/better ways?



You seem to have the right idea. Now you just need to arrange your repaint() calls. You could add them to this main loop (and also put one after every time a keypress changes the block), but that''s kind of messy; or you could add them to your Block class at each point where the position changes (still a few places); or you could add it to whatever the containing class for your world model is (that might be your Canvas subclass but I don''t recommend that approach, having played with it in the past); or you could start a new thread altogether (with a shorter sleep time) that just calls the repaints whenever.

Share this post


Link to post
Share on other sites
MattieB    126
quote:
Original post by Zahlman
Uh? Where is the Canvas trying to call its repaint() from? You want to call it from somewhere outside the method.


Right before my main game loop I initialize a block and the playfield (canvas). When the playfield initializes, it keeps track of the block position (There's a pointer in the playfield class to the current falling block object) and it calls it's repaint method after the initialisation. When I don't create a main game loop, the block is painted on the canvas and I can control it with the keys. When I create a loop after it with the Thread.sleep() method and the block.fall() method, the block won't be painted and I can't control it with my arrows (No keyEvent is generated when I press on the arrows).


quote:
Original post by Zahlman
Also, when you say *your* canvas repaint() method... repaint() isn't really meant to be overloaded unless you know what you're doing; and even then you should probably include a super.repaint() somewhere to make sure that it actually is able to generate a paint() request. Your drawing logic goes in paint() (BTW, never put game logic in paint() - you'll regret it eventually) and the API does some magic and routing between repaint() and paint(Graphics g) (which includes generating that Graphics object!), rather like it does between start() and run() for Threads.


Well, I didn't mean "my repaint() method from the canvas..." but "the repaint() method from my canvas..." (I didn't overwrite it).

quote:
Original post by Zahlman
Also keep in mind that repaint()s are just a *request* - the system is allowed to wait to process them, and/or batch them together.


Is there a way to be sure the repaint (and paint) method is executed before going further?

quote:
Original post by Zahlman
You seem to have the right idea. Now you just need to arrange your repaint() calls. You could add them to this main loop (and also put one after every time a keypress changes the block), but that's kind of messy; or you could add them to your Block class at each point where the position changes (still a few places); or you could add it to whatever the containing class for your world model is (that might be your Canvas subclass but I don't recommend that approach, having played with it in the past); or you could start a new thread altogether (with a shorter sleep time) that just calls the repaints whenever.

I placed the repaint() calls in my Block class everytime a block moves (and the move-methods are executed when an arrow is pressed).

I find it strange the block isn't painted (or the canvas isn't repainted) when I create the main game loop. I have no idea what I'm doing wrong. It's like the loop takes control over the program and there's no way to get out of it (not by clicking the mouse on the cross from my mainwindow, not by pressing an arrow key).

Oh, and I've got another question:
I've got a MainWindow (extends JFrame) where the canvas is painted on. I've made a file menu with a "Start Game" menu item. When I click on this, the canvas is painted with the block on it(If I remove the main game loop that is ). Before I can control the block, I have to click on the canvas itself. Is there a way to do this automatically so the canvas is the listening window immediately?

[edited by - MattieB on January 24, 2004 9:24:47 AM]

[edited by - MattieB on January 24, 2004 9:26:15 AM]

Share this post


Link to post
Share on other sites