The Most Efficient Way To Make a 2D Game?

Hi. I have been making a game for a bit now, and I am experiencing the worst lag. Right now the game is based on a tile system, drawn on a jPanel. Basically there is a single BufferedImage on the jPanel, and then the BufferedImage is updated based on a double array of arraylists, containing all of the units occupying that space. The size is only 10x20.

I have 2 threads running, as a test. Well, actually Swing Timers. One timer runs every 40 milliseconds, and will draw the entire map by cycling through the previously mentioned array, and then using another set of for loops to draw each individual pixel. The other thread isn't actually doing anything at the moment, it is simply there to update what would be the AI. Then I have a KeyboardDispatcher which gets the input from the keyboard.

It just runs way too slowly... It's not even that I don't understand why it is running so slowly. I do. I just am curious how on earth something like a 3D game could run if something as small as this causes that much lag. In other words, what is the most common way of doing this? The most efficient? I have never used the Canvas class, and would prefer sticking with jPanel if possible. Although it might be simple to use them together, I have never actually looked into it.

Re: The Most Efficient Way To Make a 2D Game?

Java2D isn't bad in terms of performance considering it's software based (unless you're using volatile images which have hardware acceleration on some platforms). Also, most 3D games are probably using OpenGL bindings which mean the 3d is totally being rendered with hardware (mine craft uses LWJGL for example).

All that being said, I'd put $100 on the idea that it is your implementation that is slow, not java. I have written particle simulators that work with 500,000+ particles in java that run over 30fps (200+ in JOGL/LWJGL).

If you post your relevant drawing code here, I can take a look. Also, if you want smooth frame rates you'll need to do a couple things. Timers don't guarantee smooth performance, and uneven frame rates are common with this method. Games use a different system generally: You hard code in the refresh time into each entity that is moving/changing. You'r game logic can run at one speed, lets say every 3ms, but your screen refresh might run at a different speed, lets say every 15ms (~66fps). You measure the elapsed time every n number of cycles, and move/animate the entities based on how much time has actually passed instead of a fixed increment. This way if once cycle has a logic loop that takes 20ms instead of 3ms, your program eats the lost time rather than slowing down. You can also calculate frame rate averages over time and make adjustments to your animation cycle based on previous rendering statistics.

Another thing that can greatly accelerate your app with pixel by pixel animations is manipulating a bufferedImage directly. Rather than using Graphics from java2d to draw a 1x1 square, you can simply set the color of that pixel directly in the buffered image. This cuts out massive amounts of overhead when dealing with pixel level drawing.

For more complex stuff where you are compositing lots of individual images (especially those with transparency) it is important to draw as little as possible. You can help optimize this by only refreshing portions of the screen. If only the lower right side is being animated, then only refresh that part of the screen.

Finally, you need to profile your app to see what is actually eating all the time. You can do a poor-man's profile with some printouts of System.currentTimeMillis(). Here is an example:

And so on. The printouts and timers will add a bunch of overhead, but you'll get a relatively proportionate snapshot of what is eating all the cpu time. If all the measurements are 1-2ms except one which is 50ms, then that is where you need to look into optimizing. A priority for you should be determining what is taking the most time - logic or drawing. Both can be optimized greatly depending on what you're doing.

For example, for one project I was working on, there were about 1000 bouncing balls on the screen. They needed to support collision between balls. A simple brute force check for collision (compare every possible set of 2 balls to see if they are collided) slowed the program down to a pathetic < 1fps. Even openGL would not have helped at all, as profiling showed that 99% of my cpu time was spent calculating collision every cycle. I investigated quad trees which are often used for this purpose (and oct trees for 3d space) and found that a couple pages of extra code brought my program up to a smashing 70fps. What changed? Rather than making n^2 comparisons 70 times per second, I was able to drop the total number of comparisons down to log(n). So, I went from 70000000 compares per second to around 700. That is obviously orders of magnitude less work for the program.

Re: The Most Efficient Way To Make a 2D Game?

Wow thanks, that helped a lot. I remember hearing something about interpolation from some website I was looking at, and I guess you just explained it a lot better. I will start working with that right away, thanks again!

Re: The Most Efficient Way To Make a 2D Game?

It just runs way too slowly... It's not even that I don't understand why it is running so slowly. I do

FWIW, if you have not yet I would recommend profiling the code. Sometimes one can spend hours, days, or weeks optimizing the completely wrong piece of code. When/if you have truly nailed down the culprit, how you solve the problem is completely situation dependent - for instance, you mention you draw all the images then cycle through and draw each individual pixel? Sounds like a lot of repetitive work...of course, without an SSCCE as an example demonstrating slow rendering then we can't help you with your implementation and possible bottlenecks.

Re: The Most Efficient Way To Make a 2D Game?

I have definetely nailed what is taking so long. I switched the individual pixel transfers over to modifying the raster data instead, and the changes were practiaclly instananeous (3-5ms as opposed to 360-400ms per update).

However, I think I have found a solution. I am modifying the data through the ColorModel and Raster instead of the pixels themselves. However, I have no idea how the ColorModels work. I think I will go make another thread about that, so I guess I will end this one, unless anyone has any other suggestions on how to do this. Sorry about the limited amount of information, but this is more of a learning project, and I'm more interested in why it works than getting it to work.

EDIT: Oh and one more thing, I forgot to say the problem with using just Raster data. It works, and the image appears, but the colors are all wrong. I have discovered (as mentioned above) that it is the ColorModel causing the color problem, but at least it is running :D