社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 道具中心
主题 : [原创]XNA游戏Marblets源码导读(更新完毕)
jongen 离线
级别: ①新人
显示用户信息 
0  发表于: 2007-11-03   
来源于   分类

[原创]XNA游戏Marblets源码导读(更新完毕)

管理提醒: 本帖被 shawind 设置为精华(2007-11-03)
觉得这种方式蛮好,边读边写笔记一样,为以后的使用做个记录,也可以引导一下初学者(我不是初学者之后,后面再学XNA的 ),何乐而不为呢.

安装好Marblets后,新建一个Marblets游戏解决方案.

首先我们先生build,生成可执行文件,这样我们看代码的时候,可以看到实际效果,有一个感性的认识.

先来看一下它的框架,大概我给分了一下类:

1.游戏场景处理
    Screen  继承自DrawableGameComponent(已就是让我感觉AoohooXnaGameLib白写了的东东),场景处理的基类
    TitleScreen 继承自Screen,一进程序所显示的场景,显示游戏标题和高分榜.
    GameScreen  继承自Screen,真正的游戏场景
   
2.重点逻辑处理
    MarbletsGame 场景的切换,按钮的处理都在这里
    GameBoard 该游戏的逻辑处理都在这里了
    TutorialGameBoard 扩充的游戏模式

3.键盘和X360手柄按键处理
    GamePads 游戏者的定义和按钮状态的检测
    GamePadKey 定义了游戏中使用的键和键状态检测
    InputHelper 当前游戏的检测
    这个游戏考虑到了对PC和X360的双支持,如果像我这样打个小游戏不打算在X360上运行的话,倒可以省略很多.

4.其它
    Marble 游戏中的一个圆球
    Sound 声音处理
    Settings 游戏配置的处理,使用了XmlSerializer,很有用的
    settings.xml 游戏配置信息
    RelativeSprite 继承自SpriteBatch,实现了游戏画面的相对表示,不明白?改变一下游戏窗口的大小看看
    Font 文字的处理,显示高分榜的时候用到
    Program 这个不说了
    highscores.xml 高分榜数据,和settings.xml一样的东西.


先这样了,明天继续一个个来分析.
[ 此贴被jongen在2007-11-05 07:58重新编辑 ]
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
我的XNA学习足迹将记在这里
http://showim.net/blog/?cateID=4
jongen 离线
级别: ①新人
显示用户信息 
1  发表于: 2007-11-03   
接着来看Marblets游戏源码,昨天大概分了一下类,首先挑软柿子捏,看一下其中不相关的几个类.

1.Marble.cs 游戏中的一个圆球

    千里之行,始于足下,九层之台,起于垒土,别看是游戏中的最小一个元素,设计好了,可是有功半功倍的效果。
   
    1)  首先是属性的定义:长、宽、圆球消失时的动画相关、四个Texture2D(消失动画分解图、选中时的两个线圈、无色的球)、以及球的颜色。
    这个游戏没有使用四种球的图片,而且Color属性来控制,应该是个学习的好方法,减少了代码量,而且也便于扩充,大家打开Debug目录,找到settings.xml,加上一行

程序代码<Color>
  <PackedValue>1280856575</PackedValue>
</Color>

看到效果了?
    2) 构造函数 随机选择一个颜色
    3) Update 判断是否在播放消失动画,算出下一祯。
    4) Draw2DMarble 判断是否在播放动画,分别显示。被选择状态下,根据pulseFactor值轮流显示glowRing1Texture和glowRing2Texture,造成闪烁效果。
    5) Break 公开的消失方法

2. Sound.cs 声音处理

    这个类还是比较简单的,使用SoundEntry枚举出所有声音资源,用起来还是很方便的


3. Settings.cs 配置信息处理

    讲到这个,就不得不说XmlSerializer了,我也是直到现在才了解到使用类的作用 。。简单的说,可以将一个对象序列化为一个XML文档,反之,也得将这个XML文档反序列化回来。

    序列化和反序列化就分别对应了Save和Load方法了。

    对照settings.xml,这里要注意的是这个PackedValue是怎么来的,其实他是Color类的一个Properties,比如:4294901760,转化后就是{R:255 G:0 B:0 A:255}。

    highscores.xml也是一样的,就不再说了。


4. RelativeSprite.cs 画面相对表示处理

    RelativeSprite继承自SpriteBatch,Marblets游戏默认游戏窗口大小是1280X720,当改变窗口大小的时候,Resize函数就会被调用,会算出当前窗口的比例。
    然后,当使用它的Draw方法的时候,就会根据当前窗口的比例,把要绘制的东西比例表示。

    SpriteBatch类本身重载了多个Draw方法,在这里RelativeSprite只覆盖了其中一个,剩下的大家有兴趣可以点开下面的NOT IMPLEMENTED去实现吧。

