- 浏览: 432494 次
文章分类
最新评论
《游戏脚本的设计与开发》-(战棋部分)第七章 快速显示一张战场地图
今天开始脚本设计的第二部分,战棋游戏的开发。战棋游戏中我尤其喜爱光荣的英杰传和曹操传,我的多平台游戏三国记,也是以三国志曹操传为模板而开发的。本次也不例外,就从曹操传的移植为基础来开发,再进行扩展,从而实现自己的战棋游戏的开发。熟悉曹操传的朋友们都知道,曹操传分为R剧情部分和S战场部分,R剧情部分是以讲故事的形式展开的,好的游戏离不开好的剧情,所以我认为R剧情在游戏中是非常重要的。当然,也有很多玩家不喜欢过多的剧情,喜欢跳过剧情,进入S战场,直接开始战斗。这也算是这类游戏的多样性中的一个吧。
制作开始,战场地图显示
在L#脚本中,战棋游戏的脚本都以SouSou开头,为什么是SouSou呢?因为SouSou是“曹操”的在日语中的日语发音,既然以曹操传为模板,我就继续以SouSou来作为本类脚本的特征了。本次开发就先从S战场开始,L#脚本中,S战场的初期化是以下面的脚本来开始和结束的
SouSouSMap.start(); SouSouSMap.end();
首先建立一个LScriptSLGSouSou类来管理战棋脚本。
/* * LScriptSLGSouSou.js **/ var LScriptSLGSouSou = function (){}; LScriptSLGSouSou.analysis = function (childType, lineValue){ var start,end,params; switch(childType){ case "SouSouSMap": start = lineValue.indexOf("("); end = lineValue.indexOf(")"); params = lineValue.substring(start + 1,end).split(","); if(params.length == 0 || parseInt(params[0]) <= 0){ //敌军等级非固定设定 暂略 }else{ //敌军等级固定设定 暂略 } var sMap = new LSouSouSMap(); break; default: LGlobal.script.analysis(); } };
其实脚本SouSouSMap.start();是可以有参数的,来设定一些必要的参数,比如上面的敌军等级是否固定。暂时就先略过了,等后面再详细讲解。
上面的代码中可以看到,当遇到SouSouSMap脚本的时候,会实例化一个LSouSouSMap对象,LSouSouSMap是一个战场的总类,里面包括战场上的地图,军队,天气等等。
作为引擎来说,我开发的所有js文件最后都会合成到一个文件中的,但是开发这么一个大型的项目开发,在开发过程中,必须要将代码妥善的管理。建立以下文件夹src/sousou/map/s,然后在s文件夹内,新建下面三个文件。
LSouSouSMap.js
LSouSouSMapBackground.js
LSouSouSMapMiniView.js
先试着来读取一个S战场地图文件,一个完整的S战场地图文件,包含地图的图片和地图的地形属性,我先来新建一个s01.smap文件作为一个S战场地图文件,里面的内容为
{"data":[ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ] ,"img-small":"01-small.png" ,"img-big":"01-big.png"}
这个文件中包含三个属性,地形,地图缩略图,地图完整图。我先将战场的地形全都统一设置成0,以后再进行扩展。
游戏中的战场地图通常是很大的,而大多数网友们的网速又是相对来说比较慢的,如果等整个图片读取完之后再显示,那么就要花相对长的时间进行等待。如何来快速显示地图进入战斗呢?既然地图文件中包含有缩略图和完整图,那么我们可以先读取缩略图,在缩略图读取完成后先把缩略图显示出来,直接进入战场,这时候的战场是模糊的,待完整图读取完成后再把缩略图替换掉,变成漂亮的战场。
其实对于网页游戏来说,进入到游戏的时间长短是很重要的,如果读取游戏时间过长,玩家可能就会大量流失,所以一般我们只读取当前页面所需要的图片或数据,剩余的部分在游戏过程中再一步步读取。
先来看看LSouSouSMap.js类的构造器部分
function LSouSouSMap(){ var self = this; base(self,LSprite,[]); LSouSouObject.sMap = self; self._objectData = null; self._loadBar = null; self._mapData = null; self.mapW = 0; self.mapH = 0; self._mapLayer = new LSprite(); self.addChild(self._mapLayer); LGlobal.script.scriptLayer.addChild(self); LSouSouSMapScript.analysis(); }
其中的LSouSouObject是战棋游戏的共通类,包含一些共通的函数和属性。实例化结束后,再进行下一步解析LSouSouSMapScript.analysis();
SouSouSMap.start();进行战场初期化,实例化包含有地图初期化,军队初期化,天气初期化,战场事件初期化等多种实例化,今天讲地图显示,就先来进行地图初期化。地图初期化脚本是在下面的脚本之间
initialization.start; initialization.end;
读取战场地图如下
initialization.start; addMap(s01.smap); initialization.end;
LSouSouSMapScript类,用来解析战场初期化脚本,代码如下
/* * LSouSouSMapScript.js **/ LSouSouSMapScript = function(){}; LSouSouSMapScript.analysis=function(){ var script = LGlobal.script; if(script.lineList.length == 0)return; var lineValue = LMath.trim(script.lineList.shift()); if(lineValue.length == 0){ LSouSouSMapScript.analysis(); return; } trace("LSouSouSMapScript analysis lineValue = " + lineValue); switch(lineValue){ case "SouSouSMap.end()": //暂略 return; case "initialization.start": LSouSouSMapScript.initialization(); break; default: LSouSouSMapScript.analysis(); } }; LSouSouSMapScript.initialization=function(){ var script = LGlobal.script; var lineValue = LMath.trim(script.lineList.shift()); trace("script.lineList = " + script.lineList); if(lineValue.length == 0){ LSouSouSMapScript.initialization(); return; } if(lineValue == "initialization.end"){ LSouSouSMapScript.analysis(); return; } var params,i; var start = lineValue.indexOf("("); var end = lineValue.indexOf(")"); switch(lineValue.substr(0,start)){ case "addMap": LSouSouObject.sMap.addMap(lineValue.substring(start+1,end).split(",")); break; default: LSouSouSMapScript.initialization(); } };
当然,LSouSouSMapScript处理的内容不仅仅有这些,后面会继续进行扩展,可以看到当遇到addMap脚本的时候,会调用LSouSouSMap类的addMap函数。前面我说了,要想快速显示地图,先显示缩率图,然后再进行替换。具体实现过程如下。
/** * 读取地图 * param [地图名] **/ LSouSouSMap.prototype.addMap = function(param){ var self = this; var smapName = "images/smap/" + param; //显示读取进度 self._loadBar = new LoadingSample3(); self.addChild(self._loadBar); //开始读取战场地图文件 var urlloader = new LURLLoader(); urlloader.parent = self; urlloader.addEventListener(LEvent.COMPLETE,self.loadMapFileOver); urlloader.load(smapName+(LGlobal.traceDebug?("?"+(new Date()).getTime()):""),"text"); }; LSouSouSMap.prototype.loadMapFileOver = function(event){ var self = event.target.parent; //保存战场地图文件内容 self._objectData = JSON.parse(event.target.data); //保存地形 self._mapData = self._objectData.data; //描绘进度条 self._loadBar.setProgress(50); //获取战场大小 self.mapW = self._mapData[0].length*48; self.mapH = self._mapData.length*48; //开始读取战场缩略图 loader = new LLoader(); loader.parent = self; loader.addEventListener(LEvent.COMPLETE,self.loadMapSmallOver); loader.load("images/smap/imgs/" + self._objectData["img-small"]+(LGlobal.traceDebug?("?"+(new Date()).getTime()):""),"bitmapData"); }; LSouSouSMap.prototype.loadMapSmallOver = function(event){ var self = event.target.parent; //移除进度条 self.removeChild(self._loadBar); var bitmapData = new LBitmapData(event.currentTarget); //计算缩略图和完整图的比例 var scale = self.mapW/bitmapData.width; //将缩略图作为战场背景地图进行显示 self._map = new LSouSouSMapBackground(); self._map.setSmall(bitmapData,scale); self._mapLayer.addChild(self._map); //显示战场缩略图 self._miniWindow = new LSouSouSMapMiniView(bitmapData); self._mapLayer.addChild(self._miniWindow); //开始读取战场完整图 loader = new LLoader(); loader.parent = self; loader.addEventListener(LEvent.COMPLETE,self.loadMapBigOver); loader.load("images/smap/imgs/" + self._objectData["img-big"]+(LGlobal.traceDebug?("?"+(new Date()).getTime()):""),"bitmapData"); }; LSouSouSMap.prototype.loadMapBigOver = function(event){ var self = event.target.parent; self.removeChild(self._loadBar); var bitmapData = new LBitmapData(event.currentTarget); //战场完整图读取完成,替换战场地图 self._map.setBig(bitmapData); trace("loadMapBigOver"); };
其中的战场地图类LSouSouSMapBackground如下
function LSouSouSMapBackground(){ var self = this; base(self,LSprite,[]); } LSouSouSMapBackground.prototype.setSmall = function(bitmapData,scale){ var self = this; self.map = new LBitmap(bitmapData); self.map.scaleX = self.map.scaleY = scale; self.addChild(self.map); }; LSouSouSMapBackground.prototype.setBig = function(bitmapData){ var self = this; self.map.bitmapData = bitmapData; self.map.scaleX = self.map.scaleY = 1; };
战场预览类LSouSouSMapMiniView如下
function LSouSouSMapMiniView(bitmapData){ var self = this; base(self,LSprite,[]); self._miniMap = new LBitmap(bitmapData); self._miniMap.x = self._miniMap.y = 15; self.addChild(self._miniMap); self._miniBar = LSouSouObject.getBar(self._miniMap.getWidth()+30,self._miniMap.getHeight()+30); self.addChild(self._miniBar); }
其中的LSouSouObject.getBar函数是获取一个矩形边框,首先准备下面一组边框
LSouSouObject.getBar函数将上面的图片进行组合,返回需要大小的矩形边框,具体代码如下。
LSouSouObject.getBar=function(w,h){ var barWidth = 500,barHeight = 380; var img,bar = new LSprite(); if(w > 530){ for(var i=15;i<15+(w-530)*0.5+1;i+=100){ img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-up'],400,0,100,15)); img.x = i - 100; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-down'],400,0,100,15)); img.x = i - 100; img.y = h - 15; bar.addChild(img); } }else{ img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-up'],(530 - w)*0.5,0,w-30,15)); img.x = 15; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-down'],(530 - w)*0.5,0,w-30,15)); img.y = h - 15; img.x = 15; bar.addChild(img); } if(h > 410){ for(var i=15;i<(h-410)*0.5 + 1;i+=50){ img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-left'],0,0,15,50)); img.y = i; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-right'],0,0,15,50)); img.y = i; img.x = w - 15; bar.addChild(img); } img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-left'],0,0,15,380)); img.y = (h-380)*0.5; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-right'],0,0,15,380)); img.y = (h-380)*0.5; img.x = w - 15; bar.addChild(img); for(var i=h-15;i>(h+410)*0.5;i-=50){ img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-left'],0,330,15,50)); img.y = i - 50;trace(img.y); bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-right'],0,330,15,50)); img.y = i - 50; img.x = w - 15; bar.addChild(img); } }else{ img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-left'],0,(410 - h)*0.5,15,h-30)); img.y = 15; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-right'],0,(410 - h)*0.5,15,h-30)); img.x = w - 15; img.y = 15; bar.addChild(img); } img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-left-up'],0,0,15,15)); bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-right-up'],0,0,15,15)); img.x = w - 15; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-left-down'],0,0,15,15)); img.y = h - 15; bar.addChild(img); img = new LBitmap(new LBitmapData(LGlobal.imglist['bar-right-down'],0,0,15,15)); img.x = w - 15; img.y = h - 15; bar.addChild(img); return bar; };
运行效果如何呢?
缩率图读取完之后,直接开始显示战场,效果如下
完整图读取完之后,替换缩率图显示战场,效果如下
测试连接如下
http://lufylegend.com/demo/test/lsharp/08/game/index.html
以上,本章就先讲这么多了,下一章在战场上添加军队。
本章为止的源码如下,不包含lufylegend.js引擎源码,请自己到官网下载
http://lufylegend.com/demo/test/lsharp/08/08.rar
※源码运行说明:需要服务器支持,详细请看本系列文章《序》和《第一章》
《游戏脚本的设计与开发》系列文章目录
http://blog.csdn.net/lufy_legend/article/details/8888787
相关推荐
游戏实现了类似英雄无敌3 中战斗场景的回合制玩法: - 增加了六边形地图的实现 - 对战双方每个生物每一轮有一次行动机会,可以行走或攻击对方。 - 每个生物属性有:行走范围,速度,生命,伤害,防御,和攻击。 - 当...
基于Unity3D开发的一款3D回合制战棋游戏,内含源码以及资源,在Unity中导入包即可使用。 其实现功能如下: 1,通过qweasd六个按钮以及鼠标来控制场景视野。 2,回合制控制玩家角色移动,攻击,释放技能。 3,游戏...
基于unity3d的游戏程序,适合计算机专业哟西方向的学生作为毕业设计和课程设计
dev-c++开发的全鼠标操作控制台战棋,完整源代码,使用了最短路径算法,alpha-beta剪枝策略等,其中最后一版的战力相当可以,来尝试一下?
J2me战棋游戏源码,非Android版,源代码来自国外,注释全是英文的,以前的手机游戏,运行于Java环境的手机系统下,也就是J2me框架内的游戏源码。
一个用c++开发的3D战棋游戏 3D技术值得大家学习一下
简单的安卓战棋游戏,安卓移动开发课程设计/Android期末大作业 - 运行中有什么问题可以私聊博主,本人高级安卓工程师,主页置顶有常见爆红解决的方法,以及更多代码项目 ## 项目备注 1、该资源内项目代码都经过测试...
完整的游戏项目,战棋类,coco2d-x开发的,可以提供大家参考。
课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于...
游戏实现了类似英雄无敌3 中战斗场景的回合制玩法: - 对战双方每个生物每一轮有一次行动机会,可以行走或攻击对方。 - 每个生物属性有:行走范围,速度,生命,伤害,防御,和攻击。 - 当把对方生物都消灭时,即...
基于Python实现的战棋游戏源码.zip基于Python实现的战棋游戏源码.zip基于Python实现的战棋游戏源码.zip基于Python实现的战棋游戏源码.zip基于Python实现的战棋游戏源码.zip基于Python实现的战棋游戏源码.zip基于...
内核Rootkit是运行在操作系统内核空间的恶意程序,对系统安全构成巨大威胁。研究表明,内核Rootkit的共同特征是修改内核的程序控制流程。分析了Linux内核中影响程序控制流程的资源,并通过对这些资源进行保护,来...
一个战棋游戏源码,制作相当精美,一个下战棋的游戏,希望大家会喜欢
基于Java的联机对战棋类游戏.zip基于Java的联机对战棋类游戏.zip 基于Java的联机对战棋类游戏.zip基于Java的联机对战棋类游戏.zip 基于Java的联机对战棋类游戏.zip基于Java的联机对战棋类游戏.zip 基于Java的联机对...
模仿超级机器人大战写一款战棋类游戏,使用cocos2d移植到iphone上
游戏实现了类似英雄无敌3 中战斗场景的回合制玩法: - 对战双方每个生物每一轮有一次行动机会,可以行走或攻击对方。 - 每个生物属性有:行走范围,速度,生命,伤害,防御,攻击 和 是否是远程兵种。 - 当把对方...
2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。...
一款战棋游戏引擎及基于 ncurses 的 UI, 采用 go 语言开发. 支持调整规则, 设计关卡, 和对接不同类型的 UI
一套Java编写的战棋游戏源代码,感谢网友的提供,有兴趣的编译一下。