快捷搜索:

Silverlight游戏设计:(八)三国策(Demo) 之 “江山一

教程中无数次提到《三国》系列,那段荡气回肠的以前不停深刻烙印于心。我深爱中国的历史,是以我从不去公开评论政治,由于它是我的母亲;我执着于策略游戏,空隙时爱不离手的依旧是NDS中的《三国志》。《三国策Online》作为一款RPG+战棋类策略收集游戏,其成长至今多年而青春永驻,不仅由于题材的深度及画面上憨实而幽雅的体现,更紧张的是玩家能从对战中体验到身临其境酣畅淋漓般的战争快感;战鼓声、砍杀声时常缭绕于耳,一场战役过后让我感想熏染更多的是回味,依恋着重温疆场上每一次的策略、结构、走位。从大年夜学开始便已陷溺数载,时至今日依旧无法忘记,或许很多同伙也曾和我一样做过这么一个梦:偶便是传说中那浊世的枭雄,手握宝剑 横扫千军!

没错,本节我将为大年夜家展示的便是基于QXSceneEditor(Silverlight-2D游戏场景编辑器)改动的第一个Demo:三国策。

三国策游戏类型为SRPG(策略角色扮演),游戏整体分为两部分:RPG和SLG。是以,游戏中即包孕有类似RPG游戏中的角色扮演场景;同时,一旦对战开始,画面将切换到回合制战棋结构场景。玩过该游戏或类似游戏的同伙都知道,这两类场景可谓风马不接-挨不上一点边。但这却恰是我们游戏场景编辑器的强项所在-动态参数实现随意率性类型的场景自由搭建。接下来,我将先为大年夜家解说若何制作此中的RPG部分场景。

首先要做的是按照上一节讲述的措施,将QXSceneEditor改动成新的游戏Demo项目。取三国策3个字的第一个拼音字母,我将其命名为:SgcDemo。

因为不合类型的游戏包孕的元素均不相同,就拿三国策来说,场景中有舆图、遮挡、装饰物(动画部件、传送点等)、精灵等等;是以,接下来我们要做的是从新结构项目中资本文件夹的布局与位置:

上图左侧是SgcDemo全部游戏(办理规划)的布局,游戏中所有的素材散播在两个文件夹中:SgcDemo项目中的Resource和SgcDemo.Web项目中的SgcDemoResource。第四节我已很具体的解说了这几个项目的感化与联系,Resource文件夹用于寄放游戏全局所必须的资本如设置设置设备摆设摆设信息、音效、图例、面板图片等等,经由过程将这些资本文件的属性中的“天生操作”设置为“Resource”,颠末编译后,Resource文件夹将被包装进XAP文件里的SgcDemo.dll中。于是,我们可以经由过程如下要领轻松获取其内部随意率性位置的响应资本文件:

///

/// 获取项目路径

///

internal string ProjectPath(string path) {

return string.Format(@"/SgcDemo;component/Resource/{0}", path);

}

SgcDemoResource文件夹处于SgcDemo.Web网站项目中,它主要用于寄放游戏动态按需下载的资本如舆图背景、背景音乐、精灵图片、邪术图片、殊效装饰、头像图片等等,经由过程将它们的属性中的“天生操作”设置为“内容”,当Silverlight游戏制作完成后必要宣布时,我们可以经由过程点击SgcDemo.Web项目,选择VS2008菜单中的天生->宣布SgcDemo.Web即可将包孕XAP及SgcDemoResource的Silverlight游戏网站编译并宣布到指定位置。同样的,我们可以经由过程如下措施获取SgcDemoResource文件夹路径:

///

/// 获取Web相对路径

///

internal string WebPath(string path) {

return string.Format(@"../SgcDemoResource/{0}", path);

}

第六节中,我曾有讲到若何动态下载网站中的素材等资本,不知道有同伙是否测试过,该措施存在着一个很大年夜的缺陷:因为Image控件被引用而导致下载获取的图片占用的内存无法开释,对付单舆图的小游戏来说影响不大年夜,然则假如是用在制作RPG游戏方面无疑是一大年夜祸害:每切换一次场景(舆图)将导致内存莫名其妙的膨胀,必将严重影响游戏的机能及玩家体验。办理法子便是将该措施封装成一个承袭自StaticObject名为Downloader的类,在其内部定义Completed事故;当webClient.OpenReadCompleted时触发该事故。Downloader的完备代码如下:

