Wiki


Wiki Table of Contents

Page Details

First published by:
Last revision by:
1 person found this article useful.

100% of people found this useful
Silverlight Tip of the Day #43: Making it Snow in Silverlight

Filed under: [Edit Tags]

Tôi không say mê mùa đông vì mùa hè là mùa yêu thích của tôi. Tuy nhiên, sáng nay tôi đã thức dậy và đã nghe trời sắp có tuyết trên những đỉnh núi (Cascades) và tạo cảm hứng thú vị nho nhỏ trong  tôi là tạo một khung cảnh có tuyết rơi trong Silverlight.

Demo: http://silverlight.services.live.com/invoke/66033/Snowflakes/iframe.html

 

Screenshot:

image 

Bên phải là một công cụ cho phép bạn :

  1. Điều chỉnh dung lượng của tuyết.
  2. Điều chỉnh tốc độ gió (bên trái bên phải).

image

Tôi nhận thấy ứng dụng đã được nhiều người xây dựng trên bản beta2 và sau đó là bản RTM. Vì vậy, nếu bạn sử dụng bản beta 2, tôi khuyên bạn nên thận trọng khi tăng khối lượng tuyết

Để làm demo này, hãy thực hiện theo những bước sau:

Bước 1. Tạo một ứng dụng  Silverlight Application Project sử dụng  Visual Studio 2008. (Hãy  xem cụ thể tại  Tip of the Day #2  ).

Bước  2. Thêm hình sau vào Silverlight Application project của bạn :

Bước  3. Thêm mới  một Silverlight User Control vào  ứng dụng  Silverlight Application  của bạn và gọi nó là SnowFlake.xaml. Để làm điều này, click chuột phải trên ứng dụng Silverlight của bạn trong cửa sổ  Solution Explorer. Chọn  “Add->New Item…”. Chọn  “Silverlight User Control” thay đổi  Name thành  “Snowflake.xaml” và nhấn nút OK.

Bước  4. Thay đổi code  XAML của trang  Snowflake.xaml của bạn như sau:

<UserControl x:Class="Snowflakes.SnowFlake"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Image x:Name="Flake" Source="snowflake.png">
        <Image.RenderTransform>
            <ScaleTransform x:Name="SnowScale" ScaleX="0.25" ScaleY="0.25"></ScaleTransform>
        </Image.RenderTransform>
    </Image>
</UserControl>

Chúng ta chủ yếu thêm vào một hình ảnh đại diện cho một hoa tuyết. Vì hình hoa tuyết gốc lớn hơn là tôi tưởng, tôi đã thay đổi tỉ lệ để nó chỉ hiển thị kích thước là 0.25 (1/4) so với  kích thước bình thường của nó bằng cách sử dụng một ScaleTranform.

Bước  5. Trong phần code phía sau của snowflake (Snowflake.xaml.cs) chúng ta sẽ thêm một điều cần thiết để làm cho hoa tuyết rơi xuống. Tất cả những điều cần thiết chúng ta phải làm là:

  1. Chọn tọa độ là  Left, Top cho hoa tuyết . Và các hoa tuyết sẽ được ngẫu nhiên thay đổi  từ 1 đến 50 hướng.
  2. Khi những hoa tuyết từ tọa độ  Top có giá trị bằng giá trị  floor value   (764 như các hình ảnh của tôi ), hay khi nó bắt đầu đến hết cửa sổ  chúng ta sẽ gán Completed = true. Vòng lặp chính của chúng ta trong Page.xaml.cs sẽ được dọn sạch tất cả các bông tuyết với thuộc tính Completed được gán là true.
  3. Khi chúng ta tạo các hoa tuyết, chúng ta ngẫu nhiên thay đổi tỉ lệ lên hay xuống một chút để tạo một cái nhìn sâu sắc hơn.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace Snowflakes
{
    public partial class SnowFlake : UserControl
    {
        double _posLeft = 0.0;
        double _posTop = 0.0;
        double _floorValue = 764;
        int seed = DateTime.Now.Millisecond;
        Random _rand = new Random(DateTime.Now.Millisecond);
        private bool _completed = false;
 
        double _horzInc = 0.0;
 
        public bool Completed
        {
            get { return _completed; }
        }
 
        public SnowFlake(double left, double top)
        {
            InitializeComponent();
 
            _posLeft = left;
            _posTop = top;
 
            this.SetValue(Canvas.LeftProperty, _posLeft);
            this.SetValue(Canvas.TopProperty, _posTop);
 
            Random rndSize = new Random(DateTime.Now.Millisecond);
            SnowScale.ScaleX = SnowScale.ScaleY = 0.05 * rndSize.Next(1, 6);
 
        }      
        
        public void Fall(double windValue)
        {
            int value = _rand.Next(50);
 
            if (value == 25) //  1 in 50 change to change direction
            {
                if (_horzInc >= 0.2)
                    _horzInc = 0;
                else if (_horzInc <= -0.2)
                    _horzInc = 0;
                else
                {
                    value = _rand.Next(3);
                    if (value == 1) _horzInc = 0.2;
                    else if (value == 2) _horzInc = -0.2;
                    else if (value > 0) _horzInc = 0.0;
                }
            }
            
            double horzValue = _horzInc + (windValue * 0.1);
            
            _posLeft += horzValue;
               
            this.SetValue(Canvas.LeftProperty, _posLeft);
            this.SetValue(Canvas.TopProperty, _posTop++);
 
            _completed = (_posLeft >= 1019 || _posLeft <= 0 || _posTop >= _floorValue);
        }
    }
}

Bước  6: Trở lại trang Page.xaml.cs chúng ta sẽ thêm một timer để di chuyển   hay tạo các hoa tuyết. Khi di chuyển các  hoa tuyết , chúng ta kiểm tra để xem nếu các hoa tuyết có Completed = true. Nếu như thế, chúng ta thêm nó vào một array để gỡ bỏ. Khi chúng ta tạo những hoa tuyết, chúng ta tạo chúng dọc theo chiều của trang giấy từ trên xuống . Tuy nhiên, nếu có gió chúng ta cũng cần tạo chúng rơi từ  bên trái hay từ bên phải của cảnh bay qua lại theo hướng gió.

Sau đây là code cho trang  Page.xaml.cs bao gồm những đoạn mã cần thiết cho việc xử lý thanh công cụ:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
 
namespace Snowflakes
{
    public partial class Page : UserControl
    {
        List<SnowFlake> _snowFlakes = new List<SnowFlake>();
        Storyboard _snowflakeTimer = new Storyboard();
        Random _rand = new Random(DateTime.Now.Millisecond);
        int _newFlakeCount = 2;
        int _wind = 0;
 
        public Page()
        {
            InitializeComponent();
 
            _snowflakeTimer.Duration = TimeSpan.FromMilliseconds(10);
            _snowflakeTimer.Completed += new EventHandler(SnowFlakeTimer);
            _snowflakeTimer.Begin();
        }
 
        private void SnowFlakeTimer(object sender, EventArgs e)
        {
            MoveSnowFlakes();
            CreateSnowFlakes();
        }
 
        private void MoveSnowFlakes()
        {
            List<SnowFlake> _flakesToRemove = new List<SnowFlake>();
         
            foreach (SnowFlake flake in _snowFlakes)
            {
                flake.Fall(_wind);
                if (true == flake.Completed)
                    _flakesToRemove.Add(flake);
            }
            foreach (SnowFlake flake in _flakesToRemove)
            {
                _snowFlakes.Remove(flake);
                SnowCanvas.Children.Remove(flake);
            }
            _snowflakeTimer.Begin();
        }    
 
        private void CreateSnowFlakes()
        {
            TotalCount.Text = "Total Snowflakes = " + _snowFlakes.Count;
          
            int count = _rand.Next(0, _newFlakeCount);
            for (int i = 0; i < count; i++)
            {
                SnowFlake flake = new SnowFlake(_rand.Next(0, 1020), 0.0);
                _snowFlakes.Add(flake);
                SnowCanvas.Children.Add(flake);
            }
            if (_wind < 0)
            {
                for (int i = 0; i < count; i++)
                {
                    SnowFlake flake = new SnowFlake(1010, _rand.Next(0, 700));
                    _snowFlakes.Add(flake);
                    SnowCanvas.Children.Add(flake);
                }
            }
            else if (_wind > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    SnowFlake flake = new SnowFlake(0, _rand.Next(0, 700));
                    _snowFlakes.Add(flake);
                    SnowCanvas.Children.Add(flake);
                }
            }
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Host.Content.IsFullScreen = true;
        }
 
        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (null != Volume)
            {
                _newFlakeCount = (int)Volume.Value;
                VolumeValue.Text = _newFlakeCount.ToString();
            }
        }
 
        private void Wind_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (null != Wind)
            {
                _wind = (int)Wind.Value;
                WindValue.Text = _wind.ToString();
            }
        }
    }
}