5. Font.cs 文字处理

    文字的处理一直是XNA的软肋,主要是因为X360上,不存在系统字体这一说,目前比较常见的做法还是使用文字资源了图片了,像英文这种文字还好了,只有几十个字母,但中文就比较麻烦了,目前我还不知道具体的解决方案。
    目前网上有一种生成图片再加载显示的方法,我不以为然,归根结底,X360上没有字体,根据什么来生成文字图片?
    我的想法子是:
        1.让X360内置一些字体
        2.程序带一个汉字文字词典,类似矢量文字,来描述文字的信息,再像绘图一样绘出来,这样的话,还能解决缩放文字的大小的问题。

    在这个游戏里面,使用的是文字资源图片的方式,算出每个文字在资源图片的位置,和要显示的位置,再绘出来。
我的XNA学习足迹将记在这里
http://showim.net/blog/?cateID=4
jongen 离线
级别: ①新人
显示用户信息 
2  发表于: 2007-11-03   
今天我们继续来看XNA里面键盘和X360手柄按键的处理

在Marblets游戏里面,用了三个类来实现,并且实现了对四个控制器的状态检测

1. InputHelper.cs

    这个类只是公开了一个静态的GamePads类型的变量,通过Update函数不停的检测各个控制器的状态.

2. GamePads.cs

    GamePads定义了一个GamePadHelper数组,初始化的时候,就把四个(最多也就支持四个)控制器给放了进去.

    Update函数使用foreach语句来遍历并检测了各个控制器的状态,检测的方法在GamePadHelper里面实现了.


3. GamePadHelper.cs 

    首先,在这个类里面,GamePadKey枚举列出了所有在这个游戏里面使用到的按钮,包括了键盘和游戏手柄.

    再通过PlayerIndex和Dictionary分别代表了那个控制器和GamePadKey对应的键盘的按钮.

    接着Update函数里,不断的检测键盘和手柄(如果连接上了)的状态,如果游戏中使用的键没有被按下,则设置*WasReleased,*KeyWasReleased为真.
   
    最后,在这个类里面,公布了很多*Pressed的方法,通过checkPressed函数,取得该键是否被否下.

    checkPressed主有两个功能:
      1) 按钮按下之前,它的状态是Released.
      2) 保证游戏在活动状态下,这一点尤其重要,因为在PC上运行的游戏,可以通过Alt+Tab切换出去,这个时候,虽然你的游戏窗口不是活动状态,但游戏的Updata循环还在不停的检测,你不希望在你切换出去的时候,你的游戏还在听你按钮的指挥吧?
   
我的XNA学习足迹将记在这里
http://showim.net/blog/?cateID=4
jongen 离线
级别: ①新人
显示用户信息 
3  发表于: 2007-11-03   
                    今天我们来看一下Marblets的场景

Screen是这个游戏所有场景的基类,继承自DrawableGameComponent(GameComponent). 我们来看一下场景和DrawableGameComponent之间的关系.

场景我觉得可以用电视里面的一个镜头来形容,包含了背景,音乐,人物等各元素,当然其中这些元素也都是可有可无的.

DrawableGameComponent是一个资源的集合,它可以组成一个游戏中的场景,有它自己的方法和事件,比较适合封装游戏中一个独立的个体.

一个DrawableGameComponent可以是一个场景,但一个场景却不一定只是一个DrawableGameComponent,它可以是多个,通过Visible、DrawOrder、OnDrawOrderChanged
和OnVisibleChanged等方法属性,构成一个多层次,丰富效果的场景。

讨论完了DrawableGameComponent我们继续来看代码.

1.Screen.cs

    Screen.cs封装了一个基本的场景,它包括了两个必要元素:背景图和背景音乐.

    然后,通过OnVisibleChanged事件来自己的状态,来确定是否被表示或者被隐藏,并根据自己的状态来播放或停止背景音乐,以及绘图.

2.TitleScreen.cs    

    TitleScreen是我们游戏开始后看到的第一个场景,当然了,它继承自Screen,也就必须得保持它有一个背景图以及一首背景音乐.

    在它的Update函数里面,它不停的检测是否按下了A键,如果被按下,则说明游戏者有意开始玩游戏,返回GameState.Play2D回去,否则返回GameState.None,主程序接收到返回值后,再根据返回值决定是否要切换场景了.

    Draw则显示高分榜数据.

3.GameScreen.cs

    GameScreen也相对简单,把游戏的重要处理都丢给了GameBoard,自己则只是简单的显示一下分数.

    在这里我们可以看到GameBoard也是继承自DrawableGameComponent,就像我上面所说的那样,这个游戏场景是由GameScreen和GameBoard两部分组成,各司其职.

