1

I'm currently working on a simple 2D top-down shooter in which you maneuver your character around a map. The graphics are still very much in the "testing" phase (solid colors and rectangles). The drawing process is as follows:

  • I have the map (this is basically just walls or free space) stored as an integer array which is then looped through and painted onto my JPanel.
  • Once the map is drawn, I go through each "entity" on the map (powerups, other characters) and place them.
  • Finally, I draw the user's character

I experimented with different methods, and finally decided that the user's character would stay in the center of the screen with the map moving around it.

Currently, it works but it seems slow. I only have 4 walls, 2 entities, and the user's character being drawn and it's at 90FPS, spiking around 60-70 quite often. This would be acceptable if the game were finished, however I still have fancier graphics, many more entities, walls, bullets, etc. to be rendered onto the map. I've tried increasing the speed of my gameLoop, which can get it as high as 230 FPS, but even then when I move into areas with entities or walls it spikes down to 50-70.

I've tried limiting what is drawn to only what is visible but the results were overall negligible and even negative.

The current paintComponent() method looks something like this:

public void painComponent(Graphics g) {

for(int x = 0; x < Map.size.getWidth() ; x++) {

        for(int y = 0; y < Map.size.getHeight(); y++) {

                if(mapArray[y][x] == WALL) {
                    g.setColor(Color.BLACK);
                    g.fillRect(x, y, wallSize, wallSize);
                }

        }
    }

    for(int i = 0; i < map.countEntities(); i++) {

        Entity obj = map.getEntity(i);

        g.setColor(Color.WHITE);
        g.fillRect(obj.getCoords().x, obj.getCoords().y, obj.getSize().width, obj.getSize().height);

    }

    Robot bot = map.getPlayerBot();

    g.setColor(Color.BLACK);
    g.fillRect(bot.getCoords().x, bot.getCoords().y, bot.getSize().width, bot.getSize().height);
}

Do any of you gurus out there have any tips to speed this up a bit?

williamg
  • 2,738
  • 6
  • 34
  • 48
  • why not just paint the background into a BufferedImage once, and then just draw the image onto the screen as needed, instead of looping over all the map elements and drawing them every time. – MeBigFatGuy Sep 25 '11 at 02:13
  • I just tried this. It works great (90-100) when the window size is small, because it doesn't have to render the whole image. But when the game runs full screen, the FPS immediately drops to 40-50. And this is with my GameLoop running as fast as possible – williamg Sep 25 '11 at 03:09
  • Just a small tweak:I think you can safely move the line `Robot bot = map.getPlayerBot();` out of paintComponent(g) .It seems that you are querying the coords value of only one `Robot` instance. – PraveenMax Sep 25 '11 at 05:33
  • I also recommend to see this question,http://stackoverflow.com/questions/148478/java-2d-drawing-optimal-performance – PraveenMax Sep 25 '11 at 05:44
  • For further game programming info it might help to have a look around http://gamedev.stackexchange.com – Seph Oct 11 '11 at 07:39

2 Answers2

2

Beyond the answers mentioned in the following links: Java 2D Drawing Optimal Performance, Java2D Performance Issues, Java 2D game graphics and How to display many SVGs in Java with high performance

A common and simple trick to improve 2D performance is to draw all the static objects ('background') into a buffered image, then when drawing the next image you just offset the pixels of your background image from the previous screen accordingly, then you need only draw the pixels around at most two edges of the screen rather than the entire screen, this only really matters when you're drawing a lot of image layers to the screen.

Beyond all of that make sure you have double buffering enabled so that the drawing doesn't try and draw to the actual screen while you're still drawing the next image.

Community
  • 1
  • 1
Seph
  • 8,472
  • 10
  • 63
  • 94
  • So far, I've written the static images to an image, but there is no significant speed increase. Let's say the image I'm trying to draw is 1000x1000, how fast should I expect to be able to draw it? Currently I'm redrawing it every 15 ms which is about as fast as I can go without lagging. Is it reasonable to try and draw it more frequently? – williamg Oct 11 '11 at 01:02
0

Seph's answer was taken into consideration and implemented, but it did not increase the speed. Apparently, the image being drawn was not the problem at all. The problem was the timer that I was using to call the update methods. I was using an instance of the Timer class which seems to be very unreliable, especially at small intervals such as these. Upon removing the timer and calling my update methods based on the system clock, I was able to reach and maintain incredibly high FPS.

williamg
  • 2,738
  • 6
  • 34
  • 48
  • For the Timer class all you can be assured of is that it will wait 'at least' N ticks, not that it will fire off after N ticks. – Seph Oct 11 '11 at 07:38