所有的游戏设计辅助工具都是为了提高游戏开发效率而出现的,Silverlight-2D游戏场景编辑器(QXSceneEditor)同样也不例外,虽然它不比《魔兽》、《星际》、《帝国》等大作的地图编辑器拥有强大到甚至可以通过“换肤”直接创造出一款新游戏;但是大家可以通过它,配合上前几节讲述的游戏架设方式几乎能搭建任意一款2D游戏图形框架。无论是RPG(角色扮演)、SLG(策略)、RTS(即时战略)还是ACT(动作)、STG(射击)、CAG(卡片游戏)等游戏类型,不论精灵是2方向(如:《地下城与勇士》、《三国群英传》) 4方向(如:《漂流幻境》)还是8方向(如:《破天一剑》)甚至16方向(如:《剑侠世界》中的魔法),不论场景是横向、纵向、主视角、牵引模式,倾斜的还是垂直的,不论游戏空间是2层的(如:《梦幻诸仙》),3层的(如:《奇迹》)还是N层的(如:《英雄无敌》、《铁血联盟》)等等,只要是2D的均可用作场景的布局或架设。

场景编辑器是如何做到如此的高度通用而神乎其神的?在第二节中,我已较详细的讲解了它的核心功能:动态坐标系系统。通过动态修改场景以及它内部的地图、坐标系等对象的某些参数即可实现场景的任意倾斜度、单元格尺寸、参照系、2D位置,3D旋转以及主角在位置显示及移动方面的多模式。至于其中的核心代码我一再强调其实不过就两个,是否与第一部第十节的公式吻合大家可自行比对,事实证明它们是正确的,因此也请特别关注它的朋友们放一万个心:

/// <summary>

/// 将窗口坐标系中的坐标换算成游戏坐标系中的坐标

/// </summary>

public Point GetGameCoordinate(double angle, Point p, uint gridSize) {

if (angle == 0) {

return new Point((int)(p.X / gridSize), (int)(p.Y / gridSize));

} else {

double radian = GetRadian(angle);

return new Point(

(int)((p.Y / (2 * Math.Cos(radian)) + p.X / (2 * Math.Sin(radian))) / gridSize),

(int)((p.Y / (2 * Math.Cos(radian)) - p.X / (2 * Math.Sin(radian))) / gridSize)

);

}

}

/// <summary>

/// 将游戏坐标系中的坐标换算成窗口坐标系中的坐标

/// </summary>

public Point GetWindowCoordinate(double angle, Point p, uint gridSize) {

if (angle == 0) {

return new Point(p.X * gridSize, p.Y * gridSize);

} else {

double radian = GetRadian(angle);

return new Point(

(p.X - p.Y) * Math.Sin(radian) * gridSize,

(p.X + p.Y) * Math.Cos(radian) * gridSize

);

}

}

再回到功能上,仅有以上这些还是不够的;作为一个场景编辑器,更重要的是作为后续章节中我将为大家展示更多Demo的基础框架,它还需要拥有更好更强大的功能。

作为场景的编辑器,光能实现坐标系的变化只能算完成了一半,如能加上任意地图的导入才能算得上动态搭建:

//加载地图

button.Click += (s, e) => {

OpenFileDialog openFileDialog = new OpenFileDialog();

openFileDialog.Multiselect = false;

openFileDialog.Filter = "图象文件(*.jpg *.png)|*.jpg;*.png";

try {

bool result = (bool)openFileDialog.ShowDialog();

if (!result) {

return;

} else {

FileInfo fileInfo = openFileDialog.File;

Stream stream = fileInfo.OpenRead();

BitmapImage bitmapImage = new BitmapImage();

bitmapImage.SetSource(stream);

if (bitmapImage.PixelWidth < this.Width || bitmapImage.PixelHeight < this.Height) {

MessageBox.Show(string.Format("地图载入失败!图片规格小于窗口尺寸:{0} * {1}", this.Width, this.Height));

} else {

scene.MapSource = bitmapImage;

mapDetailsOutPut.Text = string.Format("宽:{0}px  高:{1}px", scene.MapWidth = bitmapImage.PixelWidth, scene.MapHeight = bitmapImage.PixelHeight);

}

stream.Close();

}

} catch {

MessageBox.Show("地图载入失败!请检查该图片格式是否正确");

}

};

