Tricks to get smooth animation

What affects the smoothness off animation:
-Frames per second
-The amount of images used and memory available
-The quality of rendered images(if cartoonlike animation)

My problem is that no matter what, my animation is never good enough for me. For examle, let’s take Scott’s scrollerexample, which is quite excellent work. I never noticed any animation flaws or anything, but with my own code I’m overly critical.

My scroller has minor slowdowns and although I have pretty high end system, the methods that I use are not the most efficient. Now I have spent 5 hours, just trying to find out what makes my engine slow down randomly.

I know there isn’t any cut and paste sollution for this and I’m not trying to find one, but please.

In theory, what makes smooth animation? Should the rendering be priority and then all the other actions after the loop thread. If so how is it possible to concentrate all your input/output/interaction behind the rendering?

One big thing I’m sure you are already aware of is garbage collection. You want to avoid creating objects and allowing objects to get collected during animation in your code. This is especially true for things like full screen scrolling because the entire screen is changing it is much easier to notice the pauses.

  1. Thou shalt not create objects during the rendering loop.
  2. Thou shalt have but one Thread, that that Thread shall do all things.
  3. Thou shalt use a hires timer or be at the Mercy of Satan and all his hacks

Any more commandments?

Cas :slight_smile:

  1. Thou shalt be deeply cautious with string manipulation.
  2. Thou shalt be sparse with collections that create iterators every time.
  3. Thou shalt avoid BufferedImage.getSubimage() like the plauge.

This depends a lot on the type of animations you’re doing. For example:

  1. If you’re not scrolling the screen, then it’s likely that not ALL of your screen is changing each frame. In PacMan, for example, only Pac and the Ghosts and maybe a pill or two change each frame - large portions of the screen (though WHICH large portions varies) remain the same.

Therefore, you can do quite a bit with ‘dirty rectangles’ and ‘setClip’, updating only those parts of the screen which absolutely need it.

  1. Using Java’s built-in ‘sleep’ or ‘wait’ is never going to be as good as the ‘hires Timer hack’ on the ‘Shared Code’ section of these boards, which in turn is never going to be as good as a native hi-res timer. Being able to reliably space your frames ‘exactly’ the same amount of time apart increases the smoothness of your animation a great deal.

  2. The quality of your graphics is unlikely to affect their speed unless you’re rendering them each frame, in which case…

  3. …cache as many things as you can within temporary Images, ready to be quickly 'drawImage’d to the screen. Expire your caches when images in them aren’t used (to save memory)

  4. Use double buffering, or triple buffering if your frame rendering time can get quite high…

  5. …and use VolatileImages (hardware accelerated) to reduce frame rendering time

Just my two cents :slight_smile:

[quote]2. Thou shalt have but one Thread, that that Thread shall do all things.
[/quote]
—Java newbie; beware—
2-> I’m doing an applet, and the start() function is launching two threads: the hi-res timer, and the main “events(); repaint();” loop. Is that a sin, God?

Cédric

That would be an ecuminical matter.

Cas ;D

Actually, in the Pacman example, I found that redrawing the screen was necessary. setClip() and dirty rectangles breaks a more important commandment; creating objects. setClip() creates a new rectangle object every time you call it and causes the code to slow down.

To avoid recreating images as much as I could, I used a couple layers:

  • The maze (never changes)

  • The pills (same size as the maze, like an overlay. Obviously, this one changes when you eat a pill)

  • The sprites (Don’t change, but they move)

    Of course, the possibility exists that I could’ve used setClip() wrong and maybe there’s better performance to be had, but with what I’ve done, it didn’t turn out well and I discovered the Rectangles being created in a profiler.

Michael Bishop

Michael,

I too found, when I originally profiled my application, that creating Rectangles (specifically, calling Area.addOp) is pretty costly - I mentioned that a little while ago on this board.

I found since then, however (with a bit of digging) that you can easily just…

a) Create a GeneralPath object OUTSIDE the main loop
b) Reset it on every iteration (no Object creation)
c) Manually called ‘lineTo’, ‘lineTo’, ‘lineTo’, ‘closePath’ to add each rectangle to the GeneralPath
d) Check other affected actors with GeneralPath.intersects(x,y,w,h) - and remember to blit them, but don’t increase the clipping rectangle for them
d) Call setClip on the finished GeneralPath
e) Blit away!

I think this is pretty optimal ‘dirty rectangle’ code (you don’t create any objects), works well with VolatileImages, and is certainly a significant speed increase in my app.

Richard.