Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Horrendous Performance in a Simple Java2D App

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.

like image 336
Ido Yehieli Avatar asked Nov 28 '22 20:11

Ido Yehieli


1 Answers

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.

like image 158
James Avatar answered Dec 05 '22 18:12

James