`
252190908
  • 浏览: 235525 次
文章分类
社区版块
存档分类
最新评论

《游戏脚本的设计与开发》-(战棋部分)2.1 快速显示一张战场地图

 
阅读更多

今天开始脚本设计的第二部分,战棋游戏的开发。战棋游戏中我尤其喜爱光荣的英杰传和曹操传,我的多平台游戏三国记,也是以三国志曹操传为模板而开发的。本次也不例外,就从曹操传的移植为基础来开发,再进行扩展,从而实现自己的战棋游戏的开发。熟悉曹操传的朋友们都知道,曹操传分为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



本章就讲到这里,欢迎继续关注我的博客

转载请注明:转自lufy_legend的博客http://blog.csdn.net/lufy_legend

分享到:
评论

相关推荐

    使用Unity3D基于GameFramework框架开发的战棋类生存经营游戏.zip

    《使用Unity3D基于GameFramework框架开发的战棋类生存经营游戏》 Unity3D是一款强大的跨平台游戏开发工具,广泛应用于2D、3D游戏的制作,支持Windows、Mac、Linux等多种操作系统,并能轻松发布到移动设备如Android...

    一个手机版战棋游戏Java源码.rar

    开发者可能使用了面向对象编程来抽象出棋子类和战场类,通过方法来模拟真实的战棋游戏流程。 2. 图形界面:J2ME提供了一些基本的图形库,如MIDP(Mobile Information Device Profile)中的Canvas类,用于绘制游戏...

    python 战棋游戏六边形地图代码实现

    游戏实现了类似英雄无敌3 中战斗场景的回合制玩法: - 增加了六边形地图的实现 - 对战双方每个生物每一轮有一次行动机会,可以行走或攻击对方。 - 每个生物属性有:行走范围,速度,生命,伤害,防御,和攻击。 - 当...

    战棋类游戏源代码

    通过分析和学习这个“二战风云bate2副本”的源代码,我们可以掌握以上诸多技术要点,不仅可以提升Cocos2d-x的开发能力,还能深入了解战棋类游戏的设计与实现,为自己的游戏开发事业打下坚实基础。

    dev-c++开发的全鼠标操作控制台战棋(完整源码)

    本文将详细讲解基于C++开发的全鼠标操作控制台战棋游戏,该游戏采用Dev-C++集成开发环境,并且在设计中应用了最短路径算法和alpha-beta剪枝策略,为玩家提供了一种策略性的游戏体验。让我们深入探讨这两个算法在游戏...

    3D战棋游戏C++实例

    在本项目"3D战棋游戏C++实例"中,我们探索的是如何使用C++编程语言来...通过深入研究这个"3D战棋游戏C++实例",不仅可以提升你的C++编程技能,还能掌握3D图形编程和游戏设计的基础知识,为未来的游戏开发奠定坚实基础。

    Unity3D战棋游戏.unitypackage

    基于Unity3D开发的一款3D回合制战棋游戏,内含源码以及资源,在Unity中导入包即可使用。 其实现功能如下: 1,通过qweasd六个按钮以及鼠标来控制场景视野。 2,回合制控制玩家角色移动,攻击,释放技能。 3,游戏...

    简单的ios战棋游戏

    在iOS平台上开发一款基于Cocos2D的战棋游戏,我们可以深入探讨以下几个关键知识点: 1. **Cocos2D框架**:Cocos2D是一款开源的游戏开发框架,它支持多种平台,包括iOS。Cocos2D提供了一套简单易用的API,用于创建2D...

    一个战棋游戏源码,制作相当精美

    在IT领域,游戏开发是极具挑战性和创新性的部分,而源码则是游戏开发的核心。本资源提供了一个战棋游戏的源码,其精美的制作展现了开发者对游戏设计的深入理解和高超的技术水平。战棋游戏是一种策略类游戏,它融合了...

    Unity独立开发的一款小型战棋游戏

    2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。...

    课程设计基于Python+PyQt5实现的战棋游戏源码.tar

    课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于Python+PyQt5实现的战棋游戏源码.tar课程设计基于...

    基于Java的三国主题单机回合制战棋游戏设计源码

    该项目是一个基于Java的三国主题单机回合制战棋游戏设计源码,包含139个文件,其中包括121个Java源文件、5个XML配置文件、5个JSON配置文件、4个JAR包文件、2个Markdown文档和2个文本文件。游戏以文字形式呈现,拥有...

    简单的安卓战棋游戏,安卓移动开发课程设计/Android期末大作业

    简单的安卓战棋游戏,安卓移动开发课程设计/Android期末大作业 - 运行中有什么问题可以私聊博主,本人高级安卓工程师,主页置顶有常见爆红解决的方法,以及更多代码项目 ## 项目备注 1、该资源内项目代码都经过测试...

    一套Java编写的战棋游戏源代码

    总的来说,分析和学习这套Java编写的战棋游戏源代码,我们可以深入理解Java编程语言、OOP设计原则、图形用户界面开发、游戏逻辑实现、AI算法以及软件工程实践等多个方面。这对于提升Java编程技能,特别是游戏开发...

    A星插件战棋移动系统.zip

    A*算法,全称为A-star,是一种广泛应用的路径搜索算法,它在游戏开发领域,尤其是战棋类游戏的移动系统设计中扮演着核心角色。本教程通过一个Unity3D的演示实例,深入浅出地解析了如何利用A*算法来实现智能角色的...

    J2ME游戏开发.pdf

    - 分析游戏设计与开发过程中的考虑因素。 #### 二、移动游戏行业简介 随着智能手机和平板电脑等移动设备的普及,移动游戏市场迅速增长。移动游戏以其便携性、多样性和易访问性吸引了广泛的用户群体,成为游戏产业的...

    双合棋程序及其源代码-一个局域网对战棋类游戏

    双合棋程序是一款基于VB6.0开发的局域网对战棋类游戏,它允许玩家在同一个网络环境中进行互动竞技。VB6.0是Microsoft Visual Basic的第六个版本,是一个面向对象的编程环境,特别适合开发Windows应用程序。这款游戏...

    Java战棋游戏源代码.rar

    【Java战棋游戏源代码】是一款基于Java编程语言开发的战棋类游戏,它展示了Java在游戏开发领域的应用。这个游戏源代码提供了学习和研究Java游戏编程的实例,可以帮助开发者了解如何利用Java进行游戏逻辑设计、图形...

    一款战棋游戏引擎及基于 ncurses 的 UI, 采用 go 语言开发. 支持调整规则, 设计关卡, 和对接不同类型的 UI

    综合这些知识点,我们可以了解到这是一个高度可定制和扩展的战棋游戏开发框架,它结合了ncurses的终端界面优势和Go语言的高效性能,为开发者提供了丰富的游戏设计可能性,同时也为玩家带来了独特的游戏体验。

Global site tag (gtag.js) - Google Analytics