Results 1 to 6 of 6
  1. #1
    TacoManStan is offline Member
    Join Date
    Sep 2011
    Posts
    50
    Rep Power
    0

    Default The Most Efficient Way To Make a 2D Game?

    Hi. I have been making a game for a bit now, and I am experiencing the worst lag. Right now the game is based on a tile system, drawn on a jPanel. Basically there is a single BufferedImage on the jPanel, and then the BufferedImage is updated based on a double array of arraylists, containing all of the units occupying that space. The size is only 10x20.

    I have 2 threads running, as a test. Well, actually Swing Timers. One timer runs every 40 milliseconds, and will draw the entire map by cycling through the previously mentioned array, and then using another set of for loops to draw each individual pixel. The other thread isn't actually doing anything at the moment, it is simply there to update what would be the AI. Then I have a KeyboardDispatcher which gets the input from the keyboard.

    It just runs way too slowly... It's not even that I don't understand why it is running so slowly. I do. I just am curious how on earth something like a 3D game could run if something as small as this causes that much lag. In other words, what is the most common way of doing this? The most efficient? I have never used the Canvas class, and would prefer sticking with jPanel if possible. Although it might be simple to use them together, I have never actually looked into it.

    Any suggestions?

  2. #2
    quad64bit's Avatar
    quad64bit is offline Moderator
    Join Date
    Jul 2009
    Location
    VA
    Posts
    1,323
    Rep Power
    7

    Default Re: The Most Efficient Way To Make a 2D Game?

    Java2D isn't bad in terms of performance considering it's software based (unless you're using volatile images which have hardware acceleration on some platforms). Also, most 3D games are probably using OpenGL bindings which mean the 3d is totally being rendered with hardware (mine craft uses LWJGL for example).

    All that being said, I'd put $100 on the idea that it is your implementation that is slow, not java. I have written particle simulators that work with 500,000+ particles in java that run over 30fps (200+ in JOGL/LWJGL).

    If you post your relevant drawing code here, I can take a look. Also, if you want smooth frame rates you'll need to do a couple things. Timers don't guarantee smooth performance, and uneven frame rates are common with this method. Games use a different system generally: You hard code in the refresh time into each entity that is moving/changing. You'r game logic can run at one speed, lets say every 3ms, but your screen refresh might run at a different speed, lets say every 15ms (~66fps). You measure the elapsed time every n number of cycles, and move/animate the entities based on how much time has actually passed instead of a fixed increment. This way if once cycle has a logic loop that takes 20ms instead of 3ms, your program eats the lost time rather than slowing down. You can also calculate frame rate averages over time and make adjustments to your animation cycle based on previous rendering statistics.

    Another thing that can greatly accelerate your app with pixel by pixel animations is manipulating a bufferedImage directly. Rather than using Graphics from java2d to draw a 1x1 square, you can simply set the color of that pixel directly in the buffered image. This cuts out massive amounts of overhead when dealing with pixel level drawing.

    For more complex stuff where you are compositing lots of individual images (especially those with transparency) it is important to draw as little as possible. You can help optimize this by only refreshing portions of the screen. If only the lower right side is being animated, then only refresh that part of the screen.

    Finally, you need to profile your app to see what is actually eating all the time. You can do a poor-man's profile with some printouts of System.currentTimeMillis(). Here is an example:

    Java Code:
    //...
    public void runGame(){
        while(true){
            logic();
            redraw();
            sleep();
        }
    }
    
    public void redraw(){
        Graphics g = someBufferedImage.getGraphics();
        g.setColor(Color.BLACK);
        //...
        g.dispose();
        window.repaint();
    }
    Ok, so above are some code excerpts from an over simplified game loop and redraw() method. You could start by timing each part and printing out the times:
    Java Code:
    //...
    public void runGame(){
        long start;
        while(true){
            start = System.currentTimeMillis();
            logic();
            System.out.println("Logic took: "+System.currentTimeMillis() - start);
            start = System.currentTimeMillis();
            redraw();
            System.out.println("Drawing took: "+System.currentTimeMillis() - start);
            start = System.currentTimeMillis();
            sleep();
            System.out.println("Slept for: "+System.currentTimeMillis() - start);
        }
    }
    
    public void redraw(){
        Graphics g = someBufferedImage.getGraphics();
        g.setColor(Color.BLACK);
        //...
        long start = System.currentTimeMillis();
        //draw something
        System.out.println("Polygon draw: "+System.currentTimeMillis() - start);
        start = System.currentTimeMillis();
        //draw something else
        System.out.println("Huge transparent PNG took: "+System.currentTimeMillis() - start);
        g.dispose();
        window.repaint();
    }
    And so on. The printouts and timers will add a bunch of overhead, but you'll get a relatively proportionate snapshot of what is eating all the cpu time. If all the measurements are 1-2ms except one which is 50ms, then that is where you need to look into optimizing. A priority for you should be determining what is taking the most time - logic or drawing. Both can be optimized greatly depending on what you're doing.

    For example, for one project I was working on, there were about 1000 bouncing balls on the screen. They needed to support collision between balls. A simple brute force check for collision (compare every possible set of 2 balls to see if they are collided) slowed the program down to a pathetic < 1fps. Even openGL would not have helped at all, as profiling showed that 99% of my cpu time was spent calculating collision every cycle. I investigated quad trees which are often used for this purpose (and oct trees for 3d space) and found that a couple pages of extra code brought my program up to a smashing 70fps. What changed? Rather than making n^2 comparisons 70 times per second, I was able to drop the total number of comparisons down to log(n). So, I went from 70000000 compares per second to around 700. That is obviously orders of magnitude less work for the program.

  3. #3
    TacoManStan is offline Member
    Join Date
    Sep 2011
    Posts
    50
    Rep Power
    0

    Default Re: The Most Efficient Way To Make a 2D Game?

    Wow thanks, that helped a lot. I remember hearing something about interpolation from some website I was looking at, and I guess you just explained it a lot better. I will start working with that right away, thanks again!

  4. #4
    doWhile is offline Moderator
    Join Date
    Jul 2010
    Location
    California
    Posts
    1,642
    Rep Power
    7

    Default Re: The Most Efficient Way To Make a 2D Game?

    It just runs way too slowly... It's not even that I don't understand why it is running so slowly. I do
    FWIW, if you have not yet I would recommend profiling the code. Sometimes one can spend hours, days, or weeks optimizing the completely wrong piece of code. When/if you have truly nailed down the culprit, how you solve the problem is completely situation dependent - for instance, you mention you draw all the images then cycle through and draw each individual pixel? Sounds like a lot of repetitive work...of course, without an SSCCE as an example demonstrating slow rendering then we can't help you with your implementation and possible bottlenecks.

  5. #5
    TacoManStan is offline Member
    Join Date
    Sep 2011
    Posts
    50
    Rep Power
    0

    Default Re: The Most Efficient Way To Make a 2D Game?

    I have definetely nailed what is taking so long. I switched the individual pixel transfers over to modifying the raster data instead, and the changes were practiaclly instananeous (3-5ms as opposed to 360-400ms per update).

    However, I think I have found a solution. I am modifying the data through the ColorModel and Raster instead of the pixels themselves. However, I have no idea how the ColorModels work. I think I will go make another thread about that, so I guess I will end this one, unless anyone has any other suggestions on how to do this. Sorry about the limited amount of information, but this is more of a learning project, and I'm more interested in why it works than getting it to work.

    EDIT: Oh and one more thing, I forgot to say the problem with using just Raster data. It works, and the image appears, but the colors are all wrong. I have discovered (as mentioned above) that it is the ColorModel causing the color problem, but at least it is running :D
    Last edited by TacoManStan; 01-26-2012 at 09:09 PM.

  6. #6
    quad64bit's Avatar
    quad64bit is offline Moderator
    Join Date
    Jul 2009
    Location
    VA
    Posts
    1,323
    Rep Power
    7

    Default Re: The Most Efficient Way To Make a 2D Game?

    Great! Glad to hear.

Similar Threads

  1. How to make my program more efficient?
    By LonelyClock in forum New To Java
    Replies: 9
    Last Post: 11-29-2011, 04:47 AM
  2. Efficient 2D Game Mapping
    By PhQ in forum New To Java
    Replies: 15
    Last Post: 11-29-2011, 01:56 AM
  3. more efficient way to make this??? [LOOK]
    By Green in forum New To Java
    Replies: 10
    Last Post: 09-09-2011, 01:01 AM
  4. Replies: 1
    Last Post: 03-22-2010, 08:21 AM
  5. A more efficient Game of Life
    By unreal4evr in forum New To Java
    Replies: 3
    Last Post: 03-27-2009, 03:08 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •