Wednesday, December 8, 2010

Simulating projectile motion with the Animation Manager using C++

In my last post I described the advantages of incorporating animations into Windows applications and gave an overview of the platform support for creating them. In this post I will dive a little deeper into how to achieve some simple animation effects with a native windows application and the Animation Manager.

First, I needed an idea: something that would at least be mildly interesting and would also provide just enough complexity to illustrate some of the animation concepts and how to implement them. I remembered back to the days of the Atari 2600 and one of my favorite games, Human Cannonball. While the sample I ended up creating is far from a full featured game, it does cover what is necessary to simulate a projectile in motion.

First off, here is an outline of how to use the Animation Manager interfaces to accomplish the effect.

  • Create animation variables. These are instances of IUIAnimationVariable and they are used to provide the coordinates of a projectile along a parabolic curve. In this sample, there is one variable for the horizontal position and one for the vertical position.
  • Create the transition objects. There are a handful of predefined transitions that can be created using IUIAnimationTransitionLibrary. For this sample, I use a linear transition from the library for the horizontal coordinates. For the vertical coordinates I create a transition based on custom interpolator that applies deceleration to an initial velocity. The transitions are associated with the animation variables from the previous step.
  • Create the storyboard. The storyboard is composed of the transitions created in the previous step. The transitions are simply added to the storyboard object, which is factoried by the animation manager.
  • Schedule the storyboard. This begins the process of updating the animation variables over a timeline. Once the storyboard is running, the animation variables are used to retrieve the x and y coordinates where the projectile should be rendered.

Sample Design Overview

The sample can be downloaded here.

There are two primary classes implemented in the sample that perform the bulk of the work: CMainWindow and CProjectileAnimation.

Before describing the details of those two objects I?ll provide an overview of the sample?s design philosophy. First, I typically use a factory create pattern. This means that the objects I define generally have a static method to factory instances. In addition, I prefer to encapsulate the public methods of classes in well-defined contracts. For this I rely on IUnknown derived interfaces. The advantages of this approach are that it requires some up-front thinking about what the contractual requirements are between components and also it uses reference counting semantics, making it easy to manage the lifetime of objects (once the patterns are committed to memory). The disadvantage is that it can sometimes make code look a bit more complicated than it needs to, especially to someone unfamiliar with the pattern. Also, it requires some boilerplate style implementation of QI/AddRef/Release.

CMainWindow

CMainWindow is a simple wrapper over a Win32 HWND. It is responsible for creating the device independent and device dependent animation objects. The device independent objects are created during initialization and kept for the lifetime of the application. These include:

  • Animation manger. Factories many of the other animation objects like the storyboard and animation variables.
  • Animation timer. Used to schedule storyboards and update the animation manager.
  • Transition factory. Creates custom transitions.
  • Transition library. Creates standard transitions.
  • D2D factory. Creates various D2D objects, in this case the D2D surface.

In addition to the device independent objects, there are a few device dependent ones managed by CMainWindow. These are created on demand in the render pass (WM_PAINT) and discarded when requested by the animation manager. These include:

  • HWND render target. The D2D surface where the projectiles are drawn.
  • Background brush. A simple gradient brush used to fill the client area.
  • Projectile bitmap. The bitmap that is animated along the parabolic path.

Launching a projectile is accomplished by pressing the spacebar. CMainWindow will launch a projectile along a fixed curve for every press. It maintains an array of active projectiles, which are all updated during the render pass. When a render pass is complete, CMainWindow relies on the animation manager to determine whether another render pass is necessary, and invalidates itself until the animation manager is done with the storyboards for all outstanding projectiles.

CMainWindow also registers itself as an IUIAnimationManagerEventHandler. This allows it to listen for state changes in the animation manager which kick off the invalidation/render cycle.

CProjectileAnimation

CProjectileAnimation is a fairly simple class that encapsulates the logic for creating the storyboard necessary to achieve the projectile effect. For initialization, it requires an IServiceProvider to probe for the various animation services it needs to create the storyboard. Those services are cached by CMainWindow (described above as the device independent objects), which implements IServiceProvider to service those requests.

CProjectileAnimation relies on an implementation of IUIAnimationInterpolator provided by CGravityInterpolator to create the horizontal component of the storyboard. This simple implementation uses a fixed initial velocity and acceleration. The interpolator is used by the animation system to provide incremental values of velocity and position based on time offset from the beginning of the storyboard.

Conclusion

While at first glance it may seem like a lot of work to achieve a fairly trivial animation, I encourage you to download and dissect this sample. I think once you take a look at how I?ve put things together it will be clear that it is really not all that complex, and that there is a lot of functionality and flexibility offered by the Animation Manager.

Katie Holmes Victoria Beckham Missy Peregrym Sarah Gellman Eliza Dushku

No comments:

Post a Comment