我不止一次在文章中说过游戏分层的重要性,处理好游戏显示层的划分和这些显示层的顺序,就可以完美控制游戏中各元素的显示和遮挡,本章来使用脚本来实现游戏显示层的划分,并且在显示层上绘制各种图形。文章中要实现的几个脚本如下。

 

/*
游戏脚本的设计与开发 第五章
*/
//添加显示层
Layer.add(-,layer01,100,100);
//清空显示层
Layer.clear(layer01);
//移除显示层
Layer.remove(layer01);
//绘制实心矩形
Layer.drawRect(layer02,0,0,100,100,0xff0000);
//绘制空心矩形框
Layer.drawRectLine(layer02,0,0,100,100,0xff0000);
//绘制实心圆角矩形
Layer.drawRoundRect(layer01,0,0,100,100,10,0x880000);
//绘制空心圆角矩形框
Layer.drawRoundRectLine(layer01,0,0,100,100,10,0x880000);
//绘制实心三角形
Layer.drawTriangle(layer03,0,0,100,100,50,150,0xff0000);
//绘制空心三角形框
Layer.drawTriangleLine(layer03,0,0,100,100,50,0,0xff0000);
//对显示层进行缓动操作
Layer.transition(layer03,{x:50},1,Strong.easeOut);

下面我们就来一个一个的实现这些脚本的解析。

 

一,显示层的添加,清空和删除

要想实现游戏中的分层,首先需要将显示层添加到游戏中,首先修改ScriptLayer类的解析函数。

 

ScriptLayer.analysis = function (value){
	var start = value.indexOf("(");
	var end = value.indexOf(")");
	switch(value.substr(0,start)){
		case "Layer.add"://添加显示层
			ScriptLayer.setLayer(value,start,end);
			break;
		case "Layer.remove"://移除显示层
			ScriptLayer.removeLayer(value,start,end);
			break;
		case "Layer.clear"://清空显示层
			ScriptLayer.clearLayer(value,start,end);
			break;
		default:
	}
};

1,添加显示层

添加显示层最简单,看下面的代码

ScriptLayer.setLayer = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var parentStr = params[0];
	var nameStr = params[1];
	var xInt = parseInt(params[2]);
	var yInt = parseInt(params[3]);
	var script = LGlobal.script;
	var layer,parent,i;
	parent = script.scriptArray.layerList[parentStr];
	layer = new LSprite();
	layer.x = xInt;
	layer.y = yInt;
	layer.name = nameStr;
	parent.addChild(layer);
	script.scriptArray.layerList[nameStr] = layer;
	script.analysis();
};

从下面的脚本中可以看到,添加显示层的一共需要4个参数,依次是被添加显示层的父级层,被添加显示层的名称,坐标x,坐标y。

Layer.add(-,layer01,100,100);

ScriptLayer.setLayer函数中,首先根据逗号,将参数分解出来,根据名字从script.scriptArray.layerList中找到父级显示层对象,然后新建一个LSprite,添加到父级显示层,最后保存到layerList数组。

下面来测试一下,修改脚本文件如下

Layer.add(-,layer01,100,100);
Layer.add(-,layer02,150,150);
Layer.add(layer01,layer03,200,200);
Load.img(backdata,lufy_legend.jpg);
Img.add(layer01,backimg01,backdata,0,0,100,100,1);
Img.add(layer02,backimg02,backdata,0,0,100,100,1);
Img.add(layer03,backimg03,backdata,0,0,100,100,1);

测试连接

http://lufylegend.com/demo/test/lsharp/05/index01.html

运行脚本,得到下面效果

《游戏脚本的设计与开发》-第五章 显示层,绘图_游戏脚本

2,清空显示层

清空显示层就是将该显示层上的所有子类都移除,看下面的代码

