I am developing a full screen exclusive mode isometric tile game from scratch -i.e. I don't use a game engine- and I have a problem when it comes to drawing "BufferedImages" and "Images" on screen. (I am using active rendering)

The default FPS value is set to 80, but when the map tiles are drawn on screen the FPS value drops at 60. The map size (=array's size) at the moment is 100 tiles (10 width * 10 height). If I change that to 100*100=1000 tiles then the FPS value drops to 0 and the game cannot be played.

The code I use to load buffered images is the following:

Quote

BufferedImage image= ImageIO.read(new File(file));

while the code to load Images is the following:

Quote

Image image= ImageIO.read(new File(file));

where file is a string containing the path to the image.The size of the tile-image that it loaded is ~3KB.

Do you have any idea why does the FPS value drop? Or a different way to suggest on how to draw images without occuring problems to the FPS value?

floorAl is an ArrayList<Tile>, where all the Tile objects representing the floor are contained along with the their x,y positions and their BufferedImages.The Tile class makes use of another class called BufferedImageLoader which is responsible for loading any BufferedImage passed as a parameter to the constructor.

Impossible to spot without the complete source. Maybe incompatible image formats. Use a profiler.In any case, 10x10 tiles is really nothing.I got a frame rate of 1400 when drawing 16x12=192 tiles using volatile images and Java2d.

Impossible to spot without the complete source. Maybe incompatible image formats. Use a profiler.In any case, 10x10 tiles is really nothing.I got a frame rate of 1400 when drawing 16x12=192 tiles using volatile images and Java2d.

The OP says the problem occurs with 100x100 tiles. By today's standards that isn't much, but it's too much for Java2D's standards.

I'd love to see a self-contained example using volatile images. Could you post some code?

Okay, I just took the written 1000 tiles, not 10000. Which sums up to a lot for 60fps indeed.I would use bigger tiles in any case...I don't have an extractable example, but you have to take care to create compatible images, not to mess with pixels and get images unmanaged.

You really shouldn't keep BufferedImages in your Tiles, but rather a String-identifier. Then have a HashMap of BufferedImages with a String as key, so you can do something like:g2d.drawImage(imageMap.get(floorAl.get(i).getImageString()), null, floorAl.get(i).getX(), floorAl.get(i).getY());

I don't know if that'll help your FPS, though. Can you post your Tile-class in the pastebin and provide a link?Are you making sure that the images you load are compatible with the graphicscontext?

have something like a "manager"-class managing all the Images (so for example "ImageManager").

Then the ImageManager holds a hash-map of all the Images you have in your res/ folder (or whatever), and then puts them into a HashMap<String, BufferedImage>.The String (the Key), will have the name of the Image loaded (for example "grass.png" / "dirt.png" / "characters/mike.png" or whatever).

Then in the constructor of the Tile you ask the ImageManager for a reference of the Image, called (for example) "grass.png", and save it in a member field.

Tl;Dr:same as Ultroman, but you won't need to "load" the BufferedImage from the HashMap everytime you want to draw it, which is bad (or slow), because it needs to "search" through the map with an algorithm. The more Images you have, the longer it will take to get it from the HashMap.Just take a reference to the Image, which is then actually stored in another class and only loaded once.

Below you can see the classes of the program. I made a small version of my game that runs in windowed mode (the same problem with fps dropping occurs in both full screen mode and NON full screen mode) which only paints the background and contains the classes that are needed to do that.

[EDIT:]You can change the map size by modifying the mHeight and mWidth variables at the very beginning of the World class.

I tried using volatileImages but didn't speed up my FPS value.An alternative of Java2D like slick2D is not an option right now. I'd like to find a way to solve my problem using java2D. In case I can't find a solution, then I'll use another library like slick2D, etc.

same as Ultroman, but you won't need to "load" the BufferedImage from the HashMap everytime you want to draw it, which is bad (or slow), because it needs to "search" through the map with an algorithm. The more Images you have, the longer it will take to get it from the HashMap.Just take a reference to the Image, which is then actually stored in another class and only loaded once.

What is the difference from your method to mine, except for the dedicated class? My suggestion was essentially the same: "have a HashMap of BufferedImages with a String as key". I've done somewhat what you said for my game, and put my static HashMap of images in a ResourceHolder class, so I can access it from every class that has a reference to the ResourceHolder, like my Creator-class and my draw-method in the Game-class.

Do you mean you give the Tile-class a BufferedImage as a parameter in the constructor from the Tile-class? So you're linking the image to the Tile-class instead of looking it up every update?

Just to clarify; this could come off as a whiney post, but I'd just love to know how much I can gain from changing to your proposed method compared to mine. I was under the impression HashMap lookups were pretty instantaneous.

I think I found a temporary solution to my problem, although any other ideas are more than welcomed. My solution is to load images as ImageIcons. I tried to load a 100x100 map at 80 fps/ups and the results were the game to run at 50 fps and 80 ups.

I'm checking, updating animations on, and drawing around 3-500 40x40px tiles at a steady 60fps, and this only takes up about a millisecond per frame/update. There must be something terribly wrong in your code. Are you sure you're not reloading all images each draw or update or something?

I'd recommend doing some timing-debugging on the different parts of your gameloop, to figure out what is taking so much time. Time every event, like update(), draw() and whatever you have.

That could be it but even then 1k images should not be that slow. Make sure you are loading images by getting compatible images from the Graphics Environment. You can also specify whether you want transparency or not. Java2D does some software rendering which means that as you scale up screen size you don't get fill rate limited.

Also, when it comes to storing images, there is nothing wrong with having a BufferedImage reference in a class. It is good to have a resource management system but keeping a reference is not bad either.

You should not deal with ImageIcons. You need to properly load everything.

If the rendering is too slow, use more memory,eg: precalculate static tiles/backgrounds wich dont change.

If the rendered map image is too large, only rerender the part wich is visible + some border to enable a smooth scrolling.

The problem then is probably then the order of elements (eg dynamic elements must be obstructed by walls)There is a range of solutions. (like a Z Buffer, or a partial rendering)But basically, the floor-tiles can be drawn first anyway, as everything is ontop of them, they cannot obstruct anything.

I think that java2D does z culling under the hood. They create rectangles and wont draw the intersection of said rectangles. The key here is draw calls. Problem with tile based systems is that if you have 1000 tiles that need to be drawn that is 1k draw calls. Cut down on draw calls as much as possible. All games I have made run fairly well at 1-2k draw calls. fillShape() drawImage() once you pass 5k, just about any system will drop fps like crazy. Size of image has virtually no impact on performance on most systems that have a DGPU.

same as Ultroman, but you won't need to "load" the BufferedImage from the HashMap everytime you want to draw it, which is bad (or slow), because it needs to "search" through the map with an algorithm. The more Images you have, the longer it will take to get it from the HashMap.Just take a reference to the Image, which is then actually stored in another class and only loaded once.

What is the difference from your method to mine, except for the dedicated class? My suggestion was essentially the same: "have a HashMap of BufferedImages with a String as key". I've done somewhat what you said for my game, and put my static HashMap of images in a ResourceHolder class, so I can access it from every class that has a reference to the ResourceHolder, like my Creator-class and my draw-method in the Game-class.

Do you mean you give the Tile-class a BufferedImage as a parameter in the constructor from the Tile-class? So you're linking the image to the Tile-class instead of looking it up every update?

Just to clarify; this could come off as a whiney post, but I'd just love to know how much I can gain from changing to your proposed method compared to mine. I was under the impression HashMap lookups were pretty instantaneous.

Hmmm... Yes. The only difference between your method and mine is the constructor stuff, and removing the lookup from the render method.

And I don't know how long a lookup in HashMap takes. I'm really not sure, but I'm sure a field "lookup" is much faster. And since rendering methods are called very very often, I thought that could be a huge difference... But I'm just checking how long a HashMap lookup would take... (I am also pretty sure that HashMap lookup time is dependent on the number of entrys. So it would take much longer if you'd have tons of sprites... and that'd be bad...).

Could be possible that would fall into the "premature optimization" bag...

Hmmm... Yes. The only difference between your method and mine is the constructor stuff, and removing the lookup from the render method.

And I don't know how long a lookup in HashMap takes. I'm really not sure, but I'm sure a field "lookup" is much faster. And since rendering methods are called very very often, I thought that could be a huge difference... But I'm just checking how long a HashMap lookup would take... (I am also pretty sure that HashMap lookup time is dependent on the number of entrys. So it would take much longer if you'd have tons of sprites... and that'd be bad...).

Could be possible that would fall into the "premature optimization" bag...

The more I think about it, the more I know you're right I'd hate to find out now that my teachers are full of it, and that HashMaps aren't instantaneous.

I know this problem very well. You should not draw all the tiles simultaneously, only the ones that are visible. This way you can easily get around 1k visible tiles without much fps drop with simple java2d. At least I don't get any FPS drop while filling the screen with pink 1px height tiles on my netbook in this applet: http://jonjavaweb.orgfree.com/TestApplet.html (press W to insert pink tiles).

If you minimize the window where the applet is and maximize it again you get a glimpse of how and how fast the tiles are drawn on the screen. There should be around 50+ tiles per platform that are fit inside the screen + a few more extra to make sure you don't get undrawn tiles when moving the screen. So adding 20 pink tiles to each visible pillar/tile coordinate you should get around 20*50=1k tiles.

Then again why you'd need that many 1 pixel height tiles ontop of each other is very rare and performace shouldn't be an issue if you stick to minimum of 8px height tiles, even on larger screen sizes.

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