内容来自RyiSnow
视频讲解
second half部分
本节讲了提升渲染性能improving rendering performance。
主要是在显示图片的时候,避免在游戏的update()
, repaint()
循环中进行图片的缩放处理,在游戏循环开始前就将图片缩放处理完毕;还有一个提示是避免在循环中创建对象。
渲染花费时间测试
protected void paintComponent(Graphics g) {
//DEBUG
long drawStart = System.nanoTime();
//...绘制部分省略
//tile
//objects..
//player
//ui
// DEBUG
if (keyH.checkDrawTime) {
long drawEnd = System.nanoTime();
long passed = drawEnd - drawStart;
g2.setColor(Color.white);
g2.drawString("Draw Time: " + passed, 10, 400);
System.out.println("Draw Time: " + passed);
}
}
在KeyHandler类增加了一个按t键,在窗口显示渲染时间的逻辑。
修改代码前部分时间数据
(75096(lowest) -- 196411, 569102(highest))
Draw Time: 81966
Draw Time: 81601
Draw Time: 75895
Draw Time: 78681
Draw Time: 81368
Draw Time: 110488
Draw Time: 90020
Draw Time: 83875
Draw Time: 86664
Draw Time: 158162
Draw Time: 85771
Draw Time: 82449
Draw Time: 76741
Draw Time: 91776
Draw Time: 76311
Draw Time: 122516
Draw Time: 107965
Draw Time: 102210
Draw Time: 85678
Draw Time: 77376
Draw Time: 87888
Draw Time: 99485
Draw Time: 86709
Draw Time: 84182
Draw Time: 81086
Draw Time: 93216
Draw Time: 108883
Draw Time: 79212
Draw Time: 82867
Draw Time: 89486
Draw Time: 85493
Draw Time: 86861
Draw Time: 82058
Draw Time: 85923
Draw Time: 87204
Draw Time: 83029
Draw Time: 79398
Draw Time: 86177
Draw Time: 105075
Draw Time: 90452
Draw Time: 77599
Draw Time: 86111
Draw Time: 87980
Draw Time: 119487
Draw Time: 84931
Draw Time: 189866
Draw Time: 131636
Draw Time: 96647
Draw Time: 79113
Draw Time: 87053
Draw Time: 84061
Draw Time: 86468
Draw Time: 92926
Draw Time: 121758
Draw Time: 92020
Draw Time: 81570
Draw Time: 77743
Draw Time: 154429
基本平均数约80000纳秒
81578 / 1000 000 000 约等于 0.000 08 second秒
修改图像缩放部分代码
主要是将缩放部分,提前处理完毕,避免每次repaint都进行缩放,以此提升效率。原始的资源图片都是16x16,然而窗口的显示大小都是48x48的,所以有一个放大的处理。
在paintComponent或update循环中避免创建对象。
g2.drawImage(tile[tileNum].image, screenX, screenY, gp.tileSize, gp.tileSize, null);
上面的Graphics2D的drawImage方法,将原始图像放大后再进行了绘制,每一帧都会进行这样的处理,虽然方便,但还是花时间的,所以提前将此图片放大处理完毕,这样每一帧就不再处理放大。
BufferedImage scaleImage = new BufferedImage(gp.tileSize, gp.tileSize, tile[0].image.getType());
Graphics2D g2 = scaleImage.createGraphics();
g2.drawImage(tile[0].image, 0, 0, gp.tileSize, gp.tileSize, null);
tile[0].image = scaleImage;
根据这个线索,调试查看了一下,Graphics2D是一个抽象类,上面的drawImage方法又是继承自Graphics类,他们都是抽象类,这个方法具体实现类是
SunGraphics2D
类,最终调用如下方法处理
public final class SunGraphics2D extends Graphics2D implements ......{
//...
public boolean drawImage(Image img, int x, int y, int width, int height,
Color bg, ImageObserver observer) {
if (img == null) {
return true;
}
if ((width == 0) || (height == 0)) {
return true;
}
final int imgW = img.getWidth(null);
final int imgH = img.getHeight(null);
if (isHiDPIImage(img)) {
return drawHiDPIImage(img, x, y, x + width, y + height, 0, 0, imgW,
imgH, bg, observer);
}
//宽高相等
if (width == imgW && height == imgH) {
return copyImage(img, x, y, 0, 0, width, height, bg, observer);
}
//如果不都相等,则缩放
try {
return imagepipe.scaleImage(this, img, x, y, width, height,
bg, observer);
} catch (InvalidPipeException e) {
try {
revalidateAll();
return imagepipe.scaleImage(this, img, x, y, width, height,
bg, observer);
} catch (InvalidPipeException e2) {
// Still catching the exception; we are not yet ready to
// validate the surfaceData correctly. Fail for now and
// try again next time around.
return false;
}
} finally {
surfaceData.markDirty();
}
}
//...
}
imagePipe的实现是ValidatePipe,具体缩放方法,没找到实现,改天再研究。
修改代码后的测试
Draw Time: 151146
Draw Time: 186406
Draw Time: 150766
Draw Time: 186129
Draw Time: 143726
Draw Time: 158520
Draw Time: 144338
Draw Time: 97132
Draw Time: 192430
Draw Time: 97546
Draw Time: 146375
Draw Time: 115086
Draw Time: 189544
Draw Time: 115722
Draw Time: 162616
Draw Time: 179987
Draw Time: 168428
Draw Time: 113938
Draw Time: 138903
Draw Time: 99984
Draw Time: 141393
Draw Time: 98835
Draw Time: 153757
Draw Time: 107112
Draw Time: 197043
Draw Time: 111609
Draw Time: 171709
Draw Time: 100114
Draw Time: 166702
Draw Time: 103464
Draw Time: 160031
Draw Time: 100773
Draw Time: 226621
Draw Time: 159755
Draw Time: 155813
Draw Time: 164293
Draw Time: 1569453
Draw Time: 106167
Draw Time: 184712
Draw Time: 111770
Draw Time: 150976
Draw Time: 103760
Draw Time: 141755
Draw Time: 137113
Draw Time: 182971
Draw Time: 97870
Draw Time: 254421
Draw Time: 98279
Draw Time: 148167
Draw Time: 107782
Draw Time: 193752
Draw Time: 102801
Draw Time: 182475
Draw Time: 119705
Draw Time: 167910
Draw Time: 181605
Draw Time: 161602
Draw Time: 112700
Draw Time: 144261
Draw Time: 97704
Draw Time: 210764
Draw Time: 210067
Draw Time: 158860
Draw Time: 159127
Draw Time: 196001
Draw Time: 128468
Draw Time: 180168
Draw Time: 179872
Draw Time: 117463
Draw Time: 141411
Draw Time: 98539
Draw Time: 155322
Draw Time: 97066
Draw Time: 1688816
根据这个时间和前面的时间对比,感觉不但没有提升,反而渲染性能下降了,迷茫了……
优化前基本渲染一次的时间是5位数,优化后时间竟然6位数的时候居多,😕。单位都是纳秒。不科学。这个后续还需要研究,看up的理论是没有问题的,up实践后性能提升了大约20000纳秒。
代码
参第6篇文章末尾。