patternjavaMinor
Slow rendering method
Viewed 0 times
renderingslowmethod
Problem
The code works fine, but the speed stays at a consistent eight frames per second.
Today I fixed some pieces and got four more frames per second.
I figured out that the typecasting
Is there anything I can do to improve the performance of this code?
Some more context
And
but for this part now it's just a few booleans for later in the game.
Today I fixed some pieces and got four more frames per second.
I figured out that the typecasting
(int) and Math.floor() consume around 50 fps.Is there anything I can do to improve the performance of this code?
public void render(){
for(int y = 0; y = Game.WIDTH / 2 - 16 && x = Game.HEIGHT / 2 - 16 && y = Game.WIDTH / 2 - 16 && x = Game.HEIGHT / 2 - 16 && y 574 && y 290 && x 540 && x < 700){
Game.pixels[screenPix] = 0xffffffff;
}
}
continue;
}
}
}
}Some more context
TreeMap guiSprites = new TreeMap();Game is the Main Class the produce a JFrame and some other stuff until it starts to call render() that actually calls the above code.private void render() {
bs = getBufferStrategy();
if(bs == null){
createBufferStrategy(2);
return;
}
screen.render();
g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
g.dispose();
bs.show();
}And
Core is a Class that handles information given by the server,but for this part now it's just a few booleans for later in the game.
Solution
This is only a quick review, since I don't know much in the area of rendering graphics
Repeated Work
There are many lines that are inside of a loop that do not need to be. Every time you move a pixel in the x direction, the inner loop, these results do not change, so you can save them in a variable outside of the x loop. This alone will save you a bunch of repeated calculations.
Modular Code
The fact you need a comment to explain that the difference between this and later code is the order, shows that this is perfect to abstract to a method.
This will make it much easier to read, and you don't have to change code in multiple places, such as if a value changes.
if x is an int, and offsetX is an int, we have
Basically, you don't need to round down anything if everything inside is going to be an integer. This also means you don't have to cast the double you got from Math.floor back to an int, saving even more time.
So many pretty powers of 2, I'm guessing it is deliberate. It is a good idea, it speeds up multiplication and division because x the micro-optimisations you implement. Low level changes like these make code harder to read, harder to change later, and more prone to bugs, if edge cases aren't accounted for. Do them last if you need the small boost to go from 58 fps to 60
Profile the code, and with each change test it again, the only way to really improve performance is to know where the bottleneck is. Sometimes it is in the last place you expect.
Repeated Work
screenPix = x + y * width;
chunkY = (int) Math.floor((y + offsetY) / 512);
tileY = (int) Math.floor(((y + offsetY) - (chunkY * 512)) / 32);There are many lines that are inside of a loop that do not need to be. Every time you move a pixel in the x direction, the inner loop, these results do not change, so you can save them in a variable outside of the x loop. This alone will save you a bunch of repeated calculations.
Modular Code
//render order: player object event
if(x >= Game.WIDTH / 2 - 16 && x = Game.HEIGHT / 2 - 16 && y <= Game.HEIGHT / 2 + 16){//wrong
//TODO render player
//TODO render equip
}
if(SpriteManager.objectSpritesGet(currTile.getObjectID()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.objectSpritesGet(currTile.getObjectID()).pixels[tilePix];
if(SpriteManager.objectSpritesGet(currTile.getObjectID2()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.objectSpritesGet(currTile.getObjectID2()).pixels[tilePix];
if(SpriteManager.objectSpritesGet(currTile.getObjectID3()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.objectSpritesGet(currTile.getObjectID3()).pixels[tilePix];
if(Core.builderMode){
if(Core.builderModePathMode && SpriteManager.eventSpritesGet(currTile.getEventWalkPath()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.eventSpritesGet(currTile.getEventWalkPath()).pixels[tilePix];
if(Core.builderModeEventMode && SpriteManager.eventSpritesGet(currTile.getEventID()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.eventSpritesGet(currTile.getEventID()).pixels[tilePix];
}else{
if(SpriteManager.eventSpritesGet(currTile.getEventAlias()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.eventSpritesGet(currTile.getEventAlias()).pixels[tilePix];
}
continue;The fact you need a comment to explain that the difference between this and later code is the order, shows that this is perfect to abstract to a method.
renderPlayer(x, y);
renderObject(tilePix, etc..);
renderEvent(Core.builderMode, tilePix, etc..);This will make it much easier to read, and you don't have to change code in multiple places, such as if a value changes.
chunkX = (int) Math.floor((x + offsetX) / 512);if x is an int, and offsetX is an int, we have
int = (int) Math.floor((int + int) / int);
=> int = (int) Math.floor(int / int);
=> int = (int) Math.floor(int);Basically, you don't need to round down anything if everything inside is going to be an integer. This also means you don't have to cast the double you got from Math.floor back to an int, saving even more time.
chunkX = (x + offsetX) / 512;512, 32, 2, 16So many pretty powers of 2, I'm guessing it is deliberate. It is a good idea, it speeds up multiplication and division because x the micro-optimisations you implement. Low level changes like these make code harder to read, harder to change later, and more prone to bugs, if edge cases aren't accounted for. Do them last if you need the small boost to go from 58 fps to 60
Profile the code, and with each change test it again, the only way to really improve performance is to know where the bottleneck is. Sometimes it is in the last place you expect.
Code Snippets
screenPix = x + y * width;
chunkY = (int) Math.floor((y + offsetY) / 512);
tileY = (int) Math.floor(((y + offsetY) - (chunkY * 512)) / 32);//render order: player object event
if(x >= Game.WIDTH / 2 - 16 && x <= Game.WIDTH / 2 + 16 && y >= Game.HEIGHT / 2 - 16 && y <= Game.HEIGHT / 2 + 16){//wrong
//TODO render player
//TODO render equip
}
if(SpriteManager.objectSpritesGet(currTile.getObjectID()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.objectSpritesGet(currTile.getObjectID()).pixels[tilePix];
if(SpriteManager.objectSpritesGet(currTile.getObjectID2()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.objectSpritesGet(currTile.getObjectID2()).pixels[tilePix];
if(SpriteManager.objectSpritesGet(currTile.getObjectID3()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.objectSpritesGet(currTile.getObjectID3()).pixels[tilePix];
if(Core.builderMode){
if(Core.builderModePathMode && SpriteManager.eventSpritesGet(currTile.getEventWalkPath()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.eventSpritesGet(currTile.getEventWalkPath()).pixels[tilePix];
if(Core.builderModeEventMode && SpriteManager.eventSpritesGet(currTile.getEventID()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.eventSpritesGet(currTile.getEventID()).pixels[tilePix];
}else{
if(SpriteManager.eventSpritesGet(currTile.getEventAlias()).pixels[tilePix] != 0xffff00ff) Game.pixels[screenPix] = SpriteManager.eventSpritesGet(currTile.getEventAlias()).pixels[tilePix];
}
continue;renderPlayer(x, y);
renderObject(tilePix, etc..);
renderEvent(Core.builderMode, tilePix, etc..);chunkX = (int) Math.floor((x + offsetX) / 512);int = (int) Math.floor((int + int) / int);
=> int = (int) Math.floor(int / int);
=> int = (int) Math.floor(int);Context
StackExchange Code Review Q#104164, answer score: 4
Revisions (0)
No revisions yet.