• Silverlight小游戏系列之"打地鼠"


    打地鼠成品:

    Get Microsoft Silverlight

    一、老鼠与洞

    打地鼠这个游戏,玩法很简单.当地鼠钻出地洞的时候用锤子敲打它,打中就得分.

    所以当考虑要写这么一个小游戏的时候,首先应该想到,要写一个"地洞".

    于是我说:"要有洞". 结果就有了洞:

    image

    注意这个洞,这可不是一般的洞.它是一个很神奇的洞,那么它是怎么组成的呢?请看下期走进科学:老鼠与洞不得不说的故事.

    哈哈,跑题了.

    其实这个洞,是有两层的,为了实现老鼠从动里面钻出来的效果,必须得把这个洞分为两层.一层是上面的圆口,一层是下面的草地.如图:

    image

    下面的图层挡住老鼠,老鼠挡住洞口.钻出来的效果就是这么实现的:

    image 

    既然提到老鼠了,那么就不得不详细说一下.

    老鼠这么个东西,实际上就是两张图片,正常情况下是这样:

    image

    被打中后是这样:

    image 

    好了,介绍完洞和老鼠,下面该说说怎样整合它们了.

    首先明确一点,一个洞只能有一只老鼠.

    所以,每个洞里面都包含一个老鼠对象

    image

    老鼠有进洞和出洞两种变化,但是老鼠这个对象也没有必要直接让游戏逻辑去调用.所以,洞也要有一个出洞的方法:

    洞的出洞方法
    public void OutHole() 

        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; 
    }

    在洞的出洞方法里调用老鼠的出洞方法,老鼠的出洞方法实际上做了一个状态切换的操作,因为老鼠在出洞之前可能已经被打过一次了

    public void OutHole() 

        
    if (imgInjured.Visibility == Visibility.Collapsed) 
        { 
            imgNormal.Visibility 
    = Visibility.Visible; 
        } 
        IsInjured 
    = false
    }

     

    调用老鼠的出洞方法,就是把老鼠的状态置为正常.

    回到洞的洞的出洞方法上,为了让游戏更具可玩性,老鼠出洞和进洞都需要一段平滑过渡的动画    sbOutHole.Begin(); 便是播放出洞动画.

    老鼠不可能永远呆在洞的外面,所以在1000毫秒之后,让老鼠进洞.

    当然,不是每一个老鼠都有那么幸运的,有些老鼠可能会被残忍的玩家无情的用锤子击中.这时老鼠为了配合玩家的残忍心理只能摆出一副无辜的受伤姿态啦.

    老鼠的 EvInjured(被击中)事件和IsInjured(被击中)属性

    老鼠的被击中事件和被击中属性
            public event Action EvInjured; 

            
    public bool IsInjured { getprivate 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事件,老鼠所在的洞在初始化的时候就已经注册这个事件了:

    洞注册老鼠的被击中事件
            public Hole() 
            { 
                
    // 为初始化变量所必需 
                InitializeComponent(); 
                mouse.EvInjured 
    += new Action(mouse_EvInjured); 
                Loaded 
    += new RoutedEventHandler(Hole_Loaded); 
            }

            
    void mouse_EvInjured() 
            { 
                Injured(); 
            } 

    洞的被击中方法:

    public void Injured() 

        mouse.Injured(); 
        sbInHole.Begin(); 
    }

    调用老鼠的Injured方法,然后播放老鼠进洞动画.

    同样的,为了让游戏逻辑清晰明了,游戏逻辑只会调用洞的被击中方法而不会去理会老鼠的被击中方法:

    老鼠的被击中方法
     public void Injured() 

        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毫秒后老鼠的进洞动画已经播放完成了.

    好了,至此老鼠与洞的故事到这里就结束啦.

    二、游戏主逻辑

    有了老鼠与洞,还得有一段逻辑代码去控制他们.

    规则:

    关卡:随着玩家玩的时间变更,时间越长关卡越高,而游戏速度(地鼠出洞的速度)也随之增加

    地鼠出洞:在固定的间隔时间里随机地洞的地鼠出洞.

    首先把洞铺到一块草地上(草地是一张图片):

    image

    通过转换把后排的洞变小,这样更有立体感.

    image 

    界面写好后,可以开始写逻辑了.用迭代把界面里的洞找出来并添加到一个List:

    初始化洞列表
    void GameMain_Loaded(object sender, RoutedEventArgs e) 

        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"); 

    主循环:

    主循环
    void gameLoop_Tick(object sender, EventArgs e) 

        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游戏开发行列中来.

    源码:https://files.cnblogs.com/zhubenwuzui/MoleAttack.rar

  • 相关阅读:
    Linux课程实践一:Linux基础实践(SSH)
    《恶意代码分析实战》读书笔记 静态分析高级技术一
    Linux课程实践四:ELF文件格式分析
    Linux课程实践三:简单程序破解
    Linux课程实践二:编译模块实现内核数据操控
    2020.12.19 加分项和课程意见/建议
    博客已换
    [题解] LuoguP4983 忘情
    [题解] LuoguP4767 [IOI2000]邮局
    [题解] LuoguP2791 幼儿园篮球题
  • 原文地址:https://www.cnblogs.com/DreamCreator/p/1778156.html
Copyright © 2020-2023  润新知