Introduction
When I worked on writing the Tetris game using Silverlight,
I would like an animation happen before a qualified row of squares begin to
collapse in response to a command. This will obviously make the game more fun.
The Problem
The animation should be invoked if necessary in a command handler (see the pseudo code below). I tried storyboard with multiple children and multiple
storyboards, neither of them worked and this drove me nut. Searching the
Internet, some one said this is impossible since there is only UI thread.
xxx_command()
{
1. Check if rows qualified for collapse
2. If yes, raise collapse event, do the animation here
3. Collapse
}
But looking at windows operating system and games they all have animations. I believe a solution exists. Finally I found it.
The Solution
The solution turns out pretty simple. The animation in WPF
itself is essentially a series of actions responding to a timer event. So I
don’t need to use storyboard: simply initiate a dispatcher timer, hook up an
anonymous delegate handler, inside which the rows of squares are iterated and
opacity is reduced gradually.
There are two tricky points here. First, it needs to disable
all other commands such that only animation is executed in the UI thread.
Second, it needs to return to the code right after the animation (line 3, Collapse).
To address the first issue, introduce a new variable AnimationInProgress
. If
this variable is true all command handlers will simply skip including the
keyboard handlers. To address the second issue, we need to use anonymous
delegate and wrap all the code after the animation into a delegate parameter.
collapse_event_handler(Action<object> collapseAction)
{
AnimationInProgress = true;
var timer = new DispatcherTimer();
timer.tick += delegate{
Code to iterate all squares and reduce opacity
If (done)
{
collapseAction();
timer.Stop();
timer = null;
AnimationInProgress = false;
}
};
timer.Start();
}
Points of Interest
Note that the key to the solution is using anonymous
delegate to mimic returning to the command. Anonymous delegate is a closure
that contains the entire execution context. In C/C++, it is function pointers.
Looking in this perspective it is not surprising that why windows operation
system and games can implement animations with ease.
Demo
You can go to http://www.bizsoftzen.com/silverlight-demos
to see the demo. When a row is qualified for collapse they are faded gradually(opacity is decremented gradually).