///

/// Web资本下载者

///

public class Downloader : StaticObject {

///

/// 已下载的文件路径列表

///

static Liststring> files = new Liststring>();

public event EventHandler Completed;

///

/// 经由过程WebClient下载图片

///

public void GetImage(string uri) {

if (files.Contains(uri)) {

if (Completed != null) { Completed(files, new EventArgs()); }

} else {

WebClient webClient = new WebClient();

webClient.OpenReadCompleted += (s, e) => {

BitmapImage bitmapImage = new BitmapImage();

bitmapImage.SetSource(e.Result);

files.Add(uri);

if (Completed != null) { Completed(files, new EventArgs()); }

};

webClient.OpenReadAsync(new Uri(WebPath(uri), UriKind.Relative), uri);

};

}

}

应用措施同样也很简单,以场景(Scene)中动态下载舆图背景为例,我们只需几行代码即可实现场景首先装载Stretch.Fill的缩略图,一旦舆图原图下载完成后即调换显示:

//下载背景图片

map.Source = GetProjectImage(string.Format("Images/Map/{0}/Thumbnail.jpg", Code));

map.Stretch = Stretch.Fill;

string mapUri = string.Format("Images/Map/{0}/Background.jpg", Code);

Downloader downloader = new Downloader();

downloader.Completed += (s, e) => {

map.Source = GetWebImage(mapUri);

map.Stretch = Stretch.None;

};

downloader.GetImage(mapUri);

到此,游戏资本的设置设置设备摆设摆设及获取措施就整个搞定了。接下来,我要重点解说场景编辑器和Demo中我是若何对游戏场景、精灵、装饰物等工具的信息进行储存、读取及处置惩罚的。

我们首先找到SgcDemo项目中Resource目录下的Config目录,此中包孕3个xml数据存储文件:Scene.xml、Sprite.xml和Decoration.xml。

打开Scene.xml,以Code=0的场景设置设置设备摆设摆设为例,其数据信息如下:

Scene Code="0">

舆图-->

Map Name="荷花池" Width="1440" Height="1080" CanScroll="False" ScrollSpeed ="10" MatrixSize="32" GridSize="40" Gradient="63.4" ReferenceStyle="0" OffsetX="861" OffsetY="25" RotationX="0" CenterOfRotationX="0" RotationY="0" CenterOfRotationY="0" RotationZ="0" CenterOfRotationZ="0" Music="0" Teleport="7_6_0,7_7_0" Terrain="0_16_0,0_17_0,0_18_0,0_19_0,0_20_0,1_16_0,1_20_0,2_16_0,2_20_0,3_4_0,3_5_0,3_6_0,3_7_0,3_8_0,3_9_0,3_10_0,3_11_0,3_12_0,3_13_0,3_14_0,3_15_0,3_16_0,3_20_0,4_4_0,4_20_0,5_4_0,5_20_0,6_4_0,6_20_0,7_4_0,7_10_0,7_11_0,7_12_0,7_13_0,7_14_0,7_15_0,7_16_0,7_20_0,8_4_0,8_10_0,8_16_0,8_20_0,9_4_0,9_10_0,9_16_0,9_20_0,10_4_0,10_5_0,10_6_0,10_10_0,10_16_0,10_20_0,11_6_0,11_10_0,11_16_0,11_20_0,12_6_0,12_10_0,12_16_0,12_20_0,13_6_0,13_10_0,13_16_0,13_20_0,14_6_0,14_10_0,14_15_0,14_16_0,14_20_0,15_6_0,15_10_0,15_14_0,15_15_0,15_20_0,16_6_0,16_10_0,16_11_0,16_12_0,16_13_0,16_14_0,16_19_0,16_20_0,17_6_0,17_18_0,17_19_0,18_6_0,18_17_0,18_18_0,19_6_0,19_16_0,19_17_0,20_6_0,20_7_0,20_8_0,20_9_0,20_10_0,20_11_0,20_12_0,20_13_0,20_14_0,20_15_0,20_16_0,"/>

遮挡-->

Masks>

Mask Code="0" Opacity="0.6" X="969" Y="244" Z="16"/>

