热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

与当年盛大通过代理《传奇》一举成名,九城代理《奇迹》一夜发迹完全不同,金山、网易凭借他们自主的研发团队,数年时间倾力打造了《剑侠》及《西游》等系列非常优秀的纯国产网游,不仅开创了此领域的先河,且作为中

与当年盛大通过代理《传奇》一举成名,九城代理《奇迹》一夜发迹完全不同,金山、网易凭借他们自主的研发团队,数年时间倾力打造了《剑侠》及《西游》等系列非常优秀的纯国产网游,不仅开创了此领域的先河,且作为中国网游行业的榜样,让我时常感到崇敬与骄傲。西山居、烈火、大话西游等工作室这些如雷贯耳的称号已家喻户晓,所有成功的背后都有着一段源自对中国古风古韵故事的生动阐述,事实也证明了神化传说终是游戏设计中永不褪色的主题。

让经典重现是无比让人神往的体验。本节,我将以制作《梦幻西游》Demo为例,继续向大家讲解并演示如何通过Silverlight-2D场景编辑器搭建出结构更复杂的游戏场景。

与前两节不同,由于《梦幻西游》与《三国策》同属回合制RPG游戏类型,因此我们首先要做的是直接按照第七节的方法,但是使用基于第八节《三国策》Demo源码之上而直接修改出来新的Demo,并取名为MhxyDemo

精致的网络游戏中精灵应该具备多部件纸娃娃系统,梦幻西游中的角色也不例外。在此Demo中,我以原始素材为依据,同样将玩家角色精灵分成身体、武器、坐骑、影子等4个部分:

此时大家或许会有些疑惑,组合后的图似乎与这些分开的素材并不吻合?是的,上图中的武器、身体图片均为精灵在无坐骑状态时的素材;而当精灵由“步行”变换为“骑乘”状态后,武器、身体的素材又会更换成另一套,这里涉及到各部分素材该如何合理布局这样一个问题。寻找相应解决方案,我们得从游戏的整体设计出发。精灵是游戏中的主角,以精灵为本,在回合制RPG游戏中,精灵拥有3种不同的显示模式:步行模式、骑乘模式及战斗模式,在这3种模式下精灵的姿势及武器的位置等均不相同:

如上图,3张均为同一角色东朝向移动时的第二帧图片,显然是截然相同的。因此,为了逻辑代码上的便利,我们必须通过对这些素材进行类似如下布局方能轻松实现灵活的素材文件加载:

至于这些素材该怎样组合,方案也是多种多样的。最简单的方案就是通过直接叠加的方式,此方式不需耗费像素合成,工作量也小,然而缺点同样明显,素材尺寸一致将导致总体容量很大。传统游戏的做法是通过配置或表头文件为每张图片定义好它的偏移量,每次调用时进行相应偏移或定点截取即可:

唯一麻烦之处是需要前期大量的美工处理及布局调整。总体来说,多部件纸娃娃系统可以大幅提升游戏的趣味性,深度套劳玩家那颗对“角色Show”痴迷的心;当然,成功的背后一切都离不开良好的游戏结构设定与布局。

素材方面就讲到这。梦幻西游除了拥有优秀的角色设定外,在场景上同样也很卓越。在本节的Demo中,我以原形为基础搭建出了传说中的2.8D斜视角双背景层次结构:

    底层为云彩,包含于Window窗口容器中,可固定不动或朝主角相反的方向1/10左右速度相对移动;表层则是正常的地图背景,主位式镜头跟随主角相对移动。通过此方式对场景进行分层处理可以实现华丽的2.8D效果,玩家在游戏中将亲历置身于天空之城般神奇的体验。而若在此基础上,将双背景换成双场景,那么《梦幻诸仙》的飞空系统不同样可以轻易实现?嘿嘿,又一次的印证了基于场景的游戏架构定能让游戏开发更加简单。

