简单 Java2D 应用程序的可怕性能
我昨天刚刚完成了第 14 届 Ludum Dare 48 小时游戏制作竞赛的我的参赛作品,并决定在 java 中使用 java2d 进行图形处理。
我对 API 不太熟悉,也没有做过很多图形编程,但我的游戏很小(只有十几个左右非常小的移动物体),所以我认为我可以天真地对其进行编程,但仍然没有遇到性能问题问题。
不用说,我错了。 游戏在大多数情况下都表现良好,但一旦屏幕上移动的“敌人”过多或分辨率调得太高,游戏就会开始明显变慢。
我已经确定性能瓶颈是屏幕绘制功能,当这些功能被注释掉时,游戏速度非常快。
有人可以提醒我我在这里可能做错了什么吗? (非常短的)源代码位于此处,其中大部分内容Main 类,以及通常的嫌疑人是 draw() 函数在 内部游戏循环。
我已经使用 BufferStrategy 来更新屏幕,这样就不会出现问题,除非我做错了。
提前致谢, 我愿意。
I've just finished my entry for the 14th Ludum Dare 48-hours game making competition yesterday, and decided to do it in java using java2d for the graphics.
I'm not that familiar with the API and haven't done a lot of graphics programming, but my game is quite small (only a dozen or so very small moving object) so I assumed I could program it naively and still encounter no performance problems.
Needless to say, I was wrong. The game performs alright most of the time but once there are a bit too many 'enemies' moving around on the screen or the resolution is cranked up too high it start getting visibly slower.
I've determined the performance bottleneck to be the screen drawing functions, when those are commented out the game is very fast.
Could someone give me a heads up on what I might be doing wrong here? The (very short) source code is located here with most of it the Main class, with the usual suspects being the draw() function that is called in the inner game loop.
I already use a BufferStrategy to update the screen, so that shouldn't be the problem unless I'm doing it wrong.
Thanks in advance,
Ido.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一些观察,尽管我认为其中任何一个都没有多大帮助。
最主要的是您正在 AWT 线程上进行绘制。 重写paintComponent()并在对象上调用repaint()。 否则这可能会导致各种问题。
您可以在每一帧重新创建颜色。 这可能是也可能不是您想要缓存的内容之一。 我不认为为你的颜色设置一个常量可能会搞砸GCing,并且当你以后想要重用颜色时,会让事情变得更容易保持正常。
每帧都重新绘制整个窗口。 您只需要重新绘制更改的部分即可。
您不需要绘制背景。 设置背景颜色并让父母处理一切。
作为设计,主体应该负责自己绘制。 它们的主人应该通知它们需要被绘制而不是绘制它们。
身体每次都会重建它们的状态。 考虑让他们在不同时间存储它并根据需要改变它们。 您可能会花费大量时间在 drawCircleBody() 中进行三角计算,
需要考虑的是设置计时器而不是在 while 循环中使用睡眠。 这将为您提供更一致的帧速率,但您需要确保您实际上能够履行您的义务(或者如果您错过了最后期限,则将多个帧合并为一帧),否则您最终会创建太多线程。
考虑使用 SwingWorker 进行计算,然后在done()方法中更新状态,最后通过调用repaint()来完成。
这些只是一些事情。 您应该尝试看看什么有效,什么无效。 自从我做Java图形绘制以来已经有一段时间了。
A few observations, although I don't think any of them will help much.
The main thing is that you're painting off of the AWT thread. Override paintComponent() and instead call repaint() on the object. This can cause all sorts of problems otherwise.
You recreate colors every frame. This may or may not be one of those things that you want to cache. I don't think though that having a constant for your colors is likely to screw up GCing and will make things easier to keep straight when you want to reuse colors later.
You redraw the entire window every frame. You just need to repaint the sections that changed.
You don't need to draw the background. Set the background color and let the parent take care of everything.
As a design thing, the bodies should be in charge of drawing themselves. Their owner should notify them that they need to be drawn rather than drawing them.
The bodies recreate their state every time. Consider having them store it between times and mutate them as needed. You may be spending a lot of time doing trig calculations in the drawCircleBody()
Something to consider is setting up a timer rather than using a sleep in a while loop. This will get you a more consistent frame rate, but you need to make sure that you can actually meet your obligations (or coalesce multiple frames into one if you miss a deadline) or you'll end up creating too many threads.
Consider using a SwingWorker to do the calculations, then update the state in the done() method, finishing by calling repaint().
These are just a few things. You should experiment to see what works and what doesn't. It's been a while since I've done Java graphics drawing.
您的代码不遵循单线程规则:
http:// /java.sun.com/products/jfc/tsc/articles/threads/threads1.html
我不确定这是否会导致您所看到的特定性能问题,但它具有巨大的潜力问题,海事组织。
Your code isn't following the single threading rule:
http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
I'm not sure if this will cause the specific performance problems that you are seeing, but it stands out as a big potential problem, imo.
好吧,只要简单地看一下你的draw()函数,你似乎声明了许多新对象(特别是在drawPolygonBody中)。 尝试重用对象,而不是每次都声明一个新对象。
编辑:instanceof 有开销。 更好的主意是扩展 Body,使其具有能够绘制自身的 draw(Graphics g) 函数。 例如:
Well, just from a brief look at your draw() function, it seems that you're declaring a number of new objects (especially in drawPolygonBody). Try to reuse objects instead of declaring a new ones each time.
EDIT: instanceof has overhead. It would be a better idea to extend Body to have a draw(Graphics g) function that draws itself. eg:
您是否尝试过对其进行分析以查看绘图函数中的瓶颈在哪里?
光看它很难说太多,但我想知道为什么你要在drawPolygonBody中绘制和填充多边形。
另外,在drawBoxBody 中,您分别绘制四条线,而不是仅仅调用drawRect()。
Have you tried profiling it to see where in the drawing functions the bottleneck is?
It's hard to say much just by looking at it, but I'm wondering why you're both drawing and filling the polygon in drawPolygonBody.
Also, in drawBoxBody, you're drawing four lines separately instead of just calling drawRect().