Silverlight中,我们可以通过OpenFileDialog实现本地资源的导入;Silverlight目前版本仅能支持少数的图片格式,我们可以通过Filter进行文件类型过滤;由于图片位于本地机器,因此一旦选取图片后(bitmapImage.SetSource(stream))我们即刻便会知道图片的尺寸(bitmapImage.PixelWidth及bitmapImage.PixelHeight),这是非常重要的信息,因为当前游戏窗口的尺寸是800*580,如果地图图片的宽、高小于该数值对于游戏中地图的移动模式是无任何意义的,于是我在逻辑上还做了额外的筛选判断。

通过不同地图背景配合上相应的坐标系系统,这才叫场景搭建嘛~:

同时,场景编辑器还应该具备地形的编辑能力;因此,我还在当前版本中定义了5种最常见的地形:障碍、平地、草地、沙漠和河流:

/// <summary>

/// 地形

/// </summary>

public enum Terrains {

/// <summary>

/// 障碍

/// </summary>

Obstacle = 0,

/// <summary>

/// 平地

/// </summary>

Flat = 1,

/// <summary>

/// 草地

/// </summary>

Grassland = 2,

/// <summary>

/// 沙漠

/// </summary>

Desert = 3,

/// <summary>

/// 河流

/// </summary>

River = 4,

/// <summary>

/// 无

/// </summary>

None = 100,

}

接下来我们只需将参照系设定为“方块”,并选择相应的绘制对象,即可在地图的坐标系中通过鼠标左键绘制相应的地形:

之前有很多朋友曾提出过这样的问题:能否让主角经过不同地形时发出不同的脚步声?其实答案很简单。在第三节中我有讲到游戏基类的时空结构,为了让对象能够发声,我们得在此基础上再增加一个声音属性,即每一个继承自GameBase的类都具备有且仅有的一个“声源”。例如“游戏窗口”拥有游戏的背景音乐;“场景”负责局域环境的背景音效;“精灵”斧头挥舞的风声、受伤时的叫喊声、走路时的脚步声以及“魔法”施放时的咒语和“魔法”自身的爆破声等等,哪怕是“面板”,当我们鼠标在“面板”的按钮上点击时同样会听到清脆的点击声,它就是我们伟大的GameBase新增的一个摸不着,看不见的优秀成员sound:

/// <summary>

/// 声音

/// </summary>

MediaElement sound = new MediaElement() {

IsHitTestVisible = false,

Visibility = Visibility.Collapsed,

AutoPlay = true,

};

当游戏对象需要发出声音时,只需告诉sound,我要发声了,并设置好声音的来源即可:

/// <summary>

/// 发出声音

/// </summary>

/// <param name="uri">路径</param>

/// <param name="loop">是否循环</param>

public void MakeSound(string uri, bool loop) {

sound.Source = new Uri(string.Format(@"../Media/{0}", uri), UriKind.Relative);

sound.Position = TimeSpan.Zero;

SoundStart(loop);

}

/// <summary>

/// 开始发音

/// </summary>

public void SoundStart(bool loop) {

if (loop) { sound.MediaEnded += sound_MediaEnded; }

sound.Play();

}

赶快啦,带上您的耳机来体验吧~嘿嘿。 ^ () ^

看着“精灵”们都活蹦乱跳的,我们此时是否应该考虑让场景也动感些?于是乎我想到了《WPF/Silverlight深度解决方案》中的HLSL自定义渲染特效之完美攻略。龌龊的事情要发生啦!一不小心,我将该Demo中所有的HLSL特效复制到了场景编辑器中,嘿嘿,见证奇迹的时刻:

以前我们做的仅仅是对精灵进行渲染,当时很多朋友还看不出个端疑来;但这回换成了整个场景,喜欢回合制RPG的朋友一眼必能看出,这样的情形太像“踩地雷”时的过渡特效了:主角在地图上行走时,一旦主动或随机遇到怪物即会立刻进行场景切换,《仙剑奇侠传》、《轩辕剑》等无数经典画面此时又占据了我的思绪,感慨呀……回过神来,这仅仅不过才是6种渲染动画,如果某天您把HLSL着色语言精通了,Silverlight任意特效玩弄于股掌之间将绝非难事,大家努力加油吧!

要收尾了,应朋友们的要求,我特意将此编辑器中的“动态物体”例如“精灵”等获取图片源的方式修改为动态下载,且在下载完成前用一张图例代替呈现。完整代码如下:

static Dictionary<string, bool> downLoadImages = new Dictionary<string, bool>();

/// <summary>

/// 设置图片控件图片源(还未下载完前用图例进行设置)

/// </summary>

/// <param name="image">源图片控件</param>

/// <param name="uri">源图片路径</param>

/// <param name="legend">图例路径</param>

