Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (527)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (594)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  smooth animation  (Read 2057 times)
0 Members and 1 Guest are viewing this topic.
Offline weston

Junior Devvie





« Posted 2004-11-15 07:12:29 »

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 Smiley 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.

for(int i = 1; i > 0; i++)
{
System.out.println(i+" cups of java downed");
}
Offline Malohkan

Senior Devvie




while (true) System.out.println("WOO!!!!");


« Reply #1 - Posted 2004-11-15 11:17:49 »

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.

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline dranonymous

Junior Devvie




Hoping to become a Java Titan someday!


« Reply #2 - Posted 2004-11-15 12:44:39 »

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>
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #3 - Posted 2004-11-15 12:55:36 »

> 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.

弾幕 ☆ @mahonnaiseblog
Offline weston

Junior Devvie





« Reply #4 - Posted 2004-11-15 16:07:29 »

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 Smiley ), 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

for(int i = 1; i > 0; i++)
{
System.out.println(i+" cups of java downed");
}
Offline Malohkan

Senior Devvie




while (true) System.out.println("WOO!!!!");


« Reply #5 - Posted 2004-11-15 17:16:10 »

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 Smiley

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline weston

Junior Devvie





« Reply #6 - Posted 2004-11-15 20:23:13 »

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 Smiley ) 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.

for(int i = 1; i > 0; i++)
{
System.out.println(i+" cups of java downed");
}
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #7 - Posted 2004-11-15 22:13:25 »

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.


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.


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:

Quote

As to decoupling from the frame-rate, it's very easy to do. All you
need is a good timer (GAGETimer would probably meet your needs) and a
few calculations to "map" movement to the frame rate. The core idea is
that the characters will work inside their own timeframe. For example,
let's say I have a character who moves 100 pixels every second. We can
then use that number in each loop to interpolate the amount to move:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
int movepixels = 100;

double actualpixels;

while(true)
{
 //Do Stuff

 actual += (timer.getClockTicks()-lasttime)/timer.getTicksPerSecond() * movepixels;
 lasttime = timer.getClockTicks();

 character.x += (int)actual;
 actual -= Math.floor(actual);
}

What the above code does is that it defines how many pixels a
character moves per second. An "actual" variable is then set up to
keep track of the interpolation. You'll note that the "actual"
variable is a double. This is so we can keep track of "partial pixels"
so that the animation doesn't look jerky due to rounding errors.

From there, we calculate the number of pixels to move since the last
frame, update the lasttime variable, add the integral part of the
number to the character's position, then subtract the integral portion
of the number from the "actual" number.

At 60 frames per second, the above should produce about 1.6 pixels of
movement per frame. Given the rounding involved, this means that the
character will tend to move 1 pixel, then 2 pixels, then 1 pixel, then
2 pixels, etc. Here's what the "actual" variable will calculate to
each time:

actual = 1.6 (remainder .6)
actual = 2.2 (remainder .2)
actual = 1.8 (remainder .Cool
actual = 2.4 (remainder .4)
actual = 2.0 (remainder .0)
actual = 1.6 (remainder .6)

The exact formula that was used for interpolation is:

Let s = ticks per second
Let t = ticks since last movement
Let m = pixels to move per second
Let x = interpolated number of pixels to move

We then solve for 'x' as:

x = t/s * m

The only thing that I haven't covered here is moving in a diagonal
fashion. That's really not that difficult as you can use the
"distances" calculated with this formula in a line drawing formula
like Bresenham.


Java Game Console Project
Last Journal Entry: 12/17/04
Offline Malohkan

Senior Devvie




while (true) System.out.println("WOO!!!!");


« Reply #8 - Posted 2004-11-16 02:39:20 »

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?

Admin and Game Developer at
GameLizard.com
Play Rimscape!    |    Play Conquer!
Offline weston

Junior Devvie





« Reply #9 - Posted 2004-11-16 02:43:29 »

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.

for(int i = 1; i > 0; i++)
{
System.out.println(i+" cups of java downed");
}
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline weston

Junior Devvie





« Reply #10 - Posted 2004-11-16 03:15:39 »

@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.

for(int i = 1; i > 0; i++)
{
System.out.println(i+" cups of java downed");
}
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #11 - Posted 2004-11-16 03:50:01 »

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?

It's automagic! Smiley 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.  Smiley

Java Game Console Project
Last Journal Entry: 12/17/04
Offline weston

Junior Devvie





« Reply #12 - Posted 2004-11-16 05:03:54 »

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).

for(int i = 1; i > 0; i++)
{
System.out.println(i+" cups of java downed");
}
Offline oNyx

JGO Coder


Medals: 2


pixels! :x


« Reply #13 - Posted 2004-11-16 05:30:54 »

>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.

弾幕 ☆ @mahonnaiseblog
Offline luisoft

JGO Coder


Projects: 6


Java games rock!


« Reply #14 - Posted 2004-11-27 22:13:22 »

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?
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

PocketCrafter7 (14 views)
2014-11-28 16:25:35

PocketCrafter7 (9 views)
2014-11-28 16:25:09

PocketCrafter7 (10 views)
2014-11-28 16:24:29

toopeicgaming1999 (76 views)
2014-11-26 15:22:04

toopeicgaming1999 (67 views)
2014-11-26 15:20:36

toopeicgaming1999 (16 views)
2014-11-26 15:20:08

SHC (30 views)
2014-11-25 12:00:59

SHC (28 views)
2014-11-25 11:53:45

Norakomi (32 views)
2014-11-25 11:26:43

Gibbo3771 (28 views)
2014-11-24 19:59:16
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!