2

I have made a map on an image which I load in the game like this:

List<Block> tempBlocks = new ArrayList<Block>();
BufferedImage level = levels.get(currentLevel);
for (int x = 0; x < level.getWidth(); x++) {
    for (int y = 0; y < level.getHeight(); y++) {
        tempBlocks.add(new Block(x, y, new Color(level.getRGB(x, y))));
    }
}

blocks = tempBlocks;
isLoading = false;

The array blocks is an array with all 1-pixel-blocks. Every single block renders like this:

g.setColor(color);
g.drawLine(x, y, x, y);

I call them like this:

for (int i = 0; i < getCurrentScene().blocks.size(); i++) 
    getCurrentScene().blocks.get(i).render(g);

It's 1280x720 blocks... Is it a better way to render this insane amount of blocks? Because I want it to load from an image, which is 1280x720. I get like 3 FPS now...

Lukas Wiklund
  • 826
  • 6
  • 21
  • Why don't you render directly the image? – Shepard Jul 12 '15 at 04:17
  • @Shepard I want collision detection and so you're creating the map from an image. – Lukas Wiklund Jul 12 '15 at 11:29
  • What do you mean? You have to change the color of some pixels when a collision occurs? – Shepard Jul 12 '15 at 12:14
  • @Shepard I wanna check if the player hits the blocks. – Lukas Wiklund Jul 12 '15 at 12:20
  • 1
    Fine, build your array of blocks but use it ONLY for collision detection. Keep the image and render it with a custom JPanel, see http://stackoverflow.com/questions/19125707/simplest-way-to-set-image-as-jpanel-background. If you need to update the image data, for example to draw the player into a new position, you can do that through BufferedImage.setRGB method. I am sure your framerate will increase a lot! – Shepard Jul 12 '15 at 12:35
  • 1
    @Shepard Thanks a lot! I had never thought of not rendering the blocks but use them as collision detection and render an image instead! :D – Lukas Wiklund Jul 12 '15 at 12:56

2 Answers2

0

For what you're doing now, if you do that for every frame, you're creating new objects all over the place for every single frame, and only using them once before discarding and allowing the garbage collector to pick them up.

Create enough objects to represent how the screen is now. Create enough objects to represent how the screen should be next.
Don't lose those. Don't create any more.

For the Color(int int int) thing you're doing? You can just do Color(int); new color(level.getRGB(x, y)) should work just fine; the java.awt.Color class can take a single int instead of three.

That said, you'd still be initializing Color a million times. If you have a limited number of Colors, it may be beneficial to call them directly or cache them in some way, instead of continually recreating new Color objects on the heap.

Dean J
  • 39,360
  • 16
  • 67
  • 93
  • 1
    Those for loops only add blocks one time, until you change map. The thing which happens every frame is those second two code blocks. But thanks for the color feedback! I didn't know it could take just one int :D – Lukas Wiklund Jul 12 '15 at 11:35
0

Shepard solved it in the comments. What I did was to render the image as g.drawImage(image, x, y); instead of rendering all of the pixels. I still use the blocks for collision detection, but that is way more efficient.

Lukas Wiklund
  • 826
  • 6
  • 21