同时,在本节的Demo中我还添加了第一部教程第三十七节中的讲到的地图切片及按需加载技术,此方案能大幅提升游戏的流畅性且降低服务器端负荷。这里还是想再次感谢goods,在他提供的9切片地图加载算法基础上,我将之再次升级为动态下载模式,核心代码如下:

        Point2D _sectionCenter;

        ///

        /// 获取或设置地图切片中心

        ///

        public Point2D sectionCenter {

            get { return _sectionCenter; }

            set {

                if (!_sectionCenter.Equals(value)) {

                    ChangeMapSection(_sectiOnCenter= value);

                }

            }

        }

 

        ///

        /// 更新呈现的地图切片

        ///

        /// 引导场景地图变换的精灵主角所处的窗口切片坐标

        private void ChangeMapSection(Point2D leaderSection) {

            int startSectionX, startSectionY, endSectionX, endSectionY;

            //根据主角当前位置来加载周边地图切片

            if (leaderSection.X == 0) {

                startSectiOnX= 0; endSectiOnX= 2;

            } else if (leaderSection.X == SectionXNum - 1) {

                startSectiOnX= leaderSection.X - 2; endSectiOnX= leaderSection.X;

            } else {

                startSectiOnX= leaderSection.X - 1; endSectiOnX= leaderSection.X + 1;

            }

            if (leaderSection.Y == 0) {

                startSectiOnY= 0; endSectiOnY= 2;

            } else if (leaderSection.Y == SectionYNum - 1) {

                startSectiOnY= leaderSection.Y - 2; endSectiOnY= leaderSection.Y;

            } else {

                startSectiOnY= leaderSection.Y - 1; endSectiOnY= leaderSection.Y + 1;

            }

            int index = 0;

            //取回已经超出主角周围9块范围的切片(x,y初始-1,第一次加载9)

            tempSection[] tempSectiOnList= sectionList.Where(c => c.x endSectionX || c.y endSectionY).ToArray();

            for (int x = startSectionX; x <= endSectionX; x++) {

                for (int y = startSectionY; y <= endSectionY; y++) {

                    //9点位中假如已经有该点位的切片在则检查下一个

                    if (sectionList.Where(c => c.x == x && c.y == y).Count() > 0) {

                        continue;

                    } else {

                        //将超出范围的切片填充到新的位置上,并重置它们的x,y点位坐标值

                        tempSectionList[index].x = x;

                        tempSectionList[index].y = y;

                        mapSection[tempSectionList[index].sectionNo].Source = GetProjectImage(string.Format("Images/MiniMap/{0}/Surface/{1}_{2}{3}", this.Code, x, y, FileType(MapFormat)));

                        //下载实际图片

                        Downloader downloader = new Downloader() {

                            Args = string.Format("{0},{1},{2}", index, x, y)

                        };

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

                            Downloader loader = s as Downloader;

                            string[] args = loader.Args.Split(',');

                            int tempIndex = Convert.ToInt32(args[0]), tempX = Convert.ToInt32(args[1]), tempY = Convert.ToInt32(args[2]);

                            if (tempSectionList[tempIndex].x == tempX && tempSectionList[tempIndex].y == tempY) {

                                mapSection[tempSectionList[tempIndex].sectionNo].Source = GetWebImage(string.Format("Images/Map/{0}/Surface/{1}_{2}{3}", this.Code, tempX, tempY, FileType(MapFormat)));

                            }

                        };

                        downloader.GetImage(WebPath(string.Format("Images/Map/{0}/Surface/{1}_{2}{3}", this.Code, x, y, FileType(MapFormat))));

                        Canvas.SetLeft(mapSection[tempSectionList[index].sectionNo], x * SectionWidth);

                        Canvas.SetTop(mapSection[tempSectionList[index].sectionNo], y * SectionHeight);

                        index++;

                    }

                }

            }

        }

另外,整张地图包含有3个景点,景点之间均是相互隔离的。在未修改任何上一节传送部分代码的基础上,我们只需配置xml文件中传送点传送到的坐标及ToScene等于当前场景代号,即可实现同场景不同位置间的传送(瞬移也是类似原理,封装好的传送代码为我们提供了相当大的便利):

    

    <Teleports>

      <Teleport ID="0" Code="0" X="2820" Y="2040" Z="184" ToScene="0" ToX="105" ToY="49" ToDirection="2" Tip="传送到:比武场"/>

      <Teleport ID="1" Code="0" X="2455" Y="1680" Z="164" ToScene="0" ToX="57" ToY="95" ToDirection="6" Tip="传送到:武门殿"/>

      <Teleport ID="2" Code="0" X="4270" Y="1530" Z="156" ToScene="0" ToX="99" ToY="83" ToDirection="2" Tip="传送到:空中亭阁"/>

      <Teleport ID="3" Code="0" X="835" Y="1510" Z="154" ToScene="0" ToX="88" ToY="79" ToDirection="0" Tip="传送到:空中亭阁"/>

    Teleports>

    再复杂的游戏设计也离不开最普通的游戏架构基础,光有强大的场景仍然无法支撑游戏的完美表述;因此,下一节我会在此Demo的基础上进一步丰富游戏,赋予游戏更多的生命与灵气。赶快加入到Silverlight游戏开发的行列中来吧,世界将因你而变得更精彩!

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

源码请到目录中下载

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

 


推荐阅读
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • Spring – Bean Life Cycle
    Spring – Bean Life Cycle ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • Ext JS MVC系列一:环境搭建与框架概览
    本文主要介绍了如何在项目中使用Ext JS 4作为前端框架,并详细讲解了Ext JS 4的MVC开发模式。文章将从项目目录结构、相关CSS和JS文件的引用以及MVC框架的整体认识三个方面进行总结。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 详解 Qt 串口通信程序全程图文 (4)
    Qt串口通信程序全程图文是本文介绍的内容,本文一开始先讲解对程序的改进,在文章最后将要讲解一些重要问题。1、在窗口中加入一些组合框ComboBox&# ... [详细]
  • 如何在Linux服务器上配置MySQL和Tomcat的开机自动启动
    在Linux服务器上部署Web项目时,通常需要确保MySQL和Tomcat服务能够随系统启动而自动运行。本文将详细介绍如何在Linux环境中配置MySQL和Tomcat的开机自启动,以确保服务的稳定性和可靠性。通过合理的配置,可以有效避免因服务未启动而导致的项目故障。 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • PTArchiver工作原理详解与应用分析
    PTArchiver工作原理及其应用分析本文详细解析了PTArchiver的工作机制,探讨了其在数据归档和管理中的应用。PTArchiver通过高效的压缩算法和灵活的存储策略,实现了对大规模数据的高效管理和长期保存。文章还介绍了其在企业级数据备份、历史数据迁移等场景中的实际应用案例,为用户提供了实用的操作建议和技术支持。 ... [详细]
  • 本文详细解析了 Yii2 框架中视图和布局的各种函数,并综述了它们在实际开发中的应用场景。通过深入探讨每个函数的功能和用法,为开发者提供了全面的参考,帮助他们在项目中更高效地利用这些工具。 ... [详细]
author-avatar
Aovte
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有