我不止一次在文章中说过游戏分层的重要性,处理好游戏显示层的划分和这些显示层的顺序,就可以完美控制游戏中各元素的显示和遮挡,本章来使用脚本来实现游戏显示层的划分,并且在显示层上绘制各种图形。文章中要实现的几个脚本如下。
/*
游戏脚本的设计与开发 第五章
*/
//添加显示层
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
运行脚本,得到下面效果
可以看到,显示层的清空和移除已经成功执行了。
二,绘制矩形,圆角矩形和三角形
下面来说一说如何使用脚本来绘制图形,从简单的矩形开始。
绘制一个实心矩形和空心矩形框的脚本如下,如下
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);
测试一下,得到效果如下
下面是测试连接
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);
运行程序得到效果
测试连接如下
http://lufylegend.com/demo/test/lsharp/05/index.html
以上是本章的素有内容,下一章来讲一下按钮,脚本的暂停与查找等功能
本章为止的lufylegend.lsharp.js源码如下
http://lufylegend.com/demo/test/lsharp/05/lufylegend.lsharp.js
《游戏脚本的设计与开发》系列文章目录
http://blog.csdn.net/lufy_legend/article/details/8888787