收藏 分享(赏)

Silverlight.XNA(C#)跨平台3D游戏研发手记:(十一)3D SLG(策略战棋游戏)设计案例.doc

上传人:dzzj200808 文档编号:2247167 上传时间:2018-09-07 格式:DOC 页数:17 大小:1.34MB
下载 相关 举报
Silverlight.XNA(C#)跨平台3D游戏研发手记:(十一)3D SLG(策略战棋游戏)设计案例.doc_第1页
第1页 / 共17页
Silverlight.XNA(C#)跨平台3D游戏研发手记:(十一)3D SLG(策略战棋游戏)设计案例.doc_第2页
第2页 / 共17页
Silverlight.XNA(C#)跨平台3D游戏研发手记:(十一)3D SLG(策略战棋游戏)设计案例.doc_第3页
第3页 / 共17页
Silverlight.XNA(C#)跨平台3D游戏研发手记:(十一)3D SLG(策略战棋游戏)设计案例.doc_第4页
第4页 / 共17页
Silverlight.XNA(C#)跨平台3D游戏研发手记:(十一)3D SLG(策略战棋游戏)设计案例.doc_第5页
第5页 / 共17页
点击查看更多>>
资源描述

1、某天,当你一不小心发现已经够随心所欲的驾驭 3D 摄像机之时,任何类型的 3D 游戏都将成为囊中玩物,过往如烟。回忆逝去的童年让我极度惦记的 SLG 策略战棋游戏,或许对于大多数玩家来说,它费时费力不被讨好;然而深邃的内涵和无限可能的战略战术始终占据着我内心很大一片天地。于是,在本系列前5 节 2D SLG 知识原理的基础上,http:/ 萌发了移植一款基于平面的 3D SLG Demo 计划。首先,什么是基于平面的 3D SLG 游戏?大伙不妨先看看以下几款该类型经典游戏巨作截图 - 英雄无敌 6、文明 5和三国志 11:无论地形单元格为四边形或六边形,其整体地貌都不存在高低起伏(No He

2、ightMap);用游戏开发者的话说便是:三维空间中,一条轴用做旋转,http:/ 另外两条轴形成类似 2D中的 Canvs 平面承载对象。这样的设计更像是一盘 3D 化棋局,地形好比棋盘盘面,角色仿若棋子,附带一个环绕棋盘的 360轨道摄像机,无论视野还是战术方略都能得到淋漓尽致的体现。当然,除此之外,层次感更分明,基于 HeightMap 地形的立面3D SLG 游戏亦备受日系游戏青睐,不乏大作,比如火焰纹章 晓之女神、皇家骑士团:命运之轮和三国志战记 2等,该类型游戏通常需要辅以更加复杂而强大的地形编辑器,这些内容并不属于本节范畴,后续章节中若有时间再做补充:OK,做足了 SLG 游戏设

3、计方面的知识准备,接下来我们要做的头等大事便是打开 第 4 节的源码,神马差集运算、四叉树算法、蜂窝拓扑算法、A*算法等等统统一并拿来,将其中的 Point 改成Vector3(即原先的 Point(X,Y)更换成 Vector3(X,0,Y),嘿嘿,原来编码也是可以这么浮云的。举个例吧,其中的 DirectionScan方法在移植前后的对比:2D 游戏中所有我们看得到的图形都是通过 Image 图片的形式予以呈现,而到了 3D 游戏中,这条路已经行不通了。比如我们要绘制3D 四边形或 3D 蜂窝状地形单元格,此时就得自己编写基于三角面合成的 3D 面控件:Shape3D / / 3D 图形

4、(面) 基类/ public abstract class Shape3D : Object3D protected Camera3D camera;protected Texture2D texture;protected BasicEffect effect;protected short indices;protected VertexPositionTexture vertices;public Shape3D(ContentManager content, GraphicsDevice device, Camera3D camera): base(content, device) t

5、his.camera = camera;effect = new BasicEffect(device) TextureEnabled = true ;string _TextureName;/ / 获取或设置纹理资产名称/ public string TextureName get return _TextureName; set _TextureName = value;texture = content.Load(value);effect.Texture = texture;public override void Draw(GameTimerEventArgs e, ModelBat

6、ch modelBatch) effect.GraphicsDevice.BlendState = BlendState.AlphaBlend; /设置透明覆盖(透明显示纹理 alpha 透明部分)effect.World = World;effect.View = camera.View;effect.Projection = camera.Projection;effect.CurrentTechnique.Passes0.Apply();device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, ve

7、rtices.Length, indices, 0, indices.Length / 3);Rect3D / / 3D 矩形 (面) 控件/ public sealed class Rect3D : Shape3D public Rect3D(ContentManager content, GraphicsDevice device, Camera3D camera, Vector2 radius): base(content, device, camera) this.Radius = radius;Vector2 _Radius;/ / 获取或设置宽高半径/ public Vector2

8、 Radius get return _Radius; set _Radius = value;indices = new short6 /2 个三角形 4 个顶点(0,1,2,3)组成 1 个四边形0, 2, 1, 0, 3, 2;vertices = new VertexPositionTexture4;vertices0.Position = new Vector3(-value.X, 0, value.Y);vertices0.TextureCoordinate = new Vector2(0, 1);vertices1.Position = new Vector3(value.X,

9、0, value.Y);vertices1.TextureCoordinate = new Vector2(1, 1);vertices2.Position = new Vector3(value.X, 0, -value.Y);vertices2.TextureCoordinate = new Vector2(1, 0);vertices3.Position = new Vector3(-value.X, 0, -value.Y);vertices3.TextureCoordinate = new Vector2(0, 0);Hex3D / / 3D 六边形 (面) 控件/ public s

10、ealed class Hex3D : Shape3D public Hex3D(ContentManager content, GraphicsDevice device, Camera3Dcamera, int radius): base(content, device , camera) this.Radius = radius;int _Radius;/ / 获取或设置半径/ public int Radius get return _Radius; set _Radius = value;indices = new short18 /6 个三角形 18 个顶点组成 1 个四边形0,

11、1, 2, 0, 2, 3,0, 3, 4,0, 4, 5,0, 5, 6,0, 6, 1;vertices = new VertexPositionTexture6; /注意,纹理一定要边缘匹配,否则会导致残影float sqrt3 = (float)Math.Sqrt(3);vertices0.Position = new Vector3(-value, 0, 0); vertices0.TextureCoordinate = new Vector2(0, 0.5f);vertices1.Position = new Vector3(-value / 2, 0, -sqrt3 * valu

12、e / 2);vertices1.TextureCoordinate = new Vector2(0.25f, (2 - sqrt3) / 4);vertices2.Position = new Vector3(value / 2, 0, -sqrt3 * value / 2);vertices2.TextureCoordinate = new Vector2(0.75f, (2 - sqrt3) / 4);vertices3.Position = new Vector3(value, 0, 0);vertices3.TextureCoordinate = new Vector2(1, 0.5

13、f);vertices4.Position = new Vector3(value / 2, 0, sqrt3 * value / 2);vertices4.TextureCoordinate = new Vector2(0.75f, (2 + sqrt3) / 4);vertices5.Position = new Vector3(-value / 2, 0, sqrt3 * value / 2);vertices5.TextureCoordinate = new Vector2(0.25f, (2 + sqrt3) / 4);其中四边形只需 2 个三角形即可,而六边形则需由 6 个三角形组

14、合而成。接下来再赋予这些单元格以纹理,配上之前移植过来的所有算法,很酷的 3D 地形即刻呈现在我们面前(额外提醒一下,在 Draw 时必须设置纹理的 BlendState 为 Alpha 混合(basicEffect.GraphicsDevice.BlendState = BlendState.AlphaBlend;),否则这些纹理的透明部分将会被可恶的黑色所覆盖):如此漂亮的地砖 Tile,也得有能够与之相匹配的 3D 场景才算协调。话说 3D 场景与 2D 场景真是截然不同,3D 场景大多基于模型,比如刚从网上下载的一个宫殿场景,还附赠了一个天空盒呢(顺带鄙视下该天空盒,即非半球又非四方,

15、嗯,很有偷懒嫌疑):将整个模型从 3DMAX 中导出成.X 或.FBX 文件后,我们便可在游戏中直接载入,很酷吧,天圆地方,魔兽出没皇宫中:慢着,你刚才说啥来着?魔兽?拜托呀,大哥。对埃及神话中那个狗头人身的死神不清楚就算了,如今,魔兽世界中如此伟大的“阿努比萨斯”活生生的矗立在你面前,汝等依旧能保持如此之淡定,小弟不胜佩服。其实,此次 Demo 制作也印证了一个事实:魔兽世界中的模型大多还是以中低品质模型为主,奇迹的诞生并非与模型复杂度成正比。而目前市面上绝大多数的 XNA 骨骼动画模型素材管道最多仅支持 72 块骨骼解析,若想展示次世代模型还得找到更加强悍的素材管道才行(或者哪位大神帮忙写

16、个?哈哈):至此,3D SLG 游戏场景全部布置完毕,接下来是操作部分。2D 游戏基于 Canvas 平面画布,鼠标点击的地方可谓所见即所得; 3D 游戏则大为不同,无论它的显示载体是 PC 的显示屏还是Windows Phone 的触摸屏,基于二维平面的点击/触碰操作要完成三维空间的精确拾取,仿佛是件不可能的事。然而前人的智慧告诉我们,一条射线便可轻松搞定这一切,这就是传说中的“3D 射线拾取法”:通过屏幕点击位置垂直于屏幕 3D 空间向内发射射线,利用射线的穿透效果拾取一切 3D 对象。其实射线拾取法也可以通俗的理解为碰撞检测,用开发者的话说便是 Ray 是否与模型的BoundingBox

17、、BoundingSphere、BoundingFrustum 或某个 Plane 等对象存在交点:在 3D 世界里,通常为了高性能检测模型之间的碰撞,会用到Box(立方体)、Sphere(球体)或者 Frustum(锥体)包裹住模型,包裹物之间的交错关系即视为模型之间的碰撞关系。其实很多 2D 游戏也效仿了类似的做法来处理各类碰撞检测。非常幸运的是, Engine Nine 除了为我们提供强大的骨骼动画解析外,还拓展了 Model 里的 Intersects 方法,用于检测基于模型 BoundingSphere 的 Pick 操作,精确度还蛮高的,再配合上一些相关算法,最终便完成了 3D S

18、LG 游戏中的角色模型拾取和单元格命中操作:命中角色和拾取单元格处理 角色移动处理是 3D SLG 游戏制作的最后环节。设计方面通常有两种方案:第一种是由起点向终点沿寻路路径移动,这种基于 A*算法的移动在我之前的教程都讲烂掉了不再赘述;而另外的则是像英雄无敌 3那样直接做由起点向终点的直线移动(题外话,制作完 Demo 后才发现,基于六方格的地形真不适合沿路径移动,非常别扭)。后者实现方法也很简单,按照第七节开头所述原理,分割出X 和 Z 分向量速度即可:角色两种移动模式算法 List movePath = new List();float xMoveSpeed, zMoveSpeed;/

19、/ A*寻路向目的地移动/ public void MoveTo(Vector3 coordinate, byte, matrix) if (movePath.Count = 0) /movePath.Clear();PathFinderFast pathFinderFast = new PathFinderFast(matrix) TileDirectionNum = Global.TileDirectionNum,HeuristicEstimate = 2,SearchLimit = 200,;List path = pathFinderFast.FindPath(new Point() X = (int)Coordinate.X, Y = (int)Coordinate.Z ,new Point() X = (int)coordinate.X, Y = (int)coordinate.Z );if (path = null | path.Count = 0; i-) movePath.Add(new Vector3(float)pathi.X, 0, (float)pathi.Y);break;Run();嘿嘿,收工。啥?人太少不给力?那么我们刷 300 个魔兽世界里的小怪出来开心开心吧,顺便也检测下本节的各种 3D 算法是否正确:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报