使用Silverlight制作简单的小游戏—Jewellery (Part 3)

上一篇:使用Silverlight制作简单的小游戏—Jewellery (Part 2)

 

实现Jewel类。Jewel类是继承于虚类JewelBase的,让我们先来看一下当前JewelBase的定义。

    public abstract class JewelBase
    {
        #region Properties

        public double Width { get; set; }
        public double Height { get; set; }
        public int IndexX { get; set; }
        public int IndexY { get; set; }
        public int Kind { get; set; }

        #endregion

        public event EventHandler Click;

        #region Abstract Methods

        public abstract void Initialize(Canvas panel);

        public abstract void MoveTo(int x, int y);

        public abstract void Destroy();

        #endregion
    }

动画过程用Storyboard来实现,在每次动画结束后,通知JewelEvent类。改进一下JewelBase中的abstract方法,如下:

        public virtual void MoveTo(int x, int y)
        {
            Storyboard board = this.GetMoveAnimation(x, y);
            board.Completed += new EventHandler(moveBoard_Completed);
            board.Begin();
        }

        private void moveBoard_Completed(object sender, EventArgs e)
        {
            JewelEvent.Add(JewelEventNames.Moved, this);  // move finish
        }

        public virtual void Destroy()
        {
            Storyboard board = this.GetDestroyAnimation();
            board.Completed += new EventHandler(destroyBoard_Completed);
            board.Begin();
        }

        private void destroyBoard_Completed(object sender, EventArgs e)
        {
            JewelEvent.Add(JewelEventNames.Destroy, this);  // destroy finish
        }

        #region Abstract Methods

        public abstract void Initialize(Canvas panel);

        protected abstract Storyboard GetMoveAnimation(int x, int y);

        protected abstract Storyboard GetDestroyAnimation();

        #endregion

好了,接下来就是在Jewel中实现这3个abstract方法。

这里使用SL中的Image显示图片,在Initialize方法中,主要是初始化Image的位置、大小,以及根据Kind选择图片源,并绑定Image的MouseLeftButtonDown事件,转化为JewelBase的Click事件,这样Jewel就可以响应用户的点击事件了。对于Jewel的Size,这里使用ScaleTransform来控制,所以要在Initialize中恢复Jewel的Size。

        public override void Initialize(Canvas canvas)
        {
            if (this.image == null)
            {
                this.image = new Image();
                this.image.Width = this.Width;
                this.image.Height = this.Height;

	        // use ScaleTransform to control Jewel's size
                this.image.RenderTransform = new ScaleTransform()
                {
                    CenterX = this.Width / 2,
                    CenterY = this.Height / 2,
                    ScaleX = 1.0,
                    ScaleY = 1.0
                };
                this.image.MouseLeftButtonDown += new MouseButtonEventHandler(rect_MouseLeftButtonDown);

                canvas.Children.Add(this.image);
            }

            Canvas.SetLeft(this.image, this.IndexX * this.Width);
            Canvas.SetTop(this.image, this.IndexY * this.Height);
            
            // reset
            ScaleTransform st = (ScaleTransform)this.image.RenderTransform;
            st.ScaleX = 1.0;
            st.ScaleY = 1.0;

            switch (this.Kind)
            {
                // set Image.Source
            }
        }

GetMoveAnimation方法和GetDestroyAnimation方法类似,就是构建并返回一个Storyboard实例。看下代码就好了。:)

        #region GetMoveAnimation Method

        protected override Storyboard GetMoveAnimation(int x, int y)
        {
            Storyboard board = new Storyboard();

            DoubleAnimation animation = new DoubleAnimation()
            {
                From = Canvas.GetLeft(this.image),
                To = x * this.Width,
                Duration = new Duration(TimeSpan.FromMilliseconds(speed))
            };
            Storyboard.SetTarget(animation, this.image);
            Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Left)"));
            board.Children.Add(animation);

            animation = new DoubleAnimation()
            {
                From = Canvas.GetTop(this.image),
                To = y * this.Height,
                Duration = new Duration(TimeSpan.FromMilliseconds(speed))
            };
            Storyboard.SetTarget(animation, this.image);
            Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));
            board.Children.Add(animation);

            return board;
        }

        #endregion

        #region GetDestroyAnimation Method

        protected override Storyboard GetDestroyAnimation()
        {
            Storyboard board = new Storyboard();

            DoubleAnimation animation = new DoubleAnimation()
            {
                From = 1.0,
                To = 0.0,
                Duration = new Duration(TimeSpan.FromMilliseconds(moveSpeed))
            };
            Storyboard.SetTarget(animation, this.image.RenderTransform);
            Storyboard.SetTargetProperty(animation, new PropertyPath("(ScaleX)"));
            board.Children.Add(animation);

            animation = new DoubleAnimation()
            {
                From = 1.0,
                To = 0.0,
                Duration = new Duration(TimeSpan.FromMilliseconds(moveSpeed))
            };
            Storyboard.SetTarget(animation, this.image.RenderTransform);
            Storyboard.SetTargetProperty(animation, new PropertyPath("(ScaleY)"));
            board.Children.Add(animation);

            return board;
        }

        #endregion

这就是整个Jewel类,再运行一下程序,我们会看到一个布满Jewel的Canvas,并且已经可以运行了。不过,这里还差一个部分要说,就是实现IJewelSelector接口,使得用户在点击Jewel时,可以看到一个闪烁的外框。这里利用动态变化的虚线框,来实现一个被选择的效果。在Selected方法中显示,在Unselected中隐藏。这里只贴出来动画的实现,具体的实现请看本文最后附加的源代码。

this.selectedLine = new Rectangle();
this.selectedLine.StrokeThickness = 2;
this.selectedLine.Stroke = new SolidColorBrush(Colors.Orange);
DoubleCollection dc = new DoubleCollection() { 1, 2 };
this.selectedLine.StrokeDashArray = dc;
this.selectedLine.StrokeDashOffset = 0;
this.selectedLine.StrokeDashCap = PenLineCap.Round;

canvas.Children.Add(this.selectedLine);

                // set animation
Storyboard board = new Storyboard();

DoubleAnimation animation = new DoubleAnimation()
{
    From = 0,
    To = 3,
    Duration = new Duration(TimeSpan.FromMilliseconds(300)),
    RepeatBehavior = RepeatBehavior.Forever,
};
Storyboard.SetTarget(animation, this.selectedLine);
Storyboard.SetTargetProperty(animation, new PropertyPath("(StrokeDashOffset)"));
board.Children.Add(animation);

board.Begin();

完结。

 

源代码:Jewellery.zip

posted on 2010-09-21 14:41  海毛虫  阅读(637)  评论(0编辑  收藏  举报