使用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
浙公网安备 33010602011771号