Java Tile Engine Super Slow

Started by
22 comments, last by gstyle 12 years, 5 months ago
Okay, I only changed a couple of the methods in Level to reflect what I had needed, as well as part of LevelRenderer.java, and the performance increase that should have grown tremendously is only hardly noticeable. Here are the differences I made:

Within Level.java:



// method to draw the current camera view of the level on the screen
public void drawLevel(Graphics gr, int x, int y)
{
gr.drawImage(cameraImage, x + offsetX, y + offsetY, null);
}

// method to render the actual image before drawing it
public void renderLevel()
{
// keeps track of graphics coordinate
int x, y;

// keeps track of tile to draw
int tileX, tileY;

tileY = coordY;

// draw all the tiles based on offsets, layer by layer
for (y = 0; y < SCREEN_HEIGHT; y += TILE_SIZE)
{
tileX = coordX;
for (x = 0; x < SCREEN_WIDTH; x += TILE_SIZE)
{
// determine which tile to draw based on tile color in array
switch (this.getTile(tileX, tileY))
{
case SPACE_COLOR:
cameraG.drawImage(tiles[0], x, y, null);
break;

case WALL_COLOR:
cameraG.drawImage(tiles[1], x, y, null);
break;
}

tileX++;
}

tileY++;
}

// steps to take in case of an offset
if (offsetX > 0)
{

}

if (offsetX < 0)
{

}

if (offsetY < 0)
{

}

if (offsetY > 0)
{

}
}

// method to update the level's current position for the camera
public void updateLevel(int input)
{
switch (input)
{
// up
case 0:
// update offset up if not too far up
if (coordY > 30)
{
offsetY += 2;
}

// if a tile length has been moved, then offset becomes 0 and coordY is decreased
if (offsetY >= TILE_SIZE)
{
offsetY = 0;
coordY--;
this.renderLevel();
}
break;
// left
case 1:
// update offset to the left if not too far left
if (coordX > 30)
{
offsetX += 2;
}

// if a tile length has been moved, then offset becomes 0 and coordX is decreased
if (offsetX >= TILE_SIZE)
{
offsetX = 0;
coordX--;
this.renderLevel();
}
break;
// right
case 2:
// update offset to the right if not too far right
if (coordX < width - 30)
{
offsetX -= 2;
}

// if a tile length has been moved, then offset becomes 0 and coordX is increased
if (offsetX <= -TILE_SIZE)
{
offsetX = 0;
coordX++;
this.renderLevel();
}
break;
// down
case 3:
// update offset down if not too far down
if (coordY < height - 30)
{
offsetY -= 2;
}

// if a tile legnth has been moved, then offset becomes 0 and coordY is increased
if (offsetY <= -TILE_SIZE)
{
offsetY = 0;
coordY++;
this.renderLevel();
}
break;
// jump
case 4:
break;
}
}


And within LevelRenderer.java:



// Run method for class
public void run(DisplayMode dm)
{
setBackground(Color.WHITE);
s = new Screen();
s.setFullScreen(dm, this);

this.createBufferStrategy( 2 );
buffer = this.getBufferStrategy();

while (!endGame)
{
try
{
// edit player and level
myPlayer.animatePlayer();
myLevel.drawLevel(gr, 0, 0);
myPlayer.drawPlayer(gr, (SCREEN_WIDTH / 2) - TILE_SIZE / 2, (SCREEN_HEIGHT / 2) - TILE_SIZE);

graphics = buffer.getDrawGraphics();
graphics.drawImage(buffer2, 0, 0, null);

if( !buffer.contentsLost() )
{
buffer.show();
}
}
catch (Exception ex)
{
System.err.println("Game Update Error: " + ex);
}

try
{
Thread.sleep(10);
}
catch (Exception ex)
{
System.out.println("Can't sleep!");
}
}

s.restoreScreen();
}


I made sure the code only calls to redraw the map once the user moves past a given offset of the screen where new tiles must be rendered and that it will simply shift the current image drawn of the map until that happens, as opposed to redrawing the entire view every loop. Did I implement this properly, or am I missing something? Your help is greatly appreciated! Btw, I haven't accounted yet for the increased tile sizes, but even still, shouldn't this be significantly faster? Thanks again.

Best regards,
Colton
Advertisement
Just had to comment that this thread helped fix MY stupid little code problem which was making me crazy. thanx!


Anyway, I ran across an article describing a speed issue in Java itself which may or may not be applicable
to the original poster or may no longer exist in java7 but here's the link anyway:

http://www.jhlabs.co...ged_images.html

It describes how certain methods can confuse Java's handling of hardware acceleration:
-Raster.getDataBuffer()
-BufferedImage.getRGB()/setRGB()
-BufferedImage.getSubImage()
-Attaching an ImageObserver to a BufferedImage
-Filtering a BufferedImage with FilteredImageSource

Man, seems like the more i learn the less i know!
Strong typing is for people with weak memories.

Have you profiled your code? (http://www.yourkit.com/ for example)

By the way, the following change halved the frame time on my computer (after taking into account the 10ms sleep delay)


In Level.java

// create blank camera canvas
cameraImage = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()0].getDefaultConfiguration().createCompatibleImage(SCREEN_WIDTH, SCREEN_HEIGHT);
//cameraImage = new BufferedImage(1280, 768, BufferedImage.TYPE_INT_ARGB);
//cameraImage.createGraphics();
cameraG = cameraImage.getGraphics();


The above creates temporary surfaces that don't require conversion when copying to a destination buffer.

Also, look into [font="Arial"]V[/font][color="#333333"][font="Arial"]olatileImage[/font][font="monospace"].[/font]
Colton, I've only skimmed most of the replies and the code since I'm at work but I haven't seen anyone suggesting turning on Java2D hardware acceleration yet. Have you tried that? AFAIK it's off by default. See here for how to enable it.
its super slow because you using GUI system as your render >_<...
just use a graphic API like OpenGL to render your game.
my 3d java game (using LWJGL) renders me over 4,000 fps.

for more info:

http://en.wikipedia.org/wiki/OpenGL
http://lwjgl.org/

hope its help you...
I might be wrong on this. But I am assuming that your level is larger than 1 screen. If so it appears that you are drawing your entire level every time you call renderLevel() in the last bit of code you posted. You should only draw the tiles that appear on screen when you render the level.

This topic is closed to new replies.

Advertisement