I am trying to make one-hand machine game. To animate falling down Images I am using storyboard. My question is if someone know how to make multiple images. In this code I have just on image falling down. Somone know how to make e.g 100 images animation in the storyboard?
private Storyboard CreateStoryBoard()
{
Storyboard sb = new Storyboard();
DoubleAnimation firstAnimation = new DoubleAnimation();
firstAnimation.SpeedRatio = 8;
firstAnimation.From = 0;
firstAnimation.To = 600;
firstAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
Storyboard.SetTarget(firstAnimation, Okejka);
Storyboard.SetTargetProperty(firstAnimation, new PropertyPath("(Canvas.Top)"));
sb.Children.Add(firstAnimation);
return sb;
}
private void SpinButton_Click(object sender, RoutedEventArgs e)
{
Storyboard sb = CreateStoryBoard();
sb.Begin();
}
For each object you need create DoubleAnimation, each DoubleAnimation add to one Storyboard and then play it.
This is one method of my AnimationHelper, I modified it for this case.
public static void Animate(List<DependencyObject> objects, EventHandler onComplete = null)
{
Storyboard sb = new Storyboard();
foreach (DependencyObject obj in objects)
{
DoubleAnimation da = new DoubleAnimation();
da.From = FromValue; // Set you From value
da.To = ToValue; // Set your To value
da.Duration = new Duration(TimeSpan.FromSeconds(2)); // Set your Duration
// a.EasingFunction = anim.Func; Easing function
// da.BeginTime = anim.BeginTime; Begin time for each DA
Storyboard.SetTarget(da, obj);
Storyboard.SetTargetProperty(da, new PropertyPath(/* this your Property path */));
sb.Children.Add(da);
}
if (onComplete != null)
sb.Completed += onComplete;
sb.Begin();
}
UPDATE #1 The next code is Button.Click event handler, this code creates 20 Images and adds it to Canvas, next step is create animations for each Image using one instance of Storyboard.
private async void b1_Click(object sender, RoutedEventArgs e)
{
CanvasContainer.Children.Clear();
_images = new List<Image>();
// load bitmap
BitmapImage bmp = new BitmapImage(new Uri("Assets/appbar/appbar.italic.png", UriKind.Relative));
// create 20 Image instance
for (int i = 0; i < 20; i++)
{
Image img = new Image();
img.Source = bmp;
img.Stretch = Stretch.Fill;
img.Width = 20;
img.Height = 20;
_images.Add(img);
Canvas.SetTop(img, 0);
Canvas.SetLeft(img, i * 20 + 5);
CanvasContainer.Children.Add(img);
}
// Simulate some delay or any task (3 sec)
await Task.Delay(3000);
Storyboard sb = new Storyboard();
// delay animation time for each object
TimeSpan beginTime = TimeSpan.FromMilliseconds(0);
foreach (Image img in _images)
{
DoubleAnimation da = new DoubleAnimation();
da.From = 0; // Set start value to 0 px
da.To = 700; // Set end value to 700 px
da.Duration = new Duration(TimeSpan.FromSeconds(2)); // Set animation time to 2 sec
da.BeginTime = beginTime; // Set delay for each Image
beginTime += TimeSpan.FromMilliseconds(100);
Storyboard.SetTarget(da, img);
Storyboard.SetTargetProperty(da, new PropertyPath("(Canvas.Top)"));
sb.Children.Add(da);
}
sb.Begin();
}
Code result:
Related
I have a simple map and a square that I would like to move from point A to D, through B and C. I've declared a method Animate:
public void Animate(double[] FirstPoint, double[] SecondPoint, Image img)
{
double x1 = FirstPoint[0];
double x2 = SecondPoint[0];
double y1 = FirstPoint[1];
double y2 = SecondPoint[1];
TranslateTransform trans = new TranslateTransform();
img.RenderTransform = trans;
DoubleAnimation anim1 = new DoubleAnimation(y1, y2, TimeSpan.FromSeconds(1));
DoubleAnimation anim2 = new DoubleAnimation(x1, x2, TimeSpan.FromSeconds(1));
trans.BeginAnimation(TranslateTransform.YProperty, anim1);
trans.BeginAnimation(TranslateTransform.XProperty, anim2);
}
The main problem is that when I use those method like this:
obj.Animate(obj.A, obj.B, Car);
obj.Animate(obj.B, obj.C, Car);
obj.Animate(obj.C, obj.D, Car);
...there's animation shown only from point C to D. When I added a MessageBox.Show to Animate method, it displayed the animation properly.
I feel that I might not fully understand the concept behind using those classes to animate objects. Any thoughts?
You can use this code as the sample for understanding, how to work with multiple animations.
This is full code for MainWindow.xaml.cs.
public partial class MainWindow : Window
{
private const string CarTransform = "CarTransform";
private Image _car;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Loaded -= MainWindow_Loaded;
// create and add Car image to LayoutRoot grid
_car = new Image();
_car.Source = new BitmapImage(new Uri("/car-icon-hi.png", UriKind.Relative));
_car.Width = 64;
_car.Height = 64;
_car.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
_car.VerticalAlignment = System.Windows.VerticalAlignment.Top;
_car.Margin = new Thickness(5);
_car.RenderTransform = new TranslateTransform();
LayoutRoot.Children.Add(_car);
}
private DoubleAnimation CreateAnimationFor(double from, double to, TimeSpan? beginTime, string targetName, DependencyProperty propertyPath)
{
DoubleAnimation da = new DoubleAnimation();
da.From = from;
da.To = to;
da.Duration = new Duration(TimeSpan.FromMilliseconds(1000));
if (beginTime != null)
da.BeginTime = beginTime;
Storyboard.SetTargetName(da, targetName);
Storyboard.SetTargetProperty(da, new PropertyPath(propertyPath));
return da;
}
private void StartAnimationClick(object sender, RoutedEventArgs e)
{
TranslateTransform _trans = _car.RenderTransform as TranslateTransform;
this.RegisterName(CarTransform, _trans); // register name for TranslateTransform instance, this action is needed for working a Storyboard with multiple animations
Storyboard sb = new Storyboard();
// from A to B
sb.Children.Add(CreateAnimationFor(0, 100, null, CarTransform, TranslateTransform.XProperty));
sb.Children.Add(CreateAnimationFor(0, 0, null, CarTransform, TranslateTransform.YProperty));
// from B to C
sb.Children.Add(CreateAnimationFor(100, 100, TimeSpan.FromSeconds(1), CarTransform, TranslateTransform.XProperty));
sb.Children.Add(CreateAnimationFor(0, 100, TimeSpan.FromSeconds(1), CarTransform, TranslateTransform.YProperty));
// from C to D
sb.Children.Add(CreateAnimationFor(100, 300, TimeSpan.FromSeconds(2), CarTransform, TranslateTransform.XProperty));
sb.Children.Add(CreateAnimationFor(100, 250, TimeSpan.FromSeconds(2), CarTransform, TranslateTransform.YProperty));
sb.Begin(this);
}
}
Result of this code:
I am trying to make an image slide diagonally in windows phone 8 C#, i have tried some code, and gotten rid of an error i created - but when i doubletap the canvas, it is supposed to trigger the event, but nothing happens. Please take a look at my code:
private void Canvas_DoubleTap(object sender, System.Windows.Input.GestureEventArgs e)
{
//The canvas was doubletapped
//Create DoubleAnimation for x value
DoubleAnimation movedefenderxpositionAnimation = new DoubleAnimation();
movedefenderxpositionAnimation.From = 0;
movedefenderxpositionAnimation.To = 30;
movedefenderxpositionAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
movedefenderxpositionAnimation.AutoReverse = false;
//Create DoubleAnimation for y value
DoubleAnimation movedefenderypositionAnimation = new DoubleAnimation();
movedefenderypositionAnimation.From = 0;
movedefenderypositionAnimation.To = 15;
movedefenderypositionAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
movedefenderypositionAnimation.AutoReverse = false;
//Create StoryBoard
Storyboard movedefenderxpositionSB = new Storyboard();
movedefenderxpositionSB.Children.Add(movedefenderxpositionAnimation);
Storyboard movedefenderypositionSB = new Storyboard();
movedefenderypositionSB.Children.Add(movedefenderypositionAnimation);
//Set the timespan
movedefenderxpositionSB.Duration = new Duration(TimeSpan.FromSeconds(1));
movedefenderypositionSB.Duration = new Duration(TimeSpan.FromSeconds(1));
//Set the target
Storyboard.SetTarget(movedefenderxpositionAnimation, squaddefender1);
Storyboard.SetTarget(movedefenderypositionAnimation, squaddefender1);
//Set the target property
Storyboard.SetTargetProperty(movedefenderxpositionAnimation, new PropertyPath("(Canvas.Left)"));
Storyboard.SetTargetProperty(movedefenderypositionAnimation, new PropertyPath("(Canvas.Top)"));
//Start the animation
movedefenderxpositionSB.Begin();
movedefenderypositionSB.Begin();
}
And also, something i dont understand. How can i set the target property of the StoryBoard, and not the one i created, two times? I added this piece of code to iron out an error, which created a new one
I am trying to create a simple animation using code. I copy pasted the same code of the msdn which is the following:
public MainPage()
{
InitializeComponent();
Rectangle myRectangle = new Rectangle();
myRectangle.Width = 200;
myRectangle.Height = 200;
Color myColor = Color.FromArgb(255, 255, 0, 0);
SolidColorBrush myBrush = new SolidColorBrush();
myBrush.Color = myColor;
myRectangle.Fill = myBrush;
// Add the rectangle to the tree.
LayoutRoot.Children.Add(myRectangle);
// Create a duration of 2 seconds.
Duration duration = new Duration(TimeSpan.FromSeconds(2));
// Create two DoubleAnimations and set their properties.
DoubleAnimation myDoubleAnimation1 = new DoubleAnimation();
DoubleAnimation myDoubleAnimation2 = new DoubleAnimation();
myDoubleAnimation1.Duration = duration;
myDoubleAnimation2.Duration = duration;
Storyboard sb = new Storyboard();
sb.Duration = duration;
sb.Children.Add(myDoubleAnimation1);
sb.Children.Add(myDoubleAnimation2);
Storyboard.SetTarget(myDoubleAnimation1, myRectangle);
Storyboard.SetTarget(myDoubleAnimation2, myRectangle);
// Set the attached properties of Canvas.Left and Canvas.Top
// to be the target properties of the two respective DoubleAnimations.
Storyboard.SetTargetProperty(
myDoubleAnimation1, new PropertyPath("(Canvas.Left)"));
Storyboard.SetTargetProperty(
myDoubleAnimation2, new PropertyPath("(Canvas.Top)"));
myDoubleAnimation1.To = 200;
myDoubleAnimation2.To = 200;
// Make the Storyboard a resource.
LayoutRoot.Resources.Add("unique_id", sb);
// Begin the animation.
sb.Begin();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
However, I obtain a red square that doesn't move when I run the emulator.
What could be the problem?
Thank you!
I am trying to get these ellipses to grow but I cannot figure out how to start the animation. This is my first attempt at WPF animation and I don't quite understand how it all works.
private void drawEllipseAnimation(double x, double y)
{
StackPanel myPanel = new StackPanel();
myPanel.Margin = new Thickness(10);
Ellipse e = new Ellipse();
e.Fill = Brushes.Yellow;
e.Stroke = Brushes.Black;
e.Height = 0;
e.Width = 0;
e.Opacity = .8;
canvas2.Children.Add(e);
Canvas.SetLeft(e, x);
Canvas.SetTop(e, y);
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 10;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, e.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Ellipse.HeightProperty));
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Ellipse.WidthProperty));
}
You don't need a Storyboard here. Just do
e.BeginAnimation(Ellipse.WidthProperty, myDoubleAnimation);
e.BeginAnimation(Ellipse.HeightProperty, myDoubleAnimation);
If you really need to do it with a Storyboard, you will have to add separate animations, one per animated property, to the Storyboard. And you have to call SetTarget instead of SetTargetName when you don't apply a name. Finally you'll need to start the Storyboard by calling Begin:
DoubleAnimation widthAnimation = new DoubleAnimation
{
From = 0,
To = 10,
Duration = TimeSpan.FromSeconds(5)
};
DoubleAnimation heightAnimation = new DoubleAnimation
{
From = 0,
To = 10,
Duration = TimeSpan.FromSeconds(5)
};
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(Ellipse.WidthProperty));
Storyboard.SetTarget(widthAnimation, e);
Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(Ellipse.HeightProperty));
Storyboard.SetTarget(heightAnimation, e);
Storyboard s = new Storyboard();
s.Children.Add(widthAnimation);
s.Children.Add(heightAnimation);
s.Begin();
I'm designing a game like this
class Anima
{
Storyboard story;
Random rand;
Canvas canvas;
Ellipse target;
public Anima() {
rand = new Random();
canvas = new Canvas();
target = new Ellipse();
target.Fill = Brushes.Red;
target.Width = 50;
target.Height = 50;
Canvas.SetLeft(target, rand.NextDouble() * 300);
Canvas.SetTop(target, rand.NextDouble() * 300);
canvas.Children.Add(target);
story = new Storyboard();
story.BeginTime = TimeSpan.FromMilliseconds(rand.Next(500, 5000));
DoubleAnimation a = new DoubleAnimation();
a.To = rand.NextDouble() * 300;
a.Duration = new Duration(TimeSpan.FromMilliseconds(50));
Storyboard.SetTarget(a, target);
Storyboard.SetTargetProperty(a, new PropertyPath(Canvas.LeftProperty));
story.Children.Add(a);
DoubleAnimation b = new DoubleAnimation();
b.To = rand.NextDouble() * 300;
b.Duration = new Duration(TimeSpan.FromMilliseconds(50));
Storyboard.SetTarget(b, target);
Storyboard.SetTargetProperty(b, new PropertyPath(Canvas.TopProperty));
story.Children.Add(b);
story.Completed += new EventHandler(story_Completed);
Window win = new Window();
win.Loaded += delegate(object sender, RoutedEventArgs e) {
story.Begin();
};
win.Content = canvas;
win.Show();
}
void story_Completed(object sender, EventArgs e) {
int next = rand.Next(500, 5000);
double left = rand.NextDouble() * 300;
double top = rand.NextDouble() * 300;
Console.WriteLine("position: ({0:G6}, {1:G6})", Canvas.GetLeft(target), Canvas.GetTop(target));
Console.WriteLine("state : wait for " + next + " ms");
Console.WriteLine("next : ({0:G6}, {1:G6})", left, top);
Console.WriteLine();
(story.Children[0] as DoubleAnimation).To = left;
(story.Children[1] as DoubleAnimation).To = top;
story.BeginTime = TimeSpan.FromMilliseconds(next);
story.Begin();
}
}
Everything is great, but I found that the ellipse didn't get the right position and make an error about 2% to 50%. It seems like the Storyboard.Completed event triggered before the end of animation.
What's wrong with it?
I would suggest that you use CompositionTarget.Rendering event or DispatcherTimer for controlling complex animations, especially if you are developing a game. The built-in animations are not precise enough and cannot be controlled easily.
Here are some links that will get you started on CompositionTarget
How to: Render on a Per Frame Interval Using CompositionTarget
Using the CompositionTarget
Fun with Animation Part 1
use Dispatcher.BeginInvoke(...), you can get the right value