Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (498)
Games in Android Showcase (117)
games submitted by our members
Games in WIP (564)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  First 2D game - yet another Tetris(tm) clone...  (Read 4190 times)
0 Members and 1 Guest are viewing this topic.
Offline tcopeland

Senior Newbie




Just a programmer


« Posted 2002-12-02 18:02:39 »

...can be found here:

http://infoether.com/~tom/games/tetris/

This is a very simple implementation of Tetris - no sound, blocks are drawn using Graphics2D.drawRoundRect(), and so on.  Everything should work though - the pause function, the "top 5 high scores", the demo mode, etc.  FWIW,  I get about 65 FPS on my little Pentium III 1.1GHz laptop.

Thanks for any feedback - this is my first effort in this field so pls be gentle :-)

Thanks,

Tom

P.S.  First I posted this over in the Java 2D section... thanks to zparticle for noticing that it should have been over here to begin with.

Just a programmer
Offline Herkules

Senior Member




Friendly fire isn't friendly!


« Reply #1 - Posted 2002-12-03 06:25:53 »

Why does Tetris run with 65fps???

What a waste of CPU resources. Consumes 100% of my CPU. Could do it easily with 1%.

HARDCODE    --     DRTS/FlyingGuns/JPilot/JXInput  --    skype me: joerg.plewe
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #2 - Posted 2002-12-03 10:14:53 »

Right... it'll take everything it can get... the game loop is pretty much this:

state.execute();
offScreenImage.drawImage(blahblah);

So it'll loop as fast as it can.  

I put a Thread.yield() inside the game loop, and a Thread.currentThread().setPriority(Thread.MIN_PRIORITY) right as the program starts to try up make it a bit less greedy....

Yours,

Tom

Just a programmer
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Herkules

Senior Member




Friendly fire isn't friendly!


« Reply #3 - Posted 2002-12-03 11:42:33 »

1  
2  
3  
4  
5  
    private final int TICK_TIME = 500;

....

    Thread.sleep( TICK_TIME );

HARDCODE    --     DRTS/FlyingGuns/JPilot/JXInput  --    skype me: joerg.plewe
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #4 - Posted 2002-12-03 11:55:23 »

Right, it could just sleep inside the game loop... but wouldn't that preclude a "row filled" animation or a "piece landed" animation?   Because those would need to, you know, fly away in little pieces or something nice and smooth.  

On the other hand, I haven't implemented any animations like that yet, so that's not a very strong argument :-)

Tom

Just a programmer
Offline cknoll

Junior Member




Flame On!


« Reply #5 - Posted 2002-12-03 15:33:19 »

Hi there,
 Just a question: does this game really need to be based on FPS, considering at 120 FPS (which is what I was getting) i'm not doing anything for 119 of those frames (if it takes just 1 frame to move the block down per second).

Is another possiblity to just have the pieces fire their own doPaint() methods when either A) The user presses a key, or B) when a timeout says to move the piece down.  Then, your game loop looks something like this:

1  
2  
3  
4  
5  
6  
7  
8  
gameOver=false;
while (!gameOver)
{
  checkRows(); // will check for completed rows and draw any animations, and move the previous rows down 1 row for each cleared row
 if (checkGameOver())
    gameOver = true;
  waitForAction();
}


waitForAction() could be alerted if the user does the 'drop block' action or the 'block collides with a row' action.  This would eliminate some degree of 'busy waiting'

There's still an issue tho, depending on how your timer works...if you do want to do a really elaborate animation (maybe each block explodes in a wonderous shower of pixel-light and sound) should the time required to display the animation halt the timer's countdown to the next block-lowering-iteration?  I think the answer is yes.  Therefore, you don't want to have the ticker in it's own loop, you probably want to cancel a pending ticker when the player does a 'drop block' and kick off a new one....or something like that.

-Chris
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #6 - Posted 2002-12-03 16:33:58 »

Hm, that's well said.  Let's see.... 

Note that any explanation I give for doing this as an FPS-based thing will be purely post-action rationalization on my part since I just kind of wrote this the only way I could think of doing it.  It's more of a lack of knowledge on my part than an attempt to do things a particular way. :-)

Anyhow, yup, let's see, how to do this without a busy-wait game loop?  OK, there could be a timer that fires once a second that kicks off a "piece lower" event that erases and redraws that piece.  And the KeyListeners could do a similar thing for rotation and left/right movement.  

The animation thing would be interesting.  

[much typing]

OK, it was interesting enough that I cobbled together an little "animation" that, in addition to be disconcertingly ugly, gives us something to work with.   I've uploaded a new version to the web site - http://infoether.com/~tom/games/tetris/.

So, how could I do something like that without a FPS thing?  Maybe run the animation in another thread?  And then interrupt the thread if the animation needed to be restarted?  Maybe that's a way to do it...