ScriptLayer.removeFromArray = function (obj){
	if(obj.childList == null)return;
	var count = obj.childList.length;
	for(var i = 0; i < count; i++){
		if(obj.type == "LSprite"){
			ScriptLayer.removeFromArray(obj.childList[i]);
		}else if(obj.type == "LBitmap"){
			LGlobal.script.scriptArray.imgList[obj.childList[i].name] = null;
		}else if(obj.type == "LTextField"){
			LGlobal.script.scriptArray.textList[obj.childList[i].name] = null;
		}
	}
};
ScriptLayer.clearLayer = function (value,start,end){
	var nameStr = LMath.trim(value.substring(start+1,end));
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	if(!layer){
		script.analysis();
		return;
	}
	ScriptLayer.removeFromArray(layer);
	layer.die();
	layer.removeAllChild();
	script.analysis();
};

其实清空一个LSprite对象是很简单的,调用die函数,可以移除所有事件,调用removeAllChild可以移除所有的子对象,但是这里除了清空该对象之外,还是要将被移除的子对象以及子对象的子对象等等,都需要从layerList数组中移除,所以我添加了removeFromArray函数,这个函数中递归循环所有子对象,将他们从layerList中全部清除,这样就真正实现了从脚本引擎中清空一个LSprite对象了。

3,移除显示层

移除一个LSprite对象,只需要从它的父级显示层对象中removeChild就可以了,但是和上面的清空显示层一样,同样需要将子对象等清空。看下面代码。

ScriptLayer.removeLayer = function (value,start,end){
	var nameStr = LMath.trim(value.substring(start+1,end));
	var script = LGlobal.script;
	var layer,parent;
	layer = script.scriptArray.layerList[nameStr];
	if(!layer){
		script.analysis();
		return;
	}
	parent = layer.parent;
	ScriptLayer.removeFromArray(layer);
	parent.removeChild(layer);
	script.scriptArray.layerList[nameStr] = null;
	script.analysis();
}

移除显示层比清空显示层多了一步,就是将自己移除。下面来测试一下清空和移除操作。修改脚本如下

Layer.add(-,layer01,100,100);
Layer.add(-,layer02,150,150);
Layer.add(-,layer03,200,200);
Load.img(backdata,lufy_legend.jpg);
Img.add(layer01,backimg01,backdata,0,0,100,100,1);
Img.add(layer02,backimg02,backdata,0,0,100,100,1);
Img.add(layer03,backimg03,backdata,0,0,100,100,1);

测试连接

http://lufylegend.com/demo/test/lsharp/05/index02.html

运行脚本,得到下面效果

《游戏脚本的设计与开发》-第五章 显示层,绘图_游戏脚本_02

可以看到,显示层的清空和移除已经成功执行了。

二,绘制矩形,圆角矩形和三角形

下面来说一说如何使用脚本来绘制图形,从简单的矩形开始。

绘制一个实心矩形和空心矩形框的脚本如下,如下

Layer.drawRect(layer02,0,0,100,100,0xff0000);
Layer.drawRectLine(layer02,0,0,100,100,0xff0000,2);

几个参数分别为:显示层,起始坐标x,起始坐标y,宽,高,颜色。

如果是绘制矩形框,则多一个参数,用来设置线宽。

先修改ScriptLayer类的解析函数

 

ScriptLayer.analysis = function (value){
	var start = value.indexOf("(");
	var end = value.indexOf(")");
	switch(value.substr(0,start)){
		case "Layer.add"://添加显示层
			ScriptLayer.setLayer(value,start,end);
			break;
		case "Layer.remove"://移除显示层
			ScriptLayer.removeLayer(value,start,end);
			break;
		case "Layer.clear"://清空显示层
			ScriptLayer.clearLayer(value,start,end);
			break;
		case "Layer.drawRect"://绘制实心矩形
			ScriptLayer.drawRect(value,start,end);
			break;
		case "Layer.drawRectLine"://绘制空心矩形框
			ScriptLayer.drawRectLine(value,start,end);
			break;
		default:
	}
};

 

