Jump to content
  • Advertisement
Sign in to follow this  
cjsst55

Managed Directx Animation Question

This topic is 4832 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I am attempting to animate 58 images that I have of a hand at different points in motion. My initialization is the following: I load each image into its own container class that holds the loaded image as texture. I then create a sprite that will draw all of the textures. In my OnPaint method I use a for loop to loop through each of the 58 container clases that store the image texture. I draw the texture and then clear the screen. I do this 58 times until all of the images have been drawn. Unfortunately, my code does not work as I had expected because the output looks as though all of the images are occuring at once. I belive my problem is either a result of displaying the images too quickly, or because I am drawing all of the images before I invalidate the current display. Does anyone have any suggestions of how I should go about fixing my problem? Any hints are appreciated. Thanks, Chris Here is the contents of my OnPaint function: protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0); device.BeginScene(); animationSprite.Begin(SpriteFlags.AlphaBlend); foreach(DealerTexture dt in array) { // Pass in sprite to container class dt.Draw(animationSprite); // Clear screen for next animation device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0); } animationSprite.End(); device.EndScene(); device.Present(); this.Invalidate(); }

Share this post


Link to post
Share on other sites
Advertisement
You should call OnPaint once per frame of animation. Try something like this:


DealerTexture current_dt;

override void OnPaint(...)
{
device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);
device.BeginScene();
animationSprite.Begin(SpriteFlags.AlphaBlend);

current_dt.Draw(animationSprite);

device.EndScene();
device.Present();
}

void SomeFunction()
{
foreach (DealerTexture dt in array)
{
current_dt = dt;
Refresh();
Thread.Sleep(100);
}
}

Share this post


Link to post
Share on other sites
cjsst55,

Your issue is, indeed that you are displaying all of the images at the same time, far too quickly. Depending on the refresh rate of your adapter/monitor and the PresentInterval you set on your Device when you created it, you could be displaying all 50-whatever images in 1/60th of a second or so. Far too quickly.

Also, note that Form::Invalidate() is a Win32 GDI/GDI+ call. Sending an invalidation message or invoking Form.Invalidate() simply notifies Windows that a portion of a form has been invalidated, and that it's OnPaint() method needs to be called. DirectX (including Managed DX) does not even use GDI/GDI+, rather, it communicates directly with the hardware. There is no need to call Form::Invalidate() as Device::Present() takes care of all the buffer flipping and display updates for you.

This is not to say that Invalidate() isn't used in DX applications. It generally _is_ used for applications that do not use a render loop, or who's render loop utilizes OnPaint to do the drawing. However, Invalidate() is simply used to trigger the OnPaint(), you rarely if ever call it from inside of OnPaint (even in standard WinForms applications).

Anyways, what you need to do is display one image per x-milliseconds. If you needed to display 58 frames at 27FPS (fairly standard frame rate for video) you would need to present a new image rougly ever 37 milliseconds. There are a number of ways you can accomplish this, including using the Timer class and all kinds of other ways. A simple method, however would be:

--- Form::OnPaint() ---

m_Device.BeginScene();

// Current sprite is m_CurSprite
// Blah blah blah, paint the sprite

m_Device.EndScene();
m_Device.Present();

m_CurSprite++;
if (m_CurSprite >= 58) // You would use a constant or variable here.
m_CurSprite = 0;



--- End of Form::OnPaint() ---


--- Program::Main() ---

MyForm form = new MyForm();
bool running = true;

// Initialize DirectX

while (running) {
form.Invalidate();
Application.DoEvents();
System.Threading.Thread.Sleep(38);
}

// Uninitialize DirectX, free textures, etc.


--- End of Program::Main() ---


And there you have it. That will do the trick.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!