Tom

Just a programmer
Offline cknoll

Junior Member




Flame On!


« Reply #7 - Posted 2002-12-03 18:10:22 »

Hah, good animation (I'm into ugly, I guess).  Anyways, it demonstrates one of my points:

The block is continuing to be signaled to drop while the animation is playing...do we want that?  Maybe, maybe not. We defintely don't want it if the animation involves clearing the row (maybe a very high row, very late in the game) and with the block falling befor ethe row is cleared, I could loose the game simply because the animation din't finish fast enough before the block collided with a non-clear row (I am getting mad just thinking about it).

So, let's say, for argument's sake, we don't want the brick to drop during the animation...that means your game loop should not let the timer controlling the block's desent continue while the current 'tick' is being processed....

Without going into too much detail, I think your game boils down to 2 threads: A user input thread (that AWT or Swing will provide to recieve user input) and your timer thread that should fire off an event of it's own to signal the block should be moved down.   The game only needs to check it's state  (to see if the game is over or if a row is cleared, or the block just falls to the bottom and nothing happens) when either A) The user clicks up arrow or B) The timer triggers.  Once this happens, the following chain of code can execute:

Move Block (either 1 space down or all the way down)
Check for row clear
Perform any animations as necessary **
Restart the Timer trigger.

** This action you can either draw to the screen as fast as possible, or you can draw it at a fixed FPS  Either way, nothing further should happen in the game (such as blocks moving downwards, etd) until after this chain of code completes.

Like you said, yes, you need to have a way to 'cancel' the trigger if the user does something that should abandon the countdown...maybe your Trigger thread can look something like this:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
Public class Trigger extends Thread
{
  private int TICK_TIME = 500;
  private boolean aborted = false;

  public setAbort()
  {
    aborted = true;
  }

  public void run()
  {
      try
     {
        Thread.sleep(TICK_TIME);
        if (!aborted)
          fireEvent();
     }
  }
}


Now, if the player does something that should halt the trigger, just call setAbort() on the trigger.  Every time you 'restart the timer trigger' you create a new trigger object.  Now, this violates rule number 1 of all game programming: do NOT create excessive objects...(especially in this case, thread objects), but it will get the job done.  With more work, you could use Thread.inturrupt() to wake up the thread so that it's in a state to reuse.  This would save a lot of resources.

-Chris
Offline cknoll

Junior Member




Flame On!


« Reply #8 - Posted 2002-12-03 18:12:22 »

Bah, I don't think I answered your main question which was where to do the animation thread:  But do it in the main game loop, you don't want any other action to take place while the animation is playing, so just make the main game loop thread call an animation routine and after it's finished continue with the game (create a new trigger, etc).  You may want to ignore user input while the animation is playing (easily indicated by using a boolean variable)

-Chris
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #9 - Posted 2002-12-04 11:48:55 »

The more I think about it the more I agree that the "loop as fast as you can" design is not good for some games.  

For example, a Othello game could just sit and wait for user input, and then spend as much cycles as necessary flipping pieces and calculating scores and exploding with light and sound.  Then it could go back to sleep and wait for the next move.  Actually, I guess it would need a background thread to be analyzing possible moves and such... assuming it was a player against computer game.  

What about arcade games though?  Maybe Tetris isn't really an arcade game per se... although when the "lower piece" speed is down to 100 ms it seems fairly arcadish.  Hm.  At the same time though, Herkules' question still seems appropriate - "why should x consume 100% of my CPU?".  Even if it is Asteroids or Space Invaders or some such, gobbling 100% of CPU seems rude.

Re-reading your post again now... the thing that bothers me about "land the piece, then play the animation, then continue the game" is that it seems a bit stilted.  I mean, part of the fun is that a lot of stuff is going on at once - I'm rotating a piece, the animation from the last piece is still going, the animation from the last time I filled up a row is fading away (at least, if there was such an animation).  On the other hand, all that could probably be done using separate threads.  

Here's a question - how could that animation be accomplished without redrawing the underlying board every time the circles get bigger?   Hm, I guess I could draw a clipped region of the board, then do the animation.... and the clipped area could be dependent on the largest circle size... hm.  Or maybe there's some Java 2D ImageFilter thing for that....

Thanks for the ideas and feedback,

Tom

Just a programmer
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline zparticle

Senior Member




Thick As A Brick


« Reply #10 - Posted 2002-12-04 12:08:31 »

