使用Silverlight制作简单的小游戏—Jewellery (Part 1)
演示页:http://seaworm.110mb.com/Jewellery.htm
逢三消除,很简单的小游戏,没有花哨的效果。新学Silverlight,这是第一个作品,边学边写,都是用的最基础的东西,大师们就不用看了。 :)
第一次写Blog,不知道怎么描述会比较好。凭感觉写,以后慢慢改进,写的不好,望见谅。
开发环境:VS2008,Silverlight 3.0
首先,在VS中新建一个Silverlight的工程,取名Jewellery(这个很废话,但是不写又觉得不合适。O(∩_∩)O~)。接下来改写MainPage.xaml,改写后的XAML大致如下:
<Grid HorizontalAlignment="Center"> <Grid.RowDefinitions> <RowDefinition Height="50" /> <RowDefinition Height="750" /> <RowDefinition Height="75" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="300" /> <ColumnDefinition Width="300" /> </Grid.ColumnDefinitions> <TextBox x:Name="Timer" Grid.Column="0" Grid.Row="0" TextAlignment="Left" Foreground="White" Text="0.00:00:00" /> <TextBox x:Name="Counter" Grid.Column="1" Grid.Row="0" TextAlignment="Right" Foreground="Yellow" Text="000" /> <Canvas x:Name="Carrier" Grid.ColumnSpan="2" Grid.Row="1" Width="600" Height="750" Background="Gray"> </Canvas> <Button Grid.Row="2" Grid.Column="0" Content="Start" Click="StartButton_Click"></Button> <Button Grid.Row="2" Grid.Column="1" Content="Stop" Click="StopButton_Click"></Button> </Grid>
使用Grid布局,用两个TextBox分别表示用掉的时间和获得的分数,一块Canvas在中间,作为游戏显示区,最下面是两个Button,用于Start和Stop。
布局有了,现在开始设计游戏架构。我喜欢从使用的角度出发,设计代码。首先我希望有这样一个类,可以在用户点Start的时候,传一个Canvas给它,由它接管这个Canvas,直到用户点Stop。所有,我有这样一个类:
public class Jewels { public Start(Canvas canvas) { } public Stop() { } }
光有Canvas是不行的,这个类还需要知道每个Jewel的大小,以及每行、列有多少个Jewel。其实,知道每个Jewel的大小,就能知道Canvas能放下多少个Jewel,不过这里我懒了一下,因为Canvas的大小是写死的,所以没有专门去算这个,而是作为参数传给这个类。于是,增加构造函数如下:
public Jewels(double jewelWidth, double jewelHeight, int rowCount, int columnCount) { }
这里应该还需要一个参数,就是Jewel的种类,不过,这个我也写死了,因为我就只有那么几张图片。 :)
该定义一个数组来存储Jewel了,首先需要一个Jewel的对象。不过,一开始不应该太关注Jewel本身的实现,比如,如何显示,如何移动等。我们只需要找出,一个Jewel需要具备哪些属性和方法。所以,一开始,我们先定义一个基类JewelBase如下:
public abstract class JewelBase { public double Width; public double Height; public int IndexX;// index of row public int IndexY;// index of column public int Kind;// kind of jewel }
基本的属性就这些,让我们在Jewels类中加入Jewel数组,由Jewels来管理所有的Jewel。这里使用了泛型来改写Jewels类:
public class Jewels<T> where T : JewelBase, new() { private T[,] JewelMap { get; set; } }
使用new()是为了可以在Jewels内部方便构建Jewel实例。好了,为了可以构建Jewels,先定义一个Jewel类,继承于JewelBase,先不管实现。
public class Jewel : JewelBase { }
现在可以回来写一下MainPage.xaml.cs文件了。
public partial class MainPage : UserControl { private double jewelWidth = 50; private double jewelHeight = 50; private Jewels<Jewel> Jewels; public MainPage() { InitializeComponent(); this.Initialize(); } private void Initialize() { this.Jewels = new Jewels<Jewel>(this.jewelWidth, this.jewelHeight, 12, 15); } private void StartButton_Click(object sender, RoutedEventArgs e) { this.Jewels.Start(this.Carrier); } private void StopButton_Click(object sender, RoutedEventArgs e) { this.Jewels.Stop(); } }
看起来很简单的样子。:)现在可以试着Build出来看一下了,虽然什么都没有。O(∩_∩)O~
继续,分析游戏的基本逻辑,执行过程大概是这样的:
根据这个流程,为Jewels类增加方法,如下:
// Initialize jewel array private void Initialize() { } // Select jewel private void SelectJewel(T jewel) { } // Unselect jewel private void UnselectJewel(T jewel) { } // check two jewels whether is neighbor private bool IsNeighbor(T source, T target) { } // exchange two jewels private void Exchange(T source, T target) { } // try to destroy, return value indicate whether success private bool TryToDestroy() { } // fill jewels after destroy private void Fill(T[] jewels) { }
同时,我们为JewelBase类增加两个新的方法,用于处理具体的显示工作,以及一个Event,响应Jewel的Click事件:
// jewel click event public event EventHandler Click; // display move animation public virtual void MoveTo(int indexX, int indexY) { } // display destroy animation public virtual void Destroy() { }
为了让用户在选择Jewel的时候,可以看到一个闪烁的边框,我单独提出一个类作为Jewel的Selector。先定义一个Interface,以后再来编写具体的代码。
public interface IJewelSelector { void Selected(Canvas canvas, JewelBase jewel); void Unselected(Canvas canvas); }
好,到此为止,基本的设计工作已经完成,接下来让我们编写具体的实现代码吧。
未完待续…