Mask Code="1" Opacity="0.6" X="926" Y="470" Z="100"/>

Mask Code="2" Opacity="0.6" X="581" Y="556" Z="100"/>

Mask Code="3" Opacity="0.6" X="155" Y="320" Z="100"/>

Mask Code="4" Opacity="0.6" X="743" Y="271" Z="27"/>

Mask Code="5" Opacity="0.6" X="505" Y="290" Z="24"/>

Masks>

动画部件-->

Animations>

Animation Code="1" Opacity="0.6" X="472" Y="0" Z="0"/>

Animations>

传送点(ID用于匹配传送二维数组,Code用于匹配Decoration.xml)-->

Teleports>

Teleport ID="0" Code="0" X="865" Y="285" Z="14" ToScene="1" ToX="70" ToY="68" ToDirection="1" Tip="大年夜风山"/>

Teleports>

精灵-->

Sprites>

Sprite Code="2" X="4" Y="6" Direction="1"/>

Sprite Code="1" X="10" Y="7" Direction="1"/>

Sprite Code="2" X="1" Y="17" Direction="2"/>

Sprite Code="3" X="2" Y="18" Direction="3"/>

Sprite Code="4" X="11" Y="19" Direction="4"/>

Sprite Code="3" X="14" Y="19" Direction="5"/>

Sprite Code="2" X="16" Y="17" Direction="6"/>

Sprite Code="0" X="19" Y="10" Direction="3"/>

Sprites>

Scene>

Map节点中的属性大年夜家应该异常认识,是的,它们便是场景编辑器所能改动的响应参数。以制作三国策场景为例,我们首先点击“载入舆图”将游戏实际舆图图片导入到编辑器中,然后对比着舆图分手对矩阵尺寸、倾斜度、X,Y偏移、地形等进行响应设置,当你感到全部场景已能与舆图背景完美吻合了,我们即可经由过程点击“导出场景信息”将此设置设置设备摆设摆设好的场景参数输出为xml文件,该文件中即包孕了上述Map节点:

必要弥补阐明一下,常常有同伙会问我为什么要应用罗列?彷佛为每个罗列附加一个数值是画蛇添足?罗列又是若何与xml进行交互的?

以enum ReferenceStyles为例,它的定义如下:

///

/// 场景参照物样式

///

public enum ReferenceStyles {

None = 0,

Grid = 1,

Box = 2,

}

在Map节点中,我们只需将ReferenceStyle = 响应的数字(例如我要设置参照系为方块则取2)即可得到该数字对应的ReferenceStyles类型。以ReferenceStyle = 1为例,在cs中,我们只需经由过程ReferenceStyle = (ReferenceStyles)((int)xScene.Attribute("ReferenceStyle"));即可将该值取得并转换成代码中的罗列类型值,全部历程大年夜致便是这样。当然,为罗列值附加数字还有加倍奇妙的利用,下一节我再为大年夜家解说具体细节。

回到scene.xml,此中Masks节点记录的是场景中所有遮挡物位置等信息,每个遮挡物的位置我们必要共同Photoshop进行定位。打开Photoshop,载入舆图,接着将遮挡物放到对应吻合的位置上,按Ctrl+R将标尺显示出来,拖动纵、横参考线分手贴住该遮挡物的最左边及最高点,此时标尺上显示的像素值即为该遮挡物的X、Y值:

遮挡物还有个紧张的Z值,用于实现它与周围精灵之间的层次遮挡关系,即2D中的伪3维效果。而这个Z值我们可以经由过程将精灵移动到它的最底端,此时精灵的X+Y值即为该遮挡物的Z值。当然,这是斜度舆图中Z值最简单的算法,还有更正确的有光阴我会与大年夜家继承探究:

Animations节点中记录的是该场景中的所有动画图,如瀑布等的位置;Teleports节点则记录的是场景中所有的传送点位置。Animation与Teleport同属于带动画的装饰物,经由过程它们的Code属性,类似数据库中的inner join内联到Decoration.xml数据文件,该文件中包孕有该代号为Code的装饰物的具体数据,类似:

装饰物-->

Decorations>

Decoration Code="0" Format="1" Width="960" Height="181" CenterX="60" CenterY="140" FrameNum="8" Interval="150"/>

Decoration Code="1" Format="0" Width="1620" Height="248" CenterX="0" CenterY="0" FrameNum="9" Interval="150"/>

