smooth animation

I’m having some trouble getting my animation to look as smooth as I want it to using time based animation. I believe this is because of the rounding that takes place before I can draw my sprites. Here is how I’m updating: x += xVelocity*delta; and I’m drawing like this: g2.drawImage(image, Math.round(x), Math.round(y), null); My sprites appear to jiggle while they are moving and I think its pretty ugly. So far the only solution I’ve come up with is to use tick based animation instead.

The peice of code I’m concerned with right now is for a game engine that will be used primarily for applet games. If I’m confident that I can get my game to run at, at least my target framerate and cap it at that, could this be considered a good choice in any way?

Has anyone else encountered this problem or found a solution to it? I know the obvious solution is use openGL :slight_smile: but since this is for applets, I’m not going to do that for several reasons. I think that there must be a solution because I’ve looked at the source for this game: http://www.brackeen.com/javagamebook/tilegame.jnlp and they are updating/drawing just like me but the animation in that game is very smooth, looks just like my tick based animation.

Here is a test applet I put together:
http://www.cyntaks.com/projects/wjge/test.html

and here are a couple executable jars which will run in fullscreen so you can see the animation more clearly:
time based: http://www.cyntaks.com/projects/wjge/test1.jar

tick based:
http://www.cyntaks.com/projects/wjge/test2.jar (random velocities will not work correctly in this version since the game engine is meant to be time based right now)

any advice on what I should do about this would be greatly appreciated.

looks like your timer is bad. Try out the GAGE Timer to figure out how much time has elapsed from the previous frame so you can move that much. I’d also suggest profiling so you can try to improve the FPS. There may be some bottlenecks you can sort out.

Have you tried not rounding, but instead casting your position? I don’t know that it would make a huge difference.

I’d agree with Mal, that your timer could be at issue as well. Java 1.5 will fix this, but then you might lose the whole reason you were doing applets in the first place.

Regards,
Dr. A>

Have you tried not rounding, but instead casting your position?

Rounding yields slightly better results than casting. Just think about it.


Well, you need a proper timer. 1.5 or GAGE.

I’m not convinced that timing is actually the problem because I’ve used gage before and got similar results. Not only that but in the smooth game that I mentioned, only System.currentTimeMillis() is used (he doesn’t even subtract the time elapsed from his sleep time). Dr. anonymous got it right about 1.5 so I won’t be using that, I’m also not going to use the GAGE timer since it would (on windows) require the user to grant permissions.

@Malohkan what were your fps, I get near 200, and I’m sure I could get much more with an accurate timer since its only using a small percentage of cpu.

Someone else told me that they were only getting fps in the 20’s though so I’m wondering if the images aren’t getting accelerated on some machines. He was using an ati card and his computer was not allowing the program to check his display mode so it appears that there are some security restrictions which are not allowing java to access certain funcitons on his system. The odd thing is that this was not true before, but he has installed sp2 since then and our best guess is that it has something to do with that. He now gets this message when trying to run a java fullscreen game: Unexpected Error Could not get display modes.

I will still optimize (when I’m done :slight_smile: ), but I doubt if any of the applets I write will even require as much processing power as that demo; it’s repainting a 640x480 image every frame as well as painting/updating and possibly sorting 200 of those blobs.

edit: forgot to say that my friend is running windows xp with java 1.4.2_05

well if you’re getting that high of an FPS, then the problem is most likely the timer. Give GAGE another shot, it’s how I keep my games smooth :slight_smile:

I would use gage, but I can’t because this is for applets and I don’t want the user to have to grant permission to use my program. I did notice that you don’t have to do this when playing the rimscape applet though (unless I did it before or something), so perhaps I’m wrong and I can use gage?

If I use gage, that will solve the fps problem but the problem with animation will persist. I know this because I was using gage with the engine until just recently. The problem is that the sprites are shaking while they move, this seems obvious to me that it is being caused by rounding off the x,y positions before drawing. I’ll continue to look through david brackeen’s source becuase I don’t think I’ve ever seen a java2D game that runs that smooth.

