-
Notifications
You must be signed in to change notification settings - Fork 2
/
BallAnimation.cs
85 lines (72 loc) · 2.28 KB
/
BallAnimation.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
using System;
using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using CoroutinesDotNet;
namespace CoroutinesForWpf.Example
{
public class BallAnimation : CoroutineBase
{
private readonly IEnumerator _mainCoroutine;
private readonly Ellipse _ball;
private readonly double _ballHeight;
private readonly double _stepSize;
private readonly double _halfStepSize;
private Point _center;
public BallAnimation(Ellipse ball, double stepSize)
{
_ball = ball;
_stepSize = stepSize;
_halfStepSize = _stepSize / 2;
_ballHeight = ball.Height - 3; // line thickness ???
_mainCoroutine = CreateMainCoroutine();
}
public override object Current => _mainCoroutine.Current;
public bool Continue { private get; set; }
public Point Center
{
set
{
_center = value;
Canvas.SetLeft(_ball, _center.X + _halfStepSize);
}
}
public override bool MoveNext()
{
return _mainCoroutine.MoveNext();
}
private IEnumerator CreateMainCoroutine()
{
yield return new WaitUntil(() => Continue);
yield return RunDropBall();
yield return RunBounceBall();
}
private IEnumerator RunDropBall()
{
var ballDropTarget = _center.Y + _halfStepSize;
var dropStep = ballDropTarget / _stepSize;
var ballY = 0d;
Canvas.SetTop(_ball, ballY);
while (ballY <= ballDropTarget)
{
ballY += dropStep;
Canvas.SetTop(_ball, ballY);
yield return null;
}
}
private IEnumerator RunBounceBall()
{
double bounceHeight = 2 * _stepSize;
int x = 0;
while (true)
{
Canvas.SetTop(_ball, _center.Y + _ballHeight - bounceHeight * Math.Sin(Math.PI * x / _stepSize));
x += 1;
if (x >= _stepSize) x = 0;
yield return null;
}
// ReSharper disable once IteratorNeverReturns
}
}
}