public AnimatableObjectSample(Microsoft.Xna.Framework.Game game) : base(game) { Rectangle bounds = GraphicsService.GraphicsDevice.Viewport.TitleSafeArea; // ----- Create three named AnimatableSprite instances. _animatableSpriteA = new AnimatableSprite("SpriteA", SpriteBatch, Logo) { Position = new Vector2(bounds.Center.X, bounds.Center.Y / 2.0f), Color = Color.Red, }; _animatableSpriteB = new AnimatableSprite("SpriteB", SpriteBatch, Logo) { Position = new Vector2(bounds.Center.X, bounds.Center.Y), Color = Color.Green, }; _animatableSpriteC = new AnimatableSprite("SpriteC", SpriteBatch, Logo) { Position = new Vector2(bounds.Center.X, 3.0f * bounds.Center.Y / 2.0f), Color = Color.Blue, }; // Create a looping color key-frame animation. ColorKeyFrameAnimation colorAnimation = new ColorKeyFrameAnimation { TargetProperty = "Color", EnableInterpolation = true, }; colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(0.0), Color.Red)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(0.5), Color.Orange)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(1.0), Color.Yellow)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(1.5), Color.Green)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(2.0), Color.Blue)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(2.5), Color.Indigo)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(3.0), Color.Violet)); colorAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(3.5), Color.Red)); AnimationClip <Color> loopedColorAnimation = new AnimationClip <Color>(colorAnimation) { TargetObject = "SpriteB", LoopBehavior = LoopBehavior.Cycle, Duration = TimeSpan.MaxValue, }; // Create a oscillating from/to animation for the position. Vector2FromToByAnimation vector2Animation = new Vector2FromToByAnimation { TargetProperty = "Position", From = new Vector2(bounds.Left + 100, _animatableSpriteC.Position.Y), To = new Vector2(bounds.Right - 100, _animatableSpriteC.Position.Y), Duration = TimeSpan.FromSeconds(2), EasingFunction = new HermiteEase { Mode = EasingMode.EaseInOut }, }; AnimationClip <Vector2> oscillatingVector2Animation = new AnimationClip <Vector2>(vector2Animation) { LoopBehavior = LoopBehavior.Oscillate, Duration = TimeSpan.MaxValue, }; // Create a timeline group that contains both animations. TimelineGroup spriteCAnimation = new TimelineGroup { TargetObject = "SpriteC", }; spriteCAnimation.Add(loopedColorAnimation); spriteCAnimation.Add(oscillatingVector2Animation); // Create a timeline group that contains the animations for SpriteB and SpriteC. TimelineGroup allSpriteAnimations = new TimelineGroup(); allSpriteAnimations.Add(loopedColorAnimation); allSpriteAnimations.Add(spriteCAnimation); // There are several ways to apply animations to animatable objects and properties: // // Method 1: Apply to an IAnimatableProperty directly. // We either have direct access to a IAnimatableProperty or we can ask the IAnimatableObject // to give us a named IAnimatableProperty. // For example: // AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteB.GetAnimatableProperty<Color>("Color")); // AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteC.GetAnimatableProperty<Color>("Color")); // AnimationService.StartAnimation(oscillatingLeftRightAnimation, _animatableSpriteC.GetAnimatableProperty<Vector2>("Position")); // In this case, the "TargetObject" and the "TargetProperty" values of the timelines/animations do not matter. // // Method 2: Apply to an IAnimatableObject directly. // For example: // AnimationService.StartAnimation(loopedColorAnimation, _animatableSpriteB); // AnimationService.StartAnimation(spriteCAnimation, _animatableSpriteC); // The animation service checks the TargetProperty value of the animations to see which // IAnimatableProperty of the IAnimatableObjects should be animated by the animation. // The "TargetObject" values of the timelines are ignored. // // Method 3: Apply a timeline to a collection of IAnimatableObjects. // For example: var animationController = AnimationService.StartAnimation(allSpriteAnimations, new[] { _animatableSpriteA, _animatableSpriteB, _animatableSpriteC }); // The "TargetObject" and "TargetProperty" values are used to check which objects and // properties must be animated by which animation. // combinedSpriteAnimation is a "tree" of timelines: // // Type TargetObject TargetProperty // -------------------------------------------------------------------------------------------------- // allSpriteAnimations TimelineGroup - - // loopedColorAnimation AnimationClip<Color> "SpriteB" - // colorAnimation ColorKeyFrameAnimation - "Color" // spriteCAnimation TimelineGroup "SpriteC" - // loopedColorAnimation AnimationClip<Color> "SpriteB" - // colorAnimation ColorKeyFrameAnimation - "Color" // oscillatingVector2Animation AnimationClip<Vector2> - - // vector2Animation FromToByAnimation - "Position" // // No animation specifies "SpriteA" as its TargetObject, therefore no animation // are applied to SpriteA. // // The first loopedColorAnimation is applied to "SpriteB". And the contained // colorAnimation is applied to the Color property of SpriteB. // // The spriteCAnimation is applied to "SpriteC". Therefore, all "children" of // spriteCAnimation are also applied to this object! The TargetObject property of // the second loopedColorAnimation is ignored! The second loopedColorAnimation is // applied to SpriteC! animationController.UpdateAndApply(); }
public BlendedAnimationSample(Microsoft.Xna.Framework.Game game) : base(game) { Rectangle bounds = GraphicsService.GraphicsDevice.Viewport.TitleSafeArea; // Create the animatable object. _animatableSprite = new AnimatableSprite("SpriteA", SpriteBatch, Logo) { Position = new Vector2(bounds.Center.X, bounds.Center.Y / 2.0f), Color = Color.Red, }; Vector2FromToByAnimation slowLeftRightAnimation = new Vector2FromToByAnimation { TargetProperty = "Position", From = new Vector2(bounds.Left + 100, bounds.Top + 200), To = new Vector2(bounds.Right - 100, bounds.Top + 200), Duration = TimeSpan.FromSeconds(4), EasingFunction = new HermiteEase { Mode = EasingMode.EaseInOut }, }; ColorKeyFrameAnimation redGreenAnimation = new ColorKeyFrameAnimation { TargetProperty = "Color", EnableInterpolation = true, }; redGreenAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(0), Color.Red)); redGreenAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(4), Color.Green)); TimelineGroup animationA = new TimelineGroup { slowLeftRightAnimation, redGreenAnimation, }; Vector2FromToByAnimation fastLeftRightAnimation = new Vector2FromToByAnimation { TargetProperty = "Position", From = new Vector2(bounds.Left + 100, bounds.Bottom - 200), To = new Vector2(bounds.Right - 100, bounds.Bottom - 200), Duration = TimeSpan.FromSeconds(1), EasingFunction = new HermiteEase { Mode = EasingMode.EaseInOut }, }; ColorKeyFrameAnimation blackWhiteAnimation = new ColorKeyFrameAnimation { TargetProperty = "Color", EnableInterpolation = true, }; blackWhiteAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(0), Color.Black)); blackWhiteAnimation.KeyFrames.Add(new KeyFrame <Color>(TimeSpan.FromSeconds(1), Color.White)); TimelineGroup animationB = new TimelineGroup { fastLeftRightAnimation, blackWhiteAnimation, }; // Create a BlendGroup that blends animationA and animationB. // The BlendGroup uses the TargetProperty values of the contained animations to // to match the animations that should be blended: // slowLeftRightAnimation with fastLeftRightAnimation // redGreenAnimation with blackWhiteAnimation _blendedAnimation = new BlendGroup { LoopBehavior = LoopBehavior.Oscillate, Duration = TimeSpan.MaxValue, }; _blendedAnimation.Add(animationA, 1); _blendedAnimation.Add(animationB, 0); _blendedAnimation.SynchronizeDurations(); // Start blended animation. AnimationService.StartAnimation(_blendedAnimation, _animatableSprite).UpdateAndApply(); }