打地鼠成品:
![Get Microsoft Silverlight](https://i-blog.csdnimg.cn/blog_migrate/f465dc8502c2f68b506811e23e11fb86.png)
一、老鼠与洞
打地鼠这个游戏,玩法很简单.当地鼠钻出地洞的时候用锤子敲打它,打中就得分.
所以当考虑要写这么一个小游戏的时候,首先应该想到,要写一个"地洞".
于是我说:"要有洞". 结果就有了洞:
注意这个洞,这可不是一般的洞.它是一个很神奇的洞,那么它是怎么组成的呢?请看下期走进科学:老鼠与洞不得不说的故事.
哈哈,跑题了.
其实这个洞,是有两层的,为了实现老鼠从动里面钻出来的效果,必须得把这个洞分为两层.一层是上面的圆口,一层是下面的草地.如图:
下面的图层挡住老鼠,老鼠挡住洞口.钻出来的效果就是这么实现的:
既然提到老鼠了,那么就不得不详细说一下.
老鼠这么个东西,实际上就是两张图片,正常情况下是这样:
被打中后是这样:
好了,介绍完洞和老鼠,下面该说说怎样整合它们了.
首先明确一点,一个洞只能有一只老鼠.
所以,每个洞里面都包含一个老鼠对象
老鼠有进洞和出洞两种变化,但是老鼠这个对象也没有必要直接让游戏逻辑去调用.所以,洞也要有一个出洞的方法:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
mouse.OutHole();
sbOutHole.Begin();
DispatcherTimer dis = new DispatcherTimer();
dis.Interval = TimeSpan.FromMilliseconds( 1000 );
dis.Tick += new EventHandler(dis_Tick2);
dis.Start();
}
void dis_Tick2( object sender, EventArgs e)
{
var dis = sender as DispatcherTimer;
if ( ! mouse.IsInjured)
sbInHole.Begin();
dis.Stop();
dis.Tick -= dis_Tick2;
}
在洞的出洞方法里调用老鼠的出洞方法,老鼠的出洞方法实际上做了一个状态切换的操作,因为老鼠在出洞之前可能已经被打过一次了
{
if (imgInjured.Visibility == Visibility.Collapsed)
{
imgNormal.Visibility = Visibility.Visible;
}
IsInjured = false ;
}
调用老鼠的出洞方法,就是把老鼠的状态置为正常.
回到洞的洞的出洞方法上,为了让游戏更具可玩性,老鼠出洞和进洞都需要一段平滑过渡的动画 sbOutHole.Begin(); 便是播放出洞动画.
老鼠不可能永远呆在洞的外面,所以在1000毫秒之后,让老鼠进洞.
当然,不是每一个老鼠都有那么幸运的,有些老鼠可能会被残忍的玩家无情的用锤子击中.这时老鼠为了配合玩家的残忍心理只能摆出一副无辜的受伤姿态啦.
老鼠的 EvInjured(被击中)事件和IsInjured(被击中)属性
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public bool IsInjured { get ; private set ; }
public Mouse()
{
// 为初始化变量所必需
InitializeComponent();
imgNormal.MouseLeftButtonDown += new MouseButtonEventHandler(imgNormal_MouseLeftButtonDown);
Cursor = Cursors.Hand;
}
void imgNormal_MouseLeftButtonDown( object sender, MouseButtonEventArgs e)
{
if (EvInjured != null )
EvInjured();
}
当老鼠被击中时,会触发EvInjured事件,老鼠所在的洞在初始化的时候就已经注册这个事件了:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
// 为初始化变量所必需
InitializeComponent();
mouse.EvInjured += new Action(mouse_EvInjured);
Loaded += new RoutedEventHandler(Hole_Loaded);
}
void mouse_EvInjured()
{
Injured();
}
洞的被击中方法:
{
mouse.Injured();
sbInHole.Begin();
}
调用老鼠的Injured方法,然后播放老鼠进洞动画.
同样的,为了让游戏逻辑清晰明了,游戏逻辑只会调用洞的被击中方法而不会去理会老鼠的被击中方法:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
imgNormal.Visibility = Visibility.Collapsed;
imgInjured.Visibility = Visibility.Visible;
DispatcherTimer dis = new DispatcherTimer();
dis.Tick += new EventHandler(dis_Tick);
dis.Interval = TimeSpan.FromMilliseconds( 500 );
dis.Start();
IsInjured = true ;
}
void dis_Tick( object sender, EventArgs e)
{
var dis = sender as DispatcherTimer;
dis.Tick -= dis_Tick;
dis.Stop();
imgInjured.Visibility = Visibility.Collapsed;
}
老鼠被击中的方法很简单,通过改变两张图片的可见性来表示当前的状态,然后在500毫秒之后让被击中的图片不可视,因为500毫秒后老鼠的进洞动画已经播放完成了.
好了,至此老鼠与洞的故事到这里就结束啦.
二、游戏主逻辑
有了老鼠与洞,还得有一段逻辑代码去控制他们.
规则:
关卡:随着玩家玩的时间变更,时间越长关卡越高,而游戏速度(地鼠出洞的速度)也随之增加
地鼠出洞:在固定的间隔时间里随机地洞的地鼠出洞.
首先把洞铺到一块草地上(草地是一张图片):
通过转换把后排的洞变小,这样更有立体感.
界面写好后,可以开始写逻辑了.用迭代把界面里的洞找出来并添加到一个List:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
gameLoop.Tick += new EventHandler(gameLoop_Tick);
gameLoop.Interval = TimeSpan.FromMilliseconds(currentSpeed);
foreach (var uie in gridHoles.Children)
{
if (uie is Hole)
{
var oneHole = uie as Hole;
holes.Add(oneHole);
oneHole.mouse.EvInjured += new Action(mouse_EvInjured);
}
}
msInjured = new MouseSound( " ResImg/MoleAttack/Sound/injured.mp3 " );
}
主循环:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![ExpandedBlockStart.gif](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
{
passedTime = DateTime.Now - startTime;
var passSeconds = passedTime.Minutes * 60 + passedTime.Seconds;
if (passSeconds > 15 && passSeconds < 30 )
{
infomation.tbLevel.Text = " 2 " ;
CurrentSpeed = 2000 ;
}
if (passSeconds > 30 && passSeconds < 60 )
{
infomation.tbLevel.Text = " 3 " ;
CurrentSpeed = 1500 ;
}
if (passSeconds > 60 && passSeconds < 120 )
{
infomation.tbLevel.Text = " 4 " ;
CurrentSpeed = 1000 ;
}
if (passSeconds > 120 && passSeconds < 240 )
{
infomation.tbLevel.Text = " 5 " ;
CurrentSpeed = 500 ;
}
if (passSeconds > 240 )
{
GameOver();
gameLoop.Stop();
}
holes[GetRandomNum( 0 , holes.Count)].OutHole();
}
passedTime 用来记录玩家玩游戏的时间,因为关卡是通过这个时间来增加的.
一直到一个固定的时间后,GameOver.(游戏的玩法就是这样的,到点就结束,然后分数越高说明玩得越好).
关卡判断完成后,随机出一个洞来并让这个洞的老鼠出洞.
嗯,这就是主逻辑了,简单吧?
三、总结
还有一些细节方面的比如分数统计,关卡显示啥的就不必说太多了.
这款游戏几乎完全使用xaml编写,只用了少部分C#代码编写逻辑,由此可见xaml的强大之处.
如能灵活的用之,便可在游戏界面上节省很多时间.
嗯,本文只是抛砖引玉,希望能够有更多的.net开发者投入到Silverlight游戏开发行列中来.