Full Screen Performance and Memory Consumption

Hello everybody, am trying to implement a full screen mode in my game, I made two versions of the implementation, each version has it’s own pros and cons.

Lets start with the first version…
I load all my sprites like this :


for(int j=0;j<9;j++){
sprite[j]=Sprite.getSubimage(960*j,0,960,540);}

Sprite is a bufferedImage.
Sprite[] is an array of BufferedImages.

Then in the render method i scale proportionally all the sprites according to the user screen dimensions using g.scale(…)
For example if the player screen is 1366*768 (like mine) (the default game resolution is 960x540)

Dimension screenSize= Toolkit.getDefaultToolkit().getScreenSize();

Width_proportions=screenSize.getWidth()/DefaultWidth;
Height_proportions=screenSize.getHeight()/DefaultHeight;

Width_proportions= 1.4229166666666666 Height_proportions= 1.4222222222222223

Then inside the render method :

g.scale(Width_proportions,Height_proportions)

Pros & Cons

  • Pros : The Game don’t consume so much memory(Only 180MB)
  • Cons : The g.scale method run inside a loop so its gonna eat up all the game FPS , its drops below 60 (60 is the normal game FPS)

Now the second version
like the first version it calculate the same proportions

Dimension screenSize= Toolkit.getDefaultToolkit().getScreenSize();
Width_proportions=screenSize.getWidth()/DefaultWidth;
Height_proportions=screenSize.getHeight()/DefaultHeight;

But this time am going to scale only and only one time all the sprites when the game starts so instead of loading the sprites like this :


for(int j=0;j<9;j++){
sprite[j]=Sprite.getSubimage(960*j,0,960,540);}

Its now done in this way :


for(int j=0;j<9;j++){
sprite[j]=scale(Sprite.getSubimage(960*j,0,960,540),960,540);}


private BufferedImage scale(BufferedImage srcImg, int w, int h){
	    BufferedImage resizedImg = new BufferedImage((int)(w*Width_proportions), (int)(h*Height_proportions), BufferedImage.TRANSLUCENT);
	    Graphics2D g2 = resizedImg.createGraphics();
	    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
	    		RenderingHints.VALUE_ANTIALIAS_ON);
	    		g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
	    		RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	    g2.drawImage(srcImg, 0, 0,(int)(w*Width_proportions), (int)(h*Height_proportions), null);
	    g2.dispose();
	    return resizedImg;
	}

And of course am recalculating all the sprites positions by multiplying the sprites x positionWidth_proportions and yHeight_proportions
Pros & Cons

  • Pros : FPS skyrocks to 170 with a nice smooth antialiased sprites :o :o ;D ;D :yawn: :yawn:
  • Cons : memory consumption 870MB and when i set the screen resolution to 1920x1080 (Width_proportions and Height_proportions are >=1.5 in this case =2.0 ) OutOfMemoryError comes in place and game loading time increase :expressionless: :expressionless: :cranky: :emo: :’(

I like how the fps is great and the sprites are nicely antialiased but i think am switching back the first version , any help would be appreciated to make the seconde version work better. :smiley:
Finaly sorry for my Bad sleepy english i just woke up from a deep sleep just to write this topic , and now am going back to rest .

To combat the high memory usage in your second method, you need to stop allocating new BufferedImages every frame. That’s going to consume ridiculous amounts of memory at high resolutions.
What you really need to do is, yes, draw to an offscreen buffer, but also reuse that buffer. So, clear the image with the graphics object and then draw to it, instead of creating a new one every time.
I’d only ever recreate the image under special conditions, like a resolution change.

In fact, what’s stopping you from just drawing srcImage straight to the screen at a larger size, where you’re drawing it to yet another image and then drawing it? Why do you need another BufferedImage (resizedImg) at all?

Hi

Do you seriously think it’s not so much? Sorry, I don’t want to be harsh. If you’re worried about performance, don’t use Java2D and replace your images by vectorized contents to reduce your memory footprint. For example, instead of storing 262544 (512*512) pixels of a single image, I store about 10000 triangles. Good luck.

I see that no one picked up on the obvious error that you should never use a BufferedImage for this kind of offscreen buffer. This should be a VolatileImage. You should look at the difference in how the two are accelerated (hint, the way this is done nothing is!)