Bước  7: Sau đây là code dành cho thanh công cụ chúng ta đặt trong trang Page.xaml:

<UserControl x:Class="Snowflakes.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="1020" Height="768">
    <Canvas x:Name="SnowCanvas" Width="1020" Height="768" Background="Black">
        <Image Width="1020"  Source="Scene.jpg"></Image>
        <TextBlock Canvas.Left="1022" x:Name="TotalCount" Foreground="White">Total Snowflakes</TextBlock>
        <TextBlock Canvas.Left="1022" Canvas.Top="30" Foreground="White">Volume</TextBlock>
        <Slider x:Name="Volume" Value="3" ValueChanged="Slider_ValueChanged" Canvas.Left="1110" Canvas.Top="30"  Minimum="0" Maximum="10" Width="100"></Slider>        
        <TextBlock  Canvas.Left="1210" Canvas.Top="30" Foreground="White" x:Name="VolumeValue">2</TextBlock>
       
        <TextBlock Canvas.Left="1022" Canvas.Top="60" Foreground="White">Wind</TextBlock>
        <Slider x:Name="Wind" Value="0" ValueChanged="Wind_ValueChanged" Canvas.Left="1110" Canvas.Top="60"  Minimum="-50" Maximum="50" Width="100"></Slider>
        <TextBlock  Canvas.Left="1210" Canvas.Top="60" Foreground="White" x:Name="WindValue">0</TextBlock>
        <Button Canvas.Left="1022" Canvas.Top="100" Content="Full Screen" Click="Button_Click"></Button>
    </Canvas>
</UserControl>
 

Cuối cùng, bạn đã có một khung cảnh tuyết đẹp và lãng mạn  để thưởng thức!

 

Thank you,
--Mike Snow

Recent Comments

Leave the first comment for this page.