Archive

Posts Tagged ‘Animation’

Avatar Mosaic -Experimenting with the Artefact Animator

April 21, 2010 6 comments

Avatar Mosaic Screenshot

After finding out about the Artefact Animator,  written by Jesse Graupmann, I knew I wanted to try it out.

The Artefact Animator library is based on the same concept as Tweener for Flash, which provides an easy way to do procedural animations in WPF and Silverlight.

I found some time last night to put together this little Xbox Live avatar mosaic and was very pleased with the results.

Test the Avatar Mosaic Prototype

Download the Source

If you take a look at the prototype, you can see there’s a few things you can do:

  • Drag the grid splitter, resize the window or change the padding slider to cause the tiles to reposition.
  • Type a new Xbox Live Gamertag in the textbox and TAB out to cause the tiles to fade out and fade back in with a new image
  • Roll over a tile and it will scale down until you roll off of it

You can download the source to see the full code but I’ll just highlight the areas where the Artefact Animator is used below.

Download the Library

The first thing you need to do is download a copy of the library from the codeplex site. Jesse has also posted documentation which will help you understand how to use the library. Once you have the library downloaded make sure to add a reference to your project.

Position the Avatar Tiles

When the application loads, AvatarTile controls are dynamically added to the main Canvas called LayoutRoot. Once the SizeChanged event of the Canvas is fired the updateTileLayout method is called.  Calling the method at this point ensures the ActualWidth property of the Canvas is available and the tile layout will be repositioned if the browser window is resized or the grid splitter is moved.

Then we loop through the children of the Canvas and based on the index of the tile an easing function is added using the code below:

ArtefactAnimator.AddEase(element, AnimationTypes.X, curX, time, ease, delay);
ArtefactAnimator.AddEase(element, AnimationTypes.Y, curY, time, ease, delay);

The element parameter defines which AvatarTile to animate.

AnimationTypes is an enum tied to different properties you can choose to animate.

The curX and curY parameters define the new value of the animated property.

The time parameter defines how long the animation should take to get to the new value.

The delay parameter defines how long before the animation should begin.

The ease parameter is a PercentHandler class instance used to define the type of easing function.  The full list of Ease Functions is posted, along with how to create custom ease functions.

When determining the curX and curY values in the updateTileLayout method, padding is also taken into consideration.  The slider sets the padding based on its position.  After the slider is moved, the updateTileLayout method is called to reflect the change in padding.

Fade Out, New Image, Fade In

After a new value is entered into the textbox and the LostFocus event is fired, the AvatarTiles are faded out to reset the brush. This was a test of the available Events of the EaseObject.

//fade out each tile incrementally
for (int i = 0; i < tileCount; i++)
{
   easeObject = ArtefactAnimator.AddEase(element, AnimationTypes.AutoAlpha, 0,
                                            time, ease, delay); 
   delay += .05;
}

//capture completed event of last "fade out" easing
easeObject.Complete += new EaseObjectHandler(easeObject_Complete);

After looping through the children and animating the Opacity of each element, a reference to the return value of the AddEase method is stored. This way we can add an event handler to the Completed event of the EaseObject instance. The event handler will then reset the image brush and animate the tiles back into view using the code below:

//set brush to new image based on textbox
ImageBrush ib = Application.Current.Resources["xboxTileBrush"] as ImageBrush;
ib.ImageSource = new BitmapImage(new Uri(string.Format("http://avatar.xboxlive.com/avatar/{0}/avatarpic-l.png", gamerTagTextBox.Text)));

//fade in each tile incrementally
for (int i = 0; i < tileCount; i++)
{
    ArtefactAnimator.AddEase(element, AnimationTypes.AutoAlpha, 1,
                                time, ease, delay);
    delay += .05;
}

Avatar Mosaic Screenshot

Mouse over action for the Tiles

And finally, taking advantage of some of the Shortcut functions built in, we’ll scale the AvatarTile based on the mouse over events.  In the AvatarTile class, the first step is to use the handy NormalizeTransformGroup method which ensures the needed Transform objects are in place.

Once the library is upgraded to Silverlight 4, this step could become obsolete by leveraging the new CompositeTransform class.

In the Loaded event:

LayoutRoot.NormalizeTransformGroup();
LayoutRoot.RenderTransformOrigin = new Point(.5, .5);

Then on Mouse Enter:

LayoutRoot.ScaleTo(.5, .5, .8, AnimationTransitions.ElasticEaseOut, 0);

And to remove the effect on Mouse Leave:

LayoutRoot.ScaleTo(1, 1, .8, AnimationTransitions.ElasticEaseIn, 0);

And that’s it! Everything is hooked up and ready to run.

Final Thoughts

I really like the direction Jesse is headed with the library by making procedural animations easier to write in Silverlight and WPF.  He’s mentioned the library is in its early stages and would love to see more people use it and provide feedback.

One of the things I found is that after changing the gamertag and fading out the tiles, the repositioning animations got very slow.  I’m not sure if that’s colliding easing objects or what, but there’s some performance work that could be done there.