I my mind there isn't anything wrong with taking 100% CPU for a full screen game because the player isn't (at least I wouldn't be) doing anything else. However it can be annoying to have an applet or windowed game up that hammers the machine.

Offline Herkules

Senior Member




Friendly fire isn't friendly!


« Reply #11 - Posted 2002-12-04 12:30:50 »

Quote
I my mind there isn't anything wrong with taking 100% CPU for a full screen game because the player isn't (at least I wouldn't be) doing anything else.


I don't agree. Yes, the PLAYER doesn't do anything else, but his machine might do!
Love to play while compiling, printing, e.g....
Or my machine is used as a dedicated Quake-server while I'm playing Tetris?

In general, for a multi-purpose, multi-tasking, maybe multi-user platform, don't assume anything what the user does or does not.


HARDCODE    --     DRTS/FlyingGuns/JPilot/JXInput  --    skype me: joerg.plewe
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #12 - Posted 2002-12-04 12:53:09 »

Yup, it makes sense to use as few resources as possible.  

I put a Thread.currentThread.sleep(20) in the game loop; that trims CPU usage to about 30% without causing flickering or anything like that.  So that's a little better.  

Tom

Just a programmer
Offline cknoll

Junior Member




Flame On!


« Reply #13 - Posted 2002-12-05 11:03:07 »

You hit the nail right on the head with your othello example...those sort of games (and I think tetris is just like those games except there's a timer that forces you to make your move, etc) aren't really 'fps' types of games (although they could be, as your game demonstratres).

Second thing i wanted to say is always ALWAYS program games with the most efficient use of resources in mind.  That means be consious of thread creation, object creation, busy loops, etc....I'm not saying you should cripple good design for maximum efficiency, but in the realm of game programming, elegent design (flexability, extendability, etc) may take a back seat to getting the fastest amount of performance....all things in balance tho.

Third, as far as thread creation, in games, I'd avoid it.  Your turn-based game makes sense in that you'd want the computer to do work about calculating moves while the player decides what he is going to do, however, doesn't the player's move change the state of the board and therefore the work the AI just did in the separate thread need to be re-calculated based on the new board?  For FPS based games, same thing with the AI, the AI will need to decide what to do after the player's avatar has performed it's action for its 'tick'...a separate thread will not help you here, I don't think.

Also, separate threads for animation is also risky, because one thread may starve and so one of your little animated guys may be frozen (there's a post about doing NPC animation in another board (check the 2d forum).  The more common design is to have 1 animation thread that checks each drawable element and draws only things that say need drawing.

Anyways, food for thought.  Most of all, have fun.

-Chris
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #14 - Posted 2002-12-05 16:40:32 »

Very cool, thanks for the thoughtful response.

FWIW, I was just reading some stuff out there on Othello algorithms.  Seems like some people create an "evaluation thread" while the human player is thinking.  The thread considers each possible human player move and evaluates the best possible response move - so when the player finally does go, the computer has some cached responses.  Cool stuff.  

Thanks again,

Tom


Just a programmer
Offline mandrixx

Senior Newbie




Java games rock!


« Reply #15 - Posted 2002-12-14 16:38:14 »

check out my tetris. maybe it will give you good ideas

http://www.mandrixx.net/tootris.html

keep on the good work
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #16 - Posted 2002-12-14 16:58:16 »

Wow dude, that's awesome!   Nice and smooth.  Very cool.

The brickout game is awesome, too... I'm working on one right now and it sure doesn't look as good as that!  Oh well.

See ya,

Tom

Just a programmer
Offline tcopeland

Senior Newbie




Just a programmer


« Reply #17 - Posted 2002-12-16 13:30:16 »

I changed the controls on my version to match yours... whoever suggested it way back when, you're right: the down arrow should simply lower the block, not drop it.

http://infoether.com/~tom/games/tetris/

See ya,

Tom

Just a programmer
Offline zparticle

Senior Member




Thick As A Brick


« Reply #18 - Posted 2002-12-16 13:50:15 »

tcopeland:

When a block gets to the bottom of the window you should be able to move it side to side for a small period of time. This allows you to slide under a fixed block to fill a gap.

Offline tcopeland

Senior Newbie




Just a programmer


« Reply #19 - Posted 2002-12-16 13:52:03 »

Hm, you're right, currently it just goes ahead and plants the piece without waiting.  I'll look at it... thanks....

Tom

Just a programmer
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Grunnt (23 views)
2014-09-23 14:38:19

radar3301 (14 views)
2014-09-21 23:33:17

BurntPizza (31 views)
2014-09-21 02:42:18

BurntPizza (22 views)
2014-09-21 01:30:30

moogie (20 views)
2014-09-21 00:26:15

UprightPath (30 views)
2014-09-20 20:14:06

BurntPizza (34 views)
2014-09-19 03:14:18

Dwinin (48 views)
2014-09-12 09:08:26

Norakomi (75 views)
2014-09-10 13:57:51

TehJavaDev (108 views)
2014-09-10 06:39:09
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!