public void SetImage(Image image, string uri, string legend) {

if (downLoadImages.ContainsKey(uri)) {

if (!downLoadImages[uri]) {

image.Source = new BitmapImage((new Uri(string.Format(@"../SceneEditorImages/{0}", legend), UriKind.Relative))) {

CreateOptions = BitmapCreateOptions.None

};

} else {

image.Source = new BitmapImage((new Uri(string.Format(@"../SceneEditorImages/{0}", uri), UriKind.Relative))) {

CreateOptions = BitmapCreateOptions.None

};

}

} else {

BitmapImage bitmapImage = new BitmapImage((new Uri(string.Format(@"../SceneEditorImages/{0}", uri), UriKind.Relative)));

bitmapImage.ImageOpened += (s, e) => {

image.Source = s as BitmapImage;

downLoadImages[uri] = true;

};

image.Source = bitmapImage;

image.Source = new BitmapImage((new Uri(string.Format(@"../SceneEditorImages/{0}", legend), UriKind.Relative))) {

CreateOptions = BitmapCreateOptions.None

};

downLoadImages.Add(uri, false);

}

}

您没看走眼,是的,这就是全部,很简单对吧。当然,您同样也可以通过Webclient对图片素材进行按需下载,替换的相应代码如下:

WebClient webClient = new WebClient();

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

BitmapImage bitmapImage = new BitmapImage();

bitmapImage.SetSource(e.Result);

image.Source = bitmapImage;

downLoadImages[uri] = true;

};

webClient.OpenReadAsync(new Uri(string.Format(@"../SceneEditorImages/{0}", uri), UriKind.Relative), uri);

WebClient下载资源更为稳定,特别是在客户端网速不正常的情况下效果尤为显著。以上两种下载图片的方式优点很多,例如每张图片只需下载一次后即可一直使用而无需自定义缓存;另外,它特别适合我第一部教程第50节中谈到的用一张图来描述“精灵”等对象序列帧图片的下载,因为在完成整张图下载前,玩家可以看到一张图例;而一旦该图下载完成后,那么无论该对象做何动作,进行何种动画,均不会有一点闪烁或破绽,仿佛加载本地图片般流畅与完美~。当然了,由于业余时间有限,又不想再重复以前用过的素材,因而导致此场景编辑器中由N*M张图片组成的“精灵”呈现得无比“闪耀”,这是相当糟糕的事情,更多的留给大家去思考这样一个问题:基于Silverlight的网络游戏,它动态加载的素材该如何配置?

最后,还想和大家说说心里话:开源,不是哗众取宠,更不是炫耀,而是一种精神。这种精神会永远推动着你和你身边的朋友们走得更远更犀利!Silverlight在2D图形方面所展示的效果华丽而极至,随着计算机硬件的发展,如果公元2012年地球还未曾毁灭,我们一同携手去畅想Web-3D那精彩的虚幻世界~未尝不是一大幸事。

说到天花乱坠…事实胜过雄辩。该出手了,是时候展示此场景编辑器的强大了,后面的内容更精彩!一同见证吧!

在线演示地址:http://silverfuture.cn

作者: 深蓝色右手
出处: http://alamiye010.cnblogs.com/
教程目录及源码下载: 点击进入( 欢迎加入WPF/Silverlight小组 WPF/Silverlight博客团队)
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。

原文链接: http://www.cnblogs.com/alamiye010/archive/2010/03/09/1681870.html

转载于:https://my.oschina.net/chen106106/blog/43622

