How can I get a decent speed out of something like this?

Basically, if you have seen burning sand or the like, I want to make a simple clone of that, but am having trouble with the fact that it’s very laggy to iterate over the entire grid every frame.

Here is the current script I have, and I’m sure that there is a better way to do this: http://epitaph64.pastebin.com/m5c4eff3c

3 cents:

a) use int instead of Byte

b) make the array 1-dimensional:
grid[width*y+x]=…

c) make x the inner loop

for (int x = 0; x < width; x++) for (int y = 0; y < height; y++)…
to
for (int y = 0; y < height; y++) for (int x = 0; x < height; x++) grid[width*y+x]=…

What Hansdampf said :slight_smile:

I suspect that especially using the Byte type in your arrays is slowing you down as that causes boxing/unboxing/casting everywhere. Given the amount of array accesses per second in your code that might cause stressing the GC.

also, all those fillrects could be a serious performance issue ?

Could be, worth checking.
If so, converting your program to use a texture where you update the pixels directly might be a solution.

I also noticed a small thing in your update() method:
You can get rid of the “if (y - 1 >= 0)” if you let the for loop start with y=1 (especially since you have your ‘y’ loop inside your ‘x’ loop)
(that won’t be a huge performance gain, but at least the code would look faster ;))

Thanks everyone for these great suggestions. I’m going to implement them and see how it works. I was thinking of trying to use a VolatileImage, but I’m not sure slick supports them.

EDIT: Incorporated them all, and the framerate is still the same, but when I turn off rendering the rectangles, I get about 15-20 more fps with these new changes, and I get about 75 instead of 55-60 fps average (55-60 being the frame rate without any rectangles before the changes.) I guess that means I do need to find a better way to render all those pixels!

EDIT2: I profiled the program, and the draw method is using 95% of the CPU time during the whole run of the program. Anyone know how I can write these pixels to some kind of hardware buffered texture easily? I have about 198,432 rectangles to draw per frame at the moment :slight_smile:

If you are manipulating an image per-pixel, you want the image to be resident in system memory not graphics memory.
Create a BufferedImage of appropriate size & type, grab it’s Raster & DataBuffer, manipulate the DataBuffer per-pixel, and then draw the image to whatever destination Graphics context you want. (It will be drawn using the software rasterization routines).

While the drawing of the image will be slower(software vs hardware); the setting of the individual pixels will be much much faster (an array write vs a fillRect).

Well, the drawing is taking up 95% of the CPU at the moment, so would that still be the case? Also, I rigged an equivalent boolean grid to hold which values need to be re-rendered, and that slows down the initial frames from 15 to 8, but once all the pixels have fallen to the bottom, I get the full 60 fps I have set as a limit at the moment.

Okay, I tried making a buffered image and using setRGB to set the pixels, but it appears slick can’t render a buffered image. I tried casting to an image, but it can’t be cast to a slick image, and slick can’t draw awt.image data =/

EDIT: Found a BufferedImageUtil in the javadocs for slick, but it returns a texture and I’m not sure how to render that. Also, even before rendering it, just setting the texture data is slower than drawing all those rectangles and setting the ints.

EDIT2: I got it working at an okay speed for now by rendering 4x4 rectangles instead of 1x1. Here’s the current source code now: http://epitaph64.pastebin.com/f40f56562

I got some help from kappa and others on lwjgl’s irc, and also I added a multi-pass update function to speed things up a bit.

Now http://validopinion.wordpress.com/2009/06/07/improving-the-basic-burning-sand-clone/ it runs rather nicely (150-300 fps) on a 400x300 grid with 2x2 pixels to fill 800x600. I still am going to improve the rendering so that whenever the grid becomes full of sand, it won’t lag as much by combining clumps of pixels into single rectangles or something.