Decoration Code="2" Format="0" Width="3780" Height="600" CenterX="0" CenterY="0" FrameNum="9" Interval="150"/>

Decorations>

Sprites节点与上面的装饰物类似,包孕的是场景中所有非玩家精灵所处的位置、朝向等信息,同样的经由过程它们的Code属性内联到Sprite.xml精灵动画图象数据文件:

精灵-->

Sprites>

Sprite Code="0" FullName="大年夜乔" Width="160" Height="140" Speed="280" MoveMode="1" BodyCenter="80,120" IconCenter="21,78" Frames="200, 6, 6, -1, 100, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1"/>

Sprite Code="1" FullName="孙尚喷鼻" Width="72" Height="104" Speed="280" MoveMode="1" BodyCenter="33,86" IconCenter="21,78" Frames="200, 6, 6, -1, 100, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1"/>

Sprite Code="2" FullName="深蓝色右手" Width="72" Height="104" Speed="280" MoveMode="1" BodyCenter="33,86" IconCenter="21,78" Frames="200, 6, 6, -1, 100, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1"/>

Sprite Code="3" FullName="貂禅" Width="102" Height="136" Speed="280" MoveMode="1" BodyCenter="45,102" IconCenter="21,78" Frames="200, 6, 6, -1, 100, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1"/>

Sprite Code="4" FullName="小乔" Width="128" Height="160" Speed="280" MoveMode="0" BodyCenter="61,126" IconCenter="21,78" Frames="200, 6, 6, -1, 100, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1"/>

Sprites>

全部场景中暂时就放这么些器械了。当然,仅有设置设置设备摆设摆设照样不可的,我们还得进行响应的数据读取,暂时照样选择应用LINQ TO XML吧,由于简单,以是我爱。

我们首先必要在项目中添加对System.Xml.Linq的引用,同时在cs中using System.Linq;和using System.Xml.Linq;

接下来我们经由过程如下措施加载Xml文件:

///

/// 加载XML文件

///

///

XML文件地址

/// XElement

public XElement LoadXML(string uri) {

return XElement.Load(ProjectPath(string.Format("Config/{0}", uri)));

}

以载入scene.xml文件读取Code=0场景数据信息为例,我们可以经由过程如下措施进行操作:

XElement xScene = LoadXML("Scene.xml").DescendantsAndSelf("Scene").Single(X => X.Attribute("Code").Value == "0");

XElement xMap = xScene.Element("Map");

//设置响应参数

MapName = xMap.Attribute("Name").Value.ToString();

MapWidth = (double)xMap.Attribute("Width");

MapHeight = (double)xMap.Attribute("Height");

……

总的来说,有了这些设置设置设备摆设摆设文件,经由过程对如场景、精灵这些类进行Code属性封装,在切换场景时我们仅仅要做的是奉告游戏我要到哪个场景了scene.Code = code,游戏即刻会切换到该新场景,所有的素材下载、精灵加载、内存开释等等均无须我们再多敲一个代码,scene内部帮我们搞定了所有的统统。照样那句老话,游戏开拓着实是可以很简单的,看你的游戏架构是否足够机动了~

更多无足轻重的细节就不多说了,源码中都有大年夜家可以对比着看。终极所有Control类的关系图如下:

以下为实际场景截图,效果可完美匹敌《三国策Online》~ 嘿嘿:

至此,我们完成了基于QXSceneEditor改制而成的新游戏Demo – 三国策RPG场景(SgcDemo)的搭建,累计统共花费了我4天的业余光阴,10余个小时吧,包括所有素材的处置惩罚等。这里想奉告大年夜家的是,着实我已经将代码进行了高度的精练,写的每一行都有它存在的意义,基于场景编辑器去搭建任何2D游戏场景都是一件轻而易举的工作。更多的,我盼望大年夜家能去理解每一个措施的感化,能做到机动运用且触类旁通,那么游戏开拓着实不过而已。

下一节,我会继承解说若何搭建三国策SLG部分场景,RPG都做烂了~来点战棋的吧,敬请关注。

源码暂时到这下载:SgcDemo.rar

转自:http://www.cnblogs.com/alamiye010/archive/2010/03/18/1689170.html

您可能还会对下面的文章感兴趣: