我不止一次在文章中说过游戏分层的重要性,处理好游戏显示层的划分和这些显示层的顺序,就可以完美控制游戏中各元素的显示和遮挡,本章来使用脚本来实现游戏显示层的划分,并且在显示层上绘制各种图形。文章中要实现的几个脚本如下。
/* 游戏脚本的设计与开发 第五章 */ //添加显示层 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: } };
添加显示层最简单,看下面的代码
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
运行脚本,得到下面效果
清空显示层就是将该显示层上的所有子类都移除,看下面的代码
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对象了。
移除一个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