Creating Smoke Using Frame Based Animations in Windows Phone
Join the DZone community and get the full member experience.
Join For FreeCreating smoke can be a useful trick because you can use it for a wealth of applications, such as when a rocket fires, when a volcano erupts, or when a car is racing. So how can you create smoke in Windows Phone 7?
There are many ways to achieve this effect but for this post you will use a
frame based approach to build smoke. The effect when played on your
Windows Phone or emulator is pretty cool, as if the smoke is coming out
of the phone!
Understanding the Physics of Smoke
Let’s look at the physical behavior of the smoke coming out of the
volcano. Take a small sample of smoke as seen below in the red rectangle. Here
are tje observed behaviors of the smoke:
Smoke Behavior | How to Handle in Windows Phone 7 |
Smoke is moving up at random velocity. | Canvas.Leftproperty and Canvas.TopProperty changes at random. |
As the smoke moves up it becomes larger. | ScaleX and ScaleY of the smoke changes at random. |
Smoke gradually disappears. | Opacity of the smoke changes at random. |
Creating Smoke Per Frame
Basically you will need to create a tiny smoke image as shown in the figure below. Each smoke image will observe the three behaviors described in the above
section. As the frame is rendered you will be adding the addiontal smoke images.
To add a smoke per frame you will be using the code below in MainPage.xaml:
public MainPage() { InitializeComponent(); CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); } private void CompositionTarget_Rendering(object sender, EventArgs e) { SmokeImage smoke = new SmokeImage(); LayoutRoot.Children.Add(smoke); smoke.X = 200; smoke.Y = 700; }
Describing a Smoke Behavior in Code
Now that you are adding a smoke per frame, you need to make sure that each added smoke behaves as described in the code above.
SmokeImage class will inherit from Canvas and as the frame is rendered, the smoke will change it’s own property.
Smoke Properties
As part of the smoke properties you will need smoke image (_smoke),
random generator (_rnd), veclocity for x and y direction (_velocityX and
_velocityY), and opacity scale rate (_currentScale). Notice that X and Y are used initially one time when the smoke is added to the parent canvas and
from this initial position, the smoke will begin it’s journey up into the
sky and disappear.
private Random _rnd = new Random(); private Image _smoke; // Control the speed of the smoke going up private double _velocityX; private double _velocityY; // dissipates rate of smoke as it rises private double _currentScale; // X and Y is used to position starting location of the smoke public double X { get { return (double)(GetValue(Canvas.LeftProperty)); } set { SetValue(Canvas.LeftProperty, value); } } public double Y { get { return (double)(GetValue(Canvas.TopProperty)); } set { SetValue(Canvas.TopProperty, value); } }
Initializing Smoke
A lot is happening in the initialization, but I want to point out two
things: 1) you have ability to change the smoke image and 2) using
CompositionTarget.Rendering, you will be changing the smoke properties
per frame. Here is the code:
public SmokeImage() { // Set speed of smoke rising random so it is more realistic _velocityX = _rnd.Next(-1, 1) – _rnd.Next(-1, 1); _velocityY = _rnd.Next(-1, 1) * 3 – 5; _smoke = new Image(); _smoke.Width = 40; _smoke.Height = 40; _smoke.Source = new BitmapImage(new Uri(“/SmokeAnimationDemo;component/smoke.png”, UriKind.Relative)); this.Children.Add(_smoke); // create different smokes dark to faded _smoke.Opacity = _rnd.Next(0, 100); // create different size of smoke _currentScale = _rnd.Next(1); ScaleTransform scale = new ScaleTransform(); scale.ScaleX = _currentScale; scale.ScaleY = _currentScale; _smoke.RenderTransform = scale; // set frame rate higher the frame rate more smokes it will create App.Current.Host.Settings.MaxFrameRate = 25; CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); }
Changing Smoke Properties Per Frame
You will be changing the smoke properties per frame as described in the sections above. One of the most important things you must be aware is
that when the smoke opacity becomes zero, you want to make sure to remove
the smoke image from the parent Canvas. If you don’t you will end up
adding MANY smoke images and eating up the your memory. See code below:
private void CompositionTarget_Rendering(object sender, EventArgs e) { // Smoke fades as it rises _smoke.Opacity -= 1; // Smoke rises up Canvas.SetLeft(_smoke, Canvas.GetLeft(_smoke)+_velocityX); Canvas.SetTop(_smoke, Canvas.GetTop(_smoke)+_velocityY); // Smoke dissipates _currentScale += 0.09; ScaleTransform scale = new ScaleTransform(); scale.ScaleX = _currentScale; scale.ScaleY = _currentScale; _smoke.RenderTransform = scale; // remove smoke if it fades completely if (_smoke.Opacity < 0) { RemoveSelf(); } } private void RemoveSelf() { CompositionTarget.Rendering -= new EventHandler(CompositionTarget_Rendering); ((Canvas)this.Parent).Children.Remove(this); }
Download Code
Conclusion
In this blog you learned about creating a smoke effect using a frame
based approach in Windows Phone 7 and provided a glimpse at the use of the CompositionTarget.Rendering event to achieve this.
Source: http://blog.toetapz.com/2010/12/15/create-smoke-using-frame-based-animation-in-windows-phone-7/
Opinions expressed by DZone contributors are their own.
Comments