下面看drawRect函数和drawRectLine函数的代码。

ScriptLayer.drawRect = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var nameStr = params[0];
	var color = params[5];
	color = color.replace("0x","#");
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	layer.graphics.drawRect(1,color,[parseInt(params[1]),parseInt(params[2]),parseInt(params[3]),parseInt(params[4])],true,color);
	script.analysis();
};
ScriptLayer.drawRectLine = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var nameStr = params[0];
	var color = params[5];
	color = color.replace("0x","#");
	var num = 1;
	if(params.length > 6)num = parseFloat(params[6]);
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	layer.graphics.drawRect(num,color,[parseInt(params[1]),parseInt(params[2]),parseInt(params[3]),parseInt(params[4])]);
	script.analysis();
};

原理很简单,先用分号分割得到参数,根据显示层的名称取得相应的显示层,然后使用LGraphics的绘图函数在显示层上进行绘图

绘制圆角矩形和三角形跟上面的原理是一样的,都是使用LGraphics的相应的绘图函数,具体实现如下

 

ScriptLayer.analysis = function (value){
	var start = value.indexOf("(");
	var end = value.indexOf(")");
	switch(value.substr(0,start)){
		case "Layer.add"://添加显示层
			ScriptLayer.setLayer(value,start,end);
			break;
		case "Layer.remove"://移除显示层
			ScriptLayer.removeLayer(value,start,end);
			break;
		case "Layer.clear"://清空显示层
			ScriptLayer.clearLayer(value,start,end);
			break;
		case "Layer.drawRect"://绘制实心矩形
			ScriptLayer.drawRect(value,start,end);
			break;
		case "Layer.drawRectLine"://绘制空心矩形框
			ScriptLayer.drawRectLine(value,start,end);
			break;
		case "Layer.drawRoundRect"://绘制实心圆角矩形
			ScriptLayer.drawRoundRect(value,start,end);
			break;
		case "Layer.drawRoundRectLine"://绘制空心圆角矩形框
			ScriptLayer.drawRoundRectLine(value,start,end);
			break;
		case "Layer.drawTriangle"://绘制实心三角形
			ScriptLayer.drawTriangle(value,start,end);
			break;
		case "Layer.drawTriangleLine"://绘制空心三角形框
			ScriptLayer.drawTriangleLine(value,start,end);
			break;
		default:
	}
};
ScriptLayer.drawRoundRect = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var nameStr = params[0];
	var color = params[6];
	color = color.replace("0x","#");
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	layer.graphics.drawRoundRect(1,color,[parseInt(params[1]),parseInt(params[2]),parseInt(params[3]),parseInt(params[4]),parseInt(params[5])],true,color);
	script.analysis();
};
ScriptLayer.drawRoundRectLine = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var nameStr = params[0];
	var color = params[6];
	color = color.replace("0x","#");
	var num = 1;
	if(params.length > 7)num = parseFloat(params[7]);
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	layer.graphics.drawRoundRect(num,color,[parseInt(params[1]),parseInt(params[2]),parseInt(params[3]),parseInt(params[4]),parseInt(params[5])]);
	script.analysis();
};
ScriptLayer.drawTriangle = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var nameStr = params[0];
	var color = params[7];
	color = color.replace("0x","#");
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	layer.graphics.drawVertices(1,color,[[parseInt(params[1]),parseInt(params[2])],[parseInt(params[3]),parseInt(params[4])],[parseInt(params[5]),parseInt(params[6])]],true,color);
	script.analysis();
};
ScriptLayer.drawTriangleLine = function (value,start,end){
	var params = value.substring(start+1,end).split(",");
	var nameStr = params[0];
	var color = params[7];
	color = color.replace("0x","#");
	var num = 1;
	if(params.length > 8)num = parseFloat(params[8]);
	var script = LGlobal.script;
	var layer = script.scriptArray.layerList[nameStr];
	layer.graphics.drawVertices(num,color,[[parseInt(params[1]),parseInt(params[2])],[parseInt(params[3]),parseInt(params[4])],[parseInt(params[5]),parseInt(params[6])]]);
	script.analysis();
};