The other issue is that due to the nature of procedural animations there is no design-time experience.  The best thing about Storyboards is that you can create them visually in Blend and preview them without having to run the application.  It’d be interesting to see if there was some way to tackle this problem. Not sure what to suggest yet.

Test the Avatar Mosaic Prototype

Download the Source

What do you think? Give the Artefact Animator a try and send your feedback to Jesse.

Big update for the Project Rosetta site today

March 3, 2010 3 comments

We just shipped a major update to the Project Rosetta site, including a new a series of Flash to Silverlight tutorials, an updated API Guide with a quick reference list and a full list of recommended tools, code samples and frameworks to download.

Getting Started Series: Project Rosetta site update

API Guide:

And this is just the beginning – you can look forward to new tutorials in the Getting Started series, along with new series of tutorials that go deeper into a single topic.

To keep track of the latest Project Rosetta content and other similar tutorials Follow us on Twitter or get updates via our RSS Feed.

BugCamSmash Dissected part 2 – Make the Bugs Crawl

December 5, 2009 9 comments

In part 1 of this series, explaining how BugCamSmash we walked through the creating the bug sprite, placing the bug at a random position on the screen and triggering a Smash animation when a rock sprite collides with the bug sprite.

In this part we will cover creating the Walk animation, rotating the bug towards and walking to a point clicked with the mouse.

Creating the Walk Animation

Blend makes creating new Storyboards for animations very simple, in the Objects Panel click the “+” button, provide a name and you’re in record mode. Creating a walk cycle for a six-legged creature is not so easy. Not until the final step of this project did I go back and refine the Walk animation. If you download the source for this part you will see seem awkward six-legged limp action.

Regardless, I have a few tips on creating this type of animation:

  • When dealing with short keyframe increments, use the Timeline Zoom (small slider below the storyboard editor) to make frame selection easier.
  • Adjust the Center Point of the Transform to make rotations act more like joints rather than rotating from the default center.
  • Hold the Ctrl key down while click and dragging a selection box to select multiple keyframes at a once.
  • Edit with AutoReverse off, this way the when adding new keyframes the position will be held from the last keyframe rather than the first.

Moving the Bug towards the Destination

To make the leg-flopping animation worth it we need to move the bug across the screen to the point that the mouse is clicked. The following code was added to the Bug class providing a public method MoveTo to pass the mouse click point to the bug sprite and a new Storyboard moveTimer was added to ease the bug towards that new point.

Since this is a lengthy bit of code, I’ve added comments inline to explain what is going on.

public void MoveTo(Point pt)
{
   //save the destination location
   destX = pt.X;
   destY = pt.Y;
   //lower the acceleration because the bug is heading to a new location
   curAcceleration = acceleration; 
   //start the moveTimer and walk cycle animation
   moveTimer.Begin();
   Walk1.Begin();
}

//this fires every 17 milliseconds
void moveTimer_Completed(object sender, EventArgs e)

   //get the current position of the bug
   curX = Canvas.GetLeft(this);
   curY = Canvas.GetTop(this);

   //check if the bug needs to move
   if (curX != destX && curX != destY)
   {
      //determine the distance to the destination
      deltaX = curX – destX;
      deltaY = curY – destY; 
      dist = Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY));

      //if the bug is close enough, snap to the destination
      if (speed >= dist)
      {
         curAcceleration = acceleration;
         Canvas.SetLeft(this, destX);
         Canvas.SetTop(this, destY);
         Walk1.Pause();
      }
      else
      {
         //ease the bug closer to its destination using walking speed and acceleration
         curX -= speed * (deltaX / dist) * curAcceleration;
         curY -= speed * (deltaY / dist) * curAcceleration;
         Canvas.SetLeft(this, curX);
         Canvas.SetTop(this, curY);

         //increase acceleration
         if (curAcceleration < 1)
            curAcceleration += acceleration;

         //begin the timer again to move closer to destination over time
         moveTimer.Begin();
      }
   }
}

 

Rotating the Bug towards the Destination

With the movement in place, rotating towards the point was simple. The current bit of code was added right before the “//ease the bug closer to its destination…” code in the moveTimer_Completed method.

The Atan2 function is used to determine the angle using the delta Point and an angle offset.  The offset of 90 degrees was used due to the original orientation of the bug artwork.

void moveTimer_Completed(object sender, EventArgs e)
{
   […]
   if (speed >= dist)
   {
      […]
   }
   else
   {
      //rotate towards destination
      destAngle = (Math.Atan2(-deltaY, -deltaX) * radiansFactor / Math.PI) + angleOffset;
      curAngle = rotation.Angle;
      curAngle += (destAngle – curAngle) * curAcceleration;
      rotation.Angle = curAngle;
      […]
   }
}

 

Now the bug will crawl and rotate towards the point clicked with the mouse and still smashable with the rock from part 1.

The next part will cover empowering the bugs to choose their own destination