I tried out the rimscape webstart again (to examine your animation :slight_smile: ) but it was complaining about an old jnlp (which I can’t seem to get rid of), I cleared webstart so that all downloaded apps are gone and I untinstalled rimscape from add/remove programs.

[quote]I would use gage, but I can’t because this is for applets and I don’t want the user to have to grant permission to use my program.
[/quote]
It’s a common misconception that GAGE can’t be used without the DLL. It can, in fact, be used without difficulty. The only thing you need to be aware of is that you’re only getting 100 ticks per second, EXACTLY. Time your framerate accordingly! Good values include 25fps, 50fps, and 100fps. Also, make sure you calculate these framerates. If you assume 100 ticks per second, you’re going to get into trouble if someone uses Java 1.5 (which runs with nanosecond precision).

[quote]If I use gage, that will solve the fps problem but the problem with animation will persist. I know this because I was using gage with the engine until just recently. The problem is that the sprites are shaking while they move, this seems obvious to me that it is being caused by rounding off the x,y positions before drawing. I’ll continue to look through david brackeen’s source becuase I don’t think I’ve ever seen a java2D game that runs that smooth.
[/quote]
That’s because of the way that interpolation works on a 2D screen. Interpolation works well in 3D, because 3D coordinates are virtual. i.e. They don’t correspond to any given element. In 2D, your objects correspond to pixels. The eye is VERY sharp and will notice the “jitter” caused by moving 1 pixel, then 2, then 1 again. The only real solution to this is to do sub-pixel rendering, which is really too slow for a video game.

The next best solution is to work your objects so that their movement coresponds to the framerate. e.g. I have a framerate of 50fps. Thus a character that moves 25 pixels per second will look better than a character that moves 30. In the case of the former, the character will move a smooth one pixel every other frame. In the case of the later, it will move an extra pixel every few frames.

Before I disappear, here’s an explanation I once gave on interpolating movement. I’m not sure if it will help you solve your problem, but it may give you a few ideas:

can’t you get the same result by storing the position as a double, modifying with double accuracy for every change, then casting to int only when you draw?

ah thank you for that jbanes, I now have a much greater understanding of the problem. The one other thing I wonder is how to tell the gage timer not to use the dll, or will it just decide not to if the dll is not found? Your explanation of choosing a framerate that will result in constant movement is likely what I didn’t notice about brackeen’s code that resulted in such smooth animation. I tried using a framerate of 50 per second and moved my blobs at 50 pixels per second, and like magic, it works! This will not always be a good general solution so I’ll have to look into the interpolation which you spoke of.

edit: I spoke too soon, I forgot to change my code back to time based after the demo I made last night, thats why the animation was smooth. I think it should still work, I just need to use gage to get a constant framerate first.

@malohkan thats what I’m doing already (except I use a float), but this is actually the cause of the problem. When you draw the image you have to round, this means that the sprite will generally move +/- one pixel from where you actually want it. If it moves 1 pixel half the time and 2 pixels the other half, this variation causes the jittering effect which I’ve been describing.

[quote]The one other thing I wonder is how to tell the gage timer not to use the dll, or will it just decide not to if the dll is not found?
[/quote]
It’s automagic! :slight_smile: Just ignore the stack trace on startup. It’s completly harmless. I only left it in so that people could debug issues in their code.

Malohkan: If you read my explanation, you’ll notice that my sample code does exactly what you describe. :slight_smile:

I tried doing that but it still popped up a dialog asking whether to grant access or not. So I modified the gage source (WindowsTimer.java) so that the loadLibrary() method just returns false. This worked well and I can now keep my framerate where I want it.

The only way I can get smooth animation is if I use velocities that are factors of the framerate (or the framerate is a factor of it). However, I’ve decided to not be too concerned with the jiggling, but I may change my mind once I’ve actually got a game written with it (I don’t think it will be very noticeable).

I don’t think it will be very noticeable

It’s only noticable at slow speeds. If you use some kind of background it’s also less visible.

I saw brackeen’s code and noticed that he uses floats in his sprites class. Why floats? I use double… I tried to convert his code to double (Chapter 5) but I got stack overflow error… I dunno why! Any tips?