另外,绘制圆或者多边形等都是一样的,以后我会直接添加到里面,这里就不赘述了,有兴趣的话可以自己先实现一下。

下面来测试一下这几个脚本,修改脚本文件如下

Layer.add(-,layer01,0,0);
Layer.drawRect(layer01,0,0,100,60,0xff0000);
Layer.drawRectLine(layer01,0,100,100,60,0xff0000,5);
Layer.drawRoundRect(layer01,150,0,100,60,10,0x880000);
Layer.drawRoundRectLine(layer01,150,100,100,60,10,0x880000,5);
Layer.drawTriangle(layer01,350,0,300,60,400,60,0xff0000);
Layer.drawTriangleLine(layer01,350,100,300,160,400,160,0xff0000,5);

测试一下,得到效果如下

《游戏脚本的设计与开发》-第五章 显示层,绘图_圆角矩形_03

下面是测试连接

http://lufylegend.com/demo/test/lsharp/05/index03.html

 

三,对显示层进行缓动变换

这里的缓动和图片缓动基本是一样的,不同的是,图片的缓动针对的是单一图片,而这里的缓动是针对整个显示层来进行缓动。

 

Layer.transition(layer03,{x:50},1,Strong.easeOut); 

各参数和上一节中的图片缓动是一致的,不再赘述了。

看一下具体实现方法。

 

ScriptLayer.transition = function (value,start,end){
	var script = LGlobal.script;
	
	var lArr = value.substring(start+1,end).split(",");
	var nameStr = lArr[0];
	//将json对象还原
	var toObj = eval('(' + lArr[1] + ')');
	//获取缓动时间
	var time = parseFloat(lArr[2]);
	var eases = lArr[3].split(".");
	var runNow = false;
	//是否立即执行下一行脚本
	if(lArr.length > 4){
		runNow = (lArr[4] == "1");
	}
	toObj["ease"] = LEasing[eases[0]][eases[1]];
	if(!runNow){
		toObj["onComplete"] = function(){
			script.analysis();
		};
	}
	LTweenLite.to(script.scriptArray.layerList[nameStr],time,toObj);  
	//如果runNow为1,则立即执行下一行脚本
	if(runNow)script.analysis();
};

 

最后,来测试一下,修改Main.ls脚本文件如下

 

/*
游戏脚本的设计与开发 第五章
*/
Layer.add(-,layer01,100,20);
Layer.add(-,layer02,150,100);
Layer.add(-,layer03,250,250);
Load.img(backdata,lufy_legend.jpg);
Img.add(layer01,backimg01,backdata,0,0,100,100,1);
Layer.drawRectLine(layer02,0,0,100,100,0xff0000);
Layer.clear(layer01);
Layer.drawRoundRectLine(layer01,0,0,100,100,10,0x880000);
Layer.drawTriangle(layer03,0,0,100,100,50,150,0xff0000);
Layer.drawRect(layer03,100,0,100,60,0xff0000);
Layer.drawRoundRect(layer03,150,70,100,60,10,0x880000);
Layer.transition(layer03,{x:50},1,Strong.easeOut);
Layer.drawTriangleLine(layer03,0,0,100,100,50,0,0xff0000);

运行程序得到效果

《游戏脚本的设计与开发》-第五章 显示层,绘图_圆角矩形_04

测试连接如下

http://lufylegend.com/demo/test/lsharp/05/index.html

以上是本章的素有内容,下一章来讲一下按钮,脚本的暂停与查找等功能

 

 

本章为止的lufylegend.lsharp.js源码如下

http://lufylegend.com/demo/test/lsharp/05/lufylegend.lsharp.js

《游戏脚本的设计与开发》系列文章目录

 

 

 

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

 

转载请注明:转自lufy_legend的博客