Large image rendering

Hello there! Again, i met a problem.

Until now i used to render only 32x32 or 40x40 sprites. But now when i needed to render some bigger image my game went from 60FPS to 4-5 FPS.

Here is my rendering code:


		g.clearRect(0, 0, screen.getWidth(), screen.getHeight());
		g.setColor(new Color(0x000000));
		g.fillRect(0, 0, screen.getWidth(), screen.getHeight());
		
		g.translate(xOffset, yOffset);
		
		for(int i=0; i<onscreenTiles.size(); i++) {
			Tile t = (Tile) onscreenTiles.get(i);
			if(t instanceof FloorTile)
				g.drawImage(t.getImage(), null, (int) t.getX(), (int) t.getY());
			else if(t instanceof HoleTile)
				g.drawImage(t.getImage(), null, (int) t.getX(), (int) t.getY());
			else if(t instanceof PathTile)
				g.drawImage(t.getImage(), null, (int) t.getX(), (int) t.getY());
		}
		for(int i=0; i<level.getOthers().size(); i++) {
			if(level.getOthers().get(i) instanceof Drop) {
				Drop d = (Drop) level.getOthers().get(i);
				d.getAnim().draw(g, d.getX(), d.getY());
			}
		}
		for(int px=Math.max(0 ,(int) -yOffset)-24; px<=Math.max(0, Math.abs((int) yOffset)) + screen.getHeight(); px++) {
			for(int i=0; i<onscreenEntities.size(); i++) {
				Entity e = (Entity) onscreenEntities.get(i);
				if(e != null && (int)e.getY() == px) {
					if(e instanceof Mummy) {
						if(((Entity) e).isDead()) ((Mummy) e).getDieAnim().draw(g, (float) (e.getX()-e.getWidth()/2), (float) (e.getY()-e.getHeight()/2));
						else ((Mummy) e).getMoveAnim().draw(g, e.getX(), e.getY());
					} else if(e instanceof Spawner) {
						if(((Entity) e).isDead()) ((Spawner) e).getDieAnim().draw(g, (float) (e.getX()-e.getWidth()/2), (float) (e.getY()-e.getHeight()/2));
						else g.drawImage(e.getImage(), null, (int) e.getX(), (int) e.getY());
					}
				}
			}
			
			for(int i=0; i<pl.getBullets().size(); i++) {
				Entity e = (Entity) pl.getBullets().get(i);
				if((int)e.getY() == px && isInScreen(e)) {
					g.drawImage(e.getImage(), null, (int) e.getX(), (int) e.getY());
				}
			}
			
			if((int)pl.getY() == px) {
				if(!pl.isWalking()) g.drawImage(pl.getImage(), null, (int) pl.getX(), (int) pl.getY());
				else pl.getMoveAnim().draw(g, pl.getX(), pl.getY());
				if(pl.isFiring()) pl.getmFlash().draw(g, pl.getMuzzleX(), pl.getMuzzleY());
			}
			
			for(int i=0; i<level.getBuildings().size(); i++) {
				Building b = (Building) level.getBuildings().get(i);
				g.drawImage(b.getImage(), null, (int) b.getX(), (int) b.getY());
			}
			
			for(int i=0; i<onscreenTiles.size(); i++) {
				Tile t = (Tile) onscreenTiles.get(i);
				if((int)t.getY() == px && t instanceof WallTile) {
					g.drawImage(t.getImage(), null, (int) t.getX(), (int) t.getY()-24);
				}
			}
		}

The problem is at

for(int i=0; i<level.getBuildings().size(); i++) {
				Building b = (Building) level.getBuildings().get(i);
				g.drawImage(b.getImage(), null, (int) b.getX(), (int) b.getY());
			}

The image is 256x224 and is loaded (as the others) at the application start.
What can i do?

There are some good optimization tips here:

I’d personally recommend ditching Java2D altogether and going with OpenGL (i.e. LibGDX or Slick). Especially if you’re depending on the “java2d.opengl” flag to have your game run at a reasonable framerate (which I’m not even sure works on MacOSX), then you may as well not use Java2D…

256x224 - that’s only 60,000 pixels. Java2D should be able to draw 100,000 of those sprites per second.

g.drawImage(t.getImage(), null, (int) t.getX(), (int) t.getY());
You should change that to
g.drawImage(t.getImage(), (int) t.getX(), (int) t.getY(), null);

You were using this method
http://docs.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#drawImage(java.awt.image.BufferedImage, java.awt.image.BufferedImageOp, int, int)
But you probably want this one
http://docs.oracle.com/javase/6/docs/api/java/awt/Graphics.html#drawImage(java.awt.Image, int, int, java.awt.image.ImageObserver)
I’m not sure though if that makes much of a difference. The reason for the low performance is probably somewhere else.

In my experience Slick is not faster than Java2D. So if you want to part with Java2D, I would say go for LibGDX.

I am using g.drawImage(image, null x, y); because i am working with bufferedimage, not image.

You can draw with BufferedImages using g.drawImage(image,x1,y1,null);

I do it all the time.

I can render 120+ images that are 1200x1200 pixels at 60 fps no problem. You start to lose performance when you are rendering with things like filters, transformations, and alpha changes. Also scaling has some performance hit. (although in my testing its very little)

okay, thanks.

one more question: is changing from Java2D in libGDX too hard, i mean, do i have to change all my code or only some simple parts of it?

[quote]In my experience Slick is not faster than Java2D. So if you want to part with Java2D, I would say go for LibGDX.
[/quote]
And how did you come to that conclusion?

And how did you come to that conclusion?
[/quote]
I wrote a program that draws and fills a large number of polygons. Using Java2D I actually get more fps than with slick.

LibGDX is very different from Java2D, but if you kept rendering and game logic separate you only have to change the rendering code.

[quote]I wrote a program that draws and fills a large number of polygons. Using Java2D I actually get more fps than with slick.
[/quote]
???

Slick (hardware accelerated) should definitely outperform Java2D (software renderer) in image/geometry rendering; if it’s slower, then you’re very likely doing something wrong.

I don’t really like to switch to using a library… And if i go, i will go with lwjgl.

Is okay to firstly start playing with lwjgl in 2D ? And after some time start using 3D?

Like the others pointed out, for drawing images, Java2d should be more than fast enough.
Results of my very unscientific measurements:
Java2d dropped under 60fps at ~ 20.000 images of 64x64 pixels
I canceled the Libgdx test run at > 40.000 images

Nevertheless, I just switched to LibGdx for easier lighting in a couple of days.

First, you always created new object and casting every loop.