Silverlight游戏设计(Game Design):(六)场景编辑器之开源畅想相关推荐

  1. Silverlight游戏设计(Game Design):目录

    孩提时那无数个难眠的夜晚,时常在思考着如何干掉BOSS的方案时已不知不觉的入睡.爱游戏,痴迷到难以割舍的状态.不断的在这个虚拟的轮回世界中扮演着一个又一个的主角而无法自拔-感受着日本人给我们重温自家的 ...

  2. Silverlight游戏设计(Game Design):(十五)如果还有梦(完)

    Silverlight游戏设计系列到此就全部结束了,原先计划至少为大家献上5个最有影响力的Demo,由于近期生活及工作的原因让我感到实在疲惫不堪因而未能如愿,还望大家见谅. Silverlight在游 ...

  3. Silverlight游戏设计(Game Design):(七)创建基于场景编辑器的新游戏Demo

    场景编辑器的功能强大且灵活,从设计之初我已毫不惭愧的将其定位到"让Silverlight游戏场景架设更简单.更快捷"这样一个高度.源码公布后,很多朋友均迫切想知道如何将其运用到实际 ...

  4. Silverlight游戏设计(Game Design):(二)场景编辑器让游戏开发更美好

    如果哪天光荣告诉我:<三国志>系列将终结,我会义无返顾的用余下那点青春继续诠释这部中国历史经典题材游戏,已无法细数它占据了我多少童年的回忆,就好比曾有那么一群满腔热血的<梦幻模拟战& ...

  5. Silverlight游戏设计(Game Design):(五)面向对象的思想塑造游戏对象

    传说,面向对象的开发模式最初是因为程序员偷懒而不小心诞生的.发展至今,人们从最初的热忠于讨论某某语言是否足够面向对象到现在开始更广泛的关注面向对象的思想而不是具体内容.面向对象的思想其实并不深奥,它存 ...

  6. Silverlight游戏设计(Game Design):(四)从零开始搭建游戏主体框架

    思路已俨然清晰,接下来要做的是从零开始搭建游戏的主体框架.Silverlight作为RIA界的新宠儿,不仅在游戏开发方面性能优越,在企业开发领域的优异表现同样日益显著.像我们这些长期从事.NET开发的 ...

  7. Silverlight游戏设计(Game Design):(八)三国策(Demo) 之 “江山一统”①

    教程中无数次提到<三国>系列,那段荡气回肠的过去一直深刻烙印于心.我深爱中国的历史,因此我从不去公开评论政治,因为它是我的母亲:我执着于策略游戏,闲暇时爱不离手的依旧是NDS中的<三 ...

  8. Silverlight游戏设计(Game Design):(十)梦幻西游(Demo) 之 “天人合一”①

    与当年盛大通过代理<传奇>一举成名,九城代理<奇迹>一夜发迹完全不同,金山.网易凭借他们自主的研发团队,数年时间倾力打造了<剑侠>及<西游>等系列非常优 ...

  9. Silverlight游戏设计(Game Design):(十一)梦幻西游(Demo) 之 “天人合一”②

    无论是单机游戏还是网络游戏,丰富剧情的背后都离不开NPC默默无闻的工作:有的吆喝着卖药卖武器,有的做为宠物常拌左右,更灵活的还可以如<暗黑破坏神>那样,作为随从协助杀敌.强大的游戏离不开高 ...

  10. Silverlight游戏设计(Game Design):(一)游戏中斜视角的原理与分析

    "暗黑破坏神3"将采用45度斜视角设置这篇数月前貌似毫不起眼的新闻一直让我记忆深刻,不断的尝试去理解大师级的暗黑团队为何放弃目前主流的纯3D路线而回归到类2D,B大的一句话道破天机 ...

最新文章

  1. R语言基于可视化进行多变量离群(Mulltivariate outliers)点检测识别:散点图可视化多变量离群点、模型平滑多变量异常检测、使用平行坐标图查看钻石数据集中的异常值
  2. mysql报196271错误_微软补丁造成MYSQL及Windows经常连接失败解决方法
  3. SAP Spartacus产品明细页面用Observable显示产品名称
  4. [转]listview中设置背景图片后 拉动变黑
  5. 数据结构--链表--LRU缓存
  6. 腾讯云直播sdk_官方推荐 | 2分钟带你认识腾讯云直播 CSS
  7. pandas php,pandas分组聚合代码详解
  8. 最大比例(压轴题 )
  9. CSDN Chrome插件更新:用CSDN的方式让开发再快一点
  10. ​富士通代理4KBit I2C铁电存储器MB85RC04V
  11. 《无线通信基础》笔记
  12. 如何用html制作一个简单的网页
  13. plc编程语言有哪几种?
  14. 数据解析——Jsonpath
  15. 通过 BTC 联动程度判断牛熊
  16. 详细直播平台开发细节,提供成品直播系统源码
  17. 关于datanode进程无法启动的另一种解决方法 java.io.IOException: Incompatible clusterIDs in /export/servers/hadoop-3.1.
  18. 逐梦C++之五:string类型
  19. 共享图书系统 图书借阅小程序系统开发心得体会 共享图书系统开发
  20. Python实战——全球疫情数据采集, 并做可视化

热门文章

  1. java钝化_黑马day14 监听器之javaBean对象的活化和钝化
  2. CodeVS 1359 数字计数 51nod 1042 数字0-9的数量 Pascal
  3. 中台核心秘密:建设过程中的组织架构
  4. 中国计算机学会推荐国际学术会议和期刊(A类)2019年
  5. 顺丰全栈资源下的自动化运维灵魂
  6. oracle 11g 解决临时表空间占满问题
  7. Linux的 ls 和 ll 的使用发放、基本区别
  8. (转)TTime, TDateTime
  9. Restful API设计规范及实战
  10. 小米冲高端?差了几口气