Archived

This topic is now archived and is closed to further replies.

FieroAddict

Jerky movement in DDraw, smooth in D3D

Recommended Posts

I''ve been doing some experimenting with the graphics for my Asteroid''s clone I''ve been working on (using .NET and DirectX9). Right now I have three different versions: Direct3D 3D, 2D using Direct3D Sprites, and DirectDraw 2D. My question is this: The source code for the animations and logic for both 2D versions is the same, aside from the D3D or DDraw specific code for displaying images. The problem is that in the DDraw version, when the asteroids are moving at certain angles, it looks like they aren''t moving at a smooth angle, instead you can tell that it''s moving jerkily up and over each frame. In the D3D version, they all look perfectly smooth. I have all animations and movements moving independant of the FPS, but I still wasn''t sure if the problem was that the D3D version can easily pull off over 300fps and the DirectDraw version is locked at 75 fps. I tried to change the flags for Flip() to NoVsync, but the program refuses to run with that setting. Or, could the problem be that in Direct3D, there is just better support for floating point positions than in DirectDraw (singles vs. integers)?

Share this post


Link to post
Share on other sites
Make sure that YOU are storing the positions as floating points. 75fps is plenty fast enough for smooth motion. When you blit the image to a surface in DirectDraw, it WILL round off to integers, but as long as you maintain the position internally as a floating point, all will be fine.

This seems to be a very common issue with time scaling. [To everyone:] IF YOU USE TIME SCALAING, USE ONLY FLOATING POINT GENERALIZED CO-ORDINATES. That includes positions, angles, frames, the whole nine... anything time scalled. Roundoff will kill you otherwise.

Share this post


Link to post
Share on other sites
Yes, everything is floating point numbers (except for the fact that DDraw only works with integer values in it Draw() functions). But all of my calculations are made with floating point numbers.

I know 75fps is plenty fast for good animation, but what I was wondering is, does DirectDraw actually pause the program while it waits to draw to the screen, or does your program continue to run and DirectDraw draws the screen in the background? This could explain the jerkiness... that it''s not being drawn in sync with the speed of my movement calculations?

Share this post


Link to post
Share on other sites
In my experience, by having VSYNC turned on, your "Flip" call will return right away but the first time you try and blit to a surface, it will wait for the flip to complete (unless you say NOWAIT in which case it will throw an error).

WHERE the pause occurs should not affect the smoothness, as long as it occurs at the same place each time through, which it will. I''d seriously check over the rest of the code and run a pile of tests before thinking the VSYNC is to blame for this... I''m just skeptical, as I''ve had it work perfectly in a number of other circumstances.

Share this post


Link to post
Share on other sites

  
Private sprites As Surface
Private frame() As Rectangle
Private destRect As Rectangle

Structure Vector
Dim X As Double
Dim Y As Double
End Structure

Private position As Vector
Private velocity As Vector

Public Sub Draw(ByRef backbuffer As Microsoft.DirectX.DirectDraw.Surface)
destRect = New Rectangle(position.X, position.Y, frame(currentFrame).Width, frame(currentFrame).Height)
backbuffer.Draw(destRect, sprites, frame(currentFrame), DrawFlags.DoNotWait Or DrawFlags.KeySource)
End Sub

Public Sub Update(ByVal seconds As Double)
position.X += velocity.X * seconds
position.Y += velocity.Y * seconds
If velocity.X > 0.0 And position.X >= 800.0 Then
''if moving right and moved beyond screen
position.X = -64.0
End If
If velocity.X < 0.0 And position.X <= -64.0 Then
''if moving left and moved beyond screen
position.X = 800.0
End If
If velocity.Y > 0.0 And position.Y >= 600.0 Then
''if moving down and moved beyond screen
position.Y = -64.0
End If
If velocity.Y < 0.0 And position.Y <= -64.0 Then
''if moving up and moved beyond screen
position.Y = 600.0
End If
End Sub


That''s the draw() and update() routines for my "asteroid". I have the exact same code in the Direct3D version using the Sprite class and textures instead of DirectDraw surfaces and the movement is always very smooth, just the DirectDraw version has a slighy noticable jerk to it''s movements at certain angles. I was attributing it to the Sprite''s draw function supporting Single variable types as opposed to DirectDraw''s integer format. I''m just going to go with D3D because that''s what''s working... but I''m curious as to how it could be done in DirectDraw.

Share this post


Link to post
Share on other sites
If you have the time, you can download the file (it's like 300k) and checkout the problem I'm refering to. This is the DirectDraw version.

At the menu, the only keys that do anything are 'S' and 'Q'. In the "game" you can hit 'Esc' to return to the menu. (I was just testing out the game framework.) You can't actually do anything in this version. But you'll notice that when the asteroids are at certain angles, they appear jumpy. I don't think it has anything to do with VB.NET. I'd like to see it run faster than my monitor refresh to see if that's causing a problem, but I can't get it to ignore the V-Sync. Maybe I'll have to try rewriting it in windowed mode as a test.


Btw, the .exe would require the .NET framework and DirectX 9.

[edited by - FieroAddict on May 8, 2003 1:19:21 PM]

Share this post


Link to post
Share on other sites
Looks like integer precision to me. At shallow angles you see the jump from one coordinate to the next.

Edit:
There's nothing you can do about this in DirectDraw. It doesn't matter if you maintain the coordinates in floating point or not. The precision is lost as soon as the coordinates hit the API.

[edited by - Donavon Keithley on May 8, 2003 2:03:56 PM]

Share this post


Link to post
Share on other sites
I agree it''s the integer precision. But, even in D3D, technically aren''t all pixels integers? You can''t have a fraction of a pixel can you? Seems I''ve played plenty of smooth games that were done in DirectDraw.

Share this post


Link to post
Share on other sites
But vertices are not integral. With non-point filtering, the appearance of a sprite-like object will look different at (0,0) versus (0.25, 0) versus (0.5, 0), etc.

Asteroids is really a worst case scenario in this respect, because you have slow moving, non-animating objects that might jump a pixel as infrequently as every second and they''re drawn against a black background which makes it even easier to see the effect. If you had rotating asteroids you probably wouldn''t notice this.

Share this post


Link to post
Share on other sites
I dunno, I''m a little skeptical about the integer precision thing, as I''ve never seen that effect purely due to that before... and it still *should* happen in D3D, even if that is the problem, since I don''t think it does anything more to blend edges to smooth out the motion... especially not on sprites.

Can''t be sure though, as I refuse to get the .NET Framework, which I''d need to test it

Even if that is the problem though, you could partially "solve" it by going to a higher resolution... what are you currently using?

Share this post


Link to post
Share on other sites
> I dunno, I''m a little skeptical about the integer precision thing, as I''ve never seen that effect purely due to that before.

As I said, Asteroids with non-rotating rocks is just about the worst-case scenario I can imagine for this. In most other cases that I can think of, integer precision would not be nearly as noticeable, it would be hidden in the noise.

> and it still *should* happen in D3D, even if that is the problem, since I don''t think it does anything more to blend edges to smooth out the motion

I can''t parse this fully, but it certainly should not happen in D3D. Move a sprite 1/10th of a pixel and it *will* look different, I promise you -- as long as you''re not using point sampling. In DirectDraw it has to cross the pixel quantum before there''s a change in appearance.

Now if were untextured or if in some other way you could see the edges, that would be a different story. You would need another form of antialiasing like supersampling or multisampling.

Share this post


Link to post
Share on other sites
Hmm... ok well I wasn''t aware that D3D actually did dynamic colour interpolation and blending for quads that fall in between pixel boundaries... news to me!

Share this post


Link to post
Share on other sites