4.TutorialGameBoard.cs

    TutorialGameBoard继承自GameBoard,它主要是增加了一个方法,每隔五秒钟判断一下有没有空位,如果有的话,就在每行最后一个空位补上一个球.大家可以打开GameScreen.cs,注掉第一行看一下效果.

    大家一定很奇怪吧,还没有看到GameBoard,为什么它的子类反尔先看了呢?

    呵呵,不好意思,先道个歉,第一篇列提纲的时候,我没有认真的读代码,错误的以为这个类是实现游戏DEMO的,不过,一来这个类简单,二来游戏DEMO的思路也正和这个扩充一模一样,那我就将错就错的继承讨论下去了.

    一个好的游戏,能够让玩家在一分钟之内知道游戏的玩法(或者最起码知道基本的操作,快捷键之类的留给高手慢慢发觉吧)无疑能提高了玩家对游戏的亲近感.这也是我特别喜欢玩Popcap公司游戏的原因,这个导读完了之后,我还打算拿他们的一个游戏出来,从零开始模仿一个出来,也做为个菜鸟学习教程.
    
    知道游戏怎么玩,好的方法之一就是DEMO了,让电脑自己去玩一回,和TutorialGameBoard这个类一样,只要设置一个时间时隔,去寻找最合适的爆破位置去爆炸,这样一个简单的DEMO就完成了!
                   
[ 此贴被jongen在2007-11-04 11:17重新编辑 ]
我的XNA学习足迹将记在这里
http://showim.net/blog/?cateID=4
jongen 离线
级别: ①新人
显示用户信息 
4  发表于: 2007-11-03   
OK,今天是最后一章了,前面三章我们看到了Marblets的各组成要素,最后要做的就是整合了各种资源,形成一个完整的游戏了.

整合之前,我们是不是还要有什么东西没看到呢?

1.GameBoard.cs

    说实话,GameBoard是我看的最马虎的一个。先看它的时候,满屏的计算,感觉眼睛花,决定它留到了最后看。到了其它的类都看完之后,我也不打算去深研究它了。原因嘛,我想大家和我一样,看完了前面的,这个类是做什么的,大概也猜到了八九分了。

    我们只看一下大概几个主要的函数是做什么的吧,具体的算法,有兴趣的自己再去研究。

    首先定义了游戏区域的大小,另外该游戏也提供了鼠标玩的模式,拿掉//#define MOUSE 的注释看看效果吧。然后就是游戏的积分了。

    Update函数里面根据游戏的状态,进行了不同的处理,还记得Marble.UpdateStatic方法吗?这里弄成静态是多个球被选中时,闪烁的效果不统一。另外就是爆破之后上面球下落,重新定位选择框坐标,递归找到附近同色球的处理了。

    Draw函数中,如果没有GameOver了,则显示坐标图和分数。

    IsGameOver中则判断还没有相联的同色球,没有的话判定GameOver,保存积分,显示结束画面。


2.MarbletsGame.cs

    MarbletsGame是这个游戏的控制中心了,首先加载了游戏的配置信息,高分榜和两个游戏场景。

    Update函数里面对退出快捷键做了处理,另外增加了Alt+Enter的全屏/窗口的切换,这也是用的比较多的哦。然后检测控制器,通过ChangeGameState函数来切换场景。

    最后就是游戏结束时的资源释放了。

搞定!完了?完了,游戏场景封装好了之后,处理它们自己的事件,已经就不事情可做啦。。。

总结一下通过阅读这份代码学到的东西:
1.游戏场景(DrawableGameComponent)的运用.
2.游戏DEMO的制作思路。
3.游戏元素的封装。
4.XmlSerializer的运用。
5.键盘和X360手柄按键处理
其它还有很多,像RelativeSprite,Sound等等,总之,这次的收获真的是相当的大,相信你和我一样,开发一个2D小品游戏应该已经没什么问题了吧?

----------------------------------------------------------------------------
后记:
至此,连续五天的导读就结束了,写这篇导读的目的,还是因为国内XNA的资料真的是少的可怜,而作为一名游戏爱好者,C#爱好者,微软技术爱好者的我,希望为XNA的推广尽自己的一份力量。

写这篇导读的时候,我刚好接触XNA才两个星期的时间,难免有理解不对的地方,请大家见谅,也欢迎大家批评指正。
[ 此贴被jongen在2007-11-05 07:58重新编辑 ]
我的XNA学习足迹将记在这里
http://showim.net/blog/?cateID=4
描述
快速回复

认证码:

验证问题:
12-5=?,答案:7 正确答案:7
按"Ctrl+Enter"直接提交