Reputation: 75
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.
Upvotes: 4
Views: 718
Reputation: 2066
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.
Upvotes: 7
Reputation: 14004
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:
public class Circle extends Body
{
// override
public void draw(Graphics g)
{
...
}
}
...
void drawBody(Body body)
{
body.draw();
}
Upvotes: 6
Reputation: 192035
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().
Upvotes: 4
Reputation: 28429
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.
Upvotes: 6