按钮
按钮在任何程序中都是必不可少的,本次先来看看如何脚本来实现按钮的各种功能。文章中要实现的几个脚本如下。
/*
游戏脚本的设计与开发 第六章
*/
//添加按钮
Button.add(layer01,button01,null,50,50,ok_button_up,ok_button_over,null);
function function_test01();
//移除按钮
Button.remove(button01);
endfunction;
//移除显示层
Layer.remove(layer01);
//给按钮添加点击事件
Button.mousedown(button01,function_test01);
下面是ScriptButton类的完整代码,用来实现上述脚本的解析
/*
* ScriptButton.js
**/
var ScriptButton = function (){};
ScriptButton.analysis = function (value){
var start = value.indexOf("(");
var end = value.indexOf(")");
switch(value.substr(0,start)){
case "Button.add"://添加按钮
ScriptButton.addButton(value,start,end);
break;
case "Button.remove"://删除按钮
ScriptButton.removeButton(value,start,end);
break;
case "Button.mousedown"://鼠标按下事件
ScriptButton.mouseevent(value,start,end,LMouseEvent.MOUSE_DOWN);
break;
case "Button.mouseup"://鼠标弹起事件
ScriptButton.mouseevent(value,start,end,LMouseEvent.MOUSE_UP);
break;
case "Button.mousemove"://鼠标移动事件
ScriptButton.mouseevent(value,start,end,LMouseEvent.MOUSE_MOVE);
break;
default:
LGlobal.script.analysis();
}
};
/**
添加按钮脚本解析
Button.add(layer01,button01,null,50,50,ok_button_up,ok_button_over,null);
*/
ScriptButton.addButton = function (value,start,end){
var script = LGlobal.script;
var layer;
//获取参数
var lArr = value.substring(start+1,end).split(",");
var layerStr = lArr[0];//显示层名称
var nameStr = lArr[1];//按钮名称
var labelStr = lArr[2];//按钮上的文字,如果设置为null,则不显示文字
var x = parseInt(lArr[3]);//按钮坐标
var y = parseInt(lArr[4]);//按钮坐标
var dataUp = lArr[5];//按钮弹起样式的bitmapData对象名称
var dataOver = lArr[6];//按钮点击后样式的bitmapData对象名称
//获取按钮弹起和按下的样式的bitmapData对象
var upimg = script.scriptArray.bitmapdataList[dataUp];
var overimg = script.scriptArray.bitmapdataList[dataOver];
//按钮弹起状态LSprite
var upLayer = new LSprite();
upLayer.addChild(new LBitmap(upimg));
//按钮按下状态LSprite
var overLayer = new LSprite();
overLayer.addChild(new LBitmap(overimg));
//如果设置了按钮文字,则开始在按钮上添加一个LTextField对象来显示文字
if(labelStr && labelStr != "null"){
var upText = new LTextField();
upText.text = labelStr;
upText.size = upimg.height * 0.5;
upText.x = (upimg.width - upText.getWidth())*0.5;
upText.y = upimg.height * 0.2;
upLayer.addChild(upText);
var overText = new LTextField();
overText.text = labelStr;
overText.size = upimg.height * 0.5;
overText.x = (upimg.width - upText.getWidth())*0.5+2;
overText.y = upimg.height * 0.2+2;
overLayer.addChild(overText);
//按钮的文字颜色
if(lArr.length > 7){
upText.color = lArr[7];
overText.color = lArr[7];
}
}
//利用按钮的两个状态,新建一个LButton按钮对象
var btn = new LButton(upLayer,overLayer);
btn.x = x;
btn.y = y;
//得到显示层
layer = script.scriptArray.layerList[layerStr];
//保存按钮
script.scriptArray.btnList[nameStr] = btn;
btn.name = nameStr;
//将按钮添加到显示层
layer.addChild(btn);
script.analysis();
};
/**
删除按钮脚本解析
Button.remove(button01);
*/
ScriptButton.removeButton = function(value,start,end){
//获取参数
var lArr = value.substring(start+1,end).split(",");
var nameStr = lArr[0];//按钮名称
var script = LGlobal.script;
//获取按钮
var btn = script.scriptArray.btnList[nameStr];
//如果按钮不存在,则解析下一行脚本
if(btn == null){
script.scriptArray.btnList[nameStr] = null;
script.analysis();
return;
}
//移除按钮
btn.parent.removeChild(btn);
script.scriptArray.btnList[nameStr] = null;
script.analysis();
};
/**
按钮事件脚本解析
Button.mousedown(button01,function_test01);
*/
ScriptButton.mouseevent = function (value,start,end,e){
var script = LGlobal.script;
//获取参数
var lArr = value.substring(start+1,end).split(",");
var nameStr = lArr[0];//按钮名称
var funStr = lArr[1];//函数名称
//获取按钮
var btn = script.scriptArray.btnList[nameStr];
//添加匿名函数,然后匿名函数中利用Call脚本类来调用相应的函数
var fun = function(event){
ScriptFunction.analysis("Call." + funStr + "();");
};
//为按钮添加事件
btn.addEventListener(e,fun);
script.analysis();
};
我在上面的代码中添加了非常详细的代码,基本上不用我再多解释什么了,下面来看看这些脚本的使用,修改Main.ls如下。
Layer.add(-,layer01,100,100);
Layer.add(-,layer02,20,50);
Text.label(layer02,txt01,点击下面按钮,被点击按钮就会消失,0,0,30,#000000);
Load.img(ok_button_over,ok_button_over.png);
Load.img(ok_button_up,ok_button_up.png);
//添加按钮
Button.add(layer01,button01,null,50,50,ok_button_up,ok_button_over);
Button.add(layer01,button02,测试1,150,50,ok_button_up,ok_button_over,#880000);
Button.add(layer01,button03,测试2,250,50,ok_button_up,ok_button_over,#008800);
//声明函数,以备按钮事件使用
function function_test01();
//移除按钮
Button.remove(button01);
endfunction;
function function_test02();
Button.remove(button02);
endfunction;
function function_test03();
Button.remove(button03);
endfunction;
//给按钮添加点击事件
Button.mousedown(button01,function_test01);
Button.mousedown(button02,function_test02);
Button.mousedown(button03,function_test03);
测试连接
http://lufylegend.com/demo/test/lsharp/06/index01.html
上面的测试中,我利用脚本添加了三个按钮,并且给这三个按钮分别添加了点击事件,点击按钮后,被点击的按钮就会被移除。
脚本暂停
在游戏脚本运行过程中,如果脚本没有暂停功能,不间断的进行解析,那么就完全不受控制了,脚本什么时候运行结束了,整个程序也就结束了。这显然是不符合我们的意愿的,而且在游戏中,也尝尝会遇到一种情况,就是点击鼠标后才继续进行下面程序,这就要用到脚本暂停了,就是脚本执行到某一行后暂停解析,等待用户的命令,然后才进行下一行的脚本解析。
下面尝试定义的脚本,如下
//暂停1秒
Wait.time(1000);
//等待点击
Wait.click();
//等待运行控制脚本的执行
Wait.ctrl();
//结束Wait.ctrl,继续进行解析
Wait.play();
下面是完整的ScriptWait.js类,用来解析暂停脚本相关的各种操作。
/*
* ScriptWait.js
**/
var ScriptWait = function (){};
ScriptWait.analysis = function (value){
var start = value.indexOf("(");
var end = value.indexOf(")");
switch(value.substr(0,start)){
case "Wait.click"://暂停,等待点击鼠标
ScriptWait.waitclick();
break;
case "Wait.ctrl"://暂停,等待运行脚本
if(int(value.substring(start + 1,end)) > 0)LGlobal.script.lineList.unshift("Wait.ctrl()");
break;
case "Wait.play"://脚本继续运行
LGlobal.script.analysis();
break;
case "Wait.time"://脚本暂停一段时间
ScriptWait.timeId = setTimeout(function(){
ScriptWait.timeId = null;
LGlobal.script.analysis();
}, 1000);
break;
case "Wait.clickOver"://结束等待点击脚本(Wait.click)
LGlobal.script.scriptLayer.removeEventListener(LMouseEvent.MOUSE_UP,ScriptWait.clickEvent);
LGlobal.script.analysis();
break;
case "Wait.timeOver"://结束时间暂停脚本(Wait.time)
ScriptWait.timeOver();
break;
case "Wait.Over"://结束所有暂停脚本
LGlobal.script.scriptLayer.removeEventListener(LMouseEvent.MOUSE_UP,ScriptWait.clickEvent);
ScriptWait.timeOver();
break;
default:
LGlobal.script.analysis();
}
};
/*
* 结束时间暂停脚本(Wait.time)
**/
ScriptWait.timeOver = function (){
if(ScriptWait.timeId){
clearTimeout(ScriptWait.timeId);
ScriptWait.timeId = null;
}
LGlobal.script.analysis();
};
/*
* 暂停,等待点击鼠标
**/
ScriptWait.waitclick = function (){
var layer = LGlobal.script.scriptLayer;
//添加一个鼠标点击事件,当鼠标点击屏幕的时候,调用clickEvent函数,开始运行脚本
layer.addEventListener(LMouseEvent.MOUSE_UP,ScriptWait.clickEvent);
};
/*
* 鼠标点击运行脚本
**/
ScriptWait.clickEvent = function (event){
LGlobal.script.scriptLayer.removeEventListener(LMouseEvent.MOUSE_UP,ScriptWait.clickEvent);
LGlobal.script.analysis();
};
上面的代码同样加了详细的注释,下面来测试一下这几个脚本,修改脚本文件如下
Layer.add(-,layer01,20,20);
Text.label(layer01,txt01,暂停测试,请等待一秒钟,0,0,20,#000000);
Wait.time(1000);
Text.label(layer01,txt01,一秒钟结束,请点击一下屏幕,0,30,20,#000000);
Wait.click();
Text.label(layer01,txt01,你点击了屏幕,脚本继续,0,60,20,#000000);
Load.img(ok_button_over,ok_button_over.png);
Load.img(ok_button_up,ok_button_up.png);
Button.add(layer01,button01,null,50,200,ok_button_up,ok_button_over);
function function_test01();
Wait.play();
endfunction;
Button.mousedown(button01,function_test01);
Text.label(layer01,txt01,脚本暂停,你可以点击OK按钮来继续解析脚本,0,90,20,#000000);
Wait.ctrl();
Button.remove(button01);
Text.label(layer01,txt01,脚本结束,0,120,20,#000000);
测试连接如下
http://lufylegend.com/demo/test/lsharp/06/index02.html
可以看到,上述的各种脚本,都在程序中正常运行了。
标签
标签功能,类似于某些程序中的go语句,就是直接跳到某个代码的位置,然后开始继续执行,下面我依然在脚本中实现以下这个功能,先来定义两个脚本,如下。
//设置标签
Mark.drawRoundRect;
//跳到drawRoundRect标签位置
Mark.goto(drawRoundRect);
在脚本解析的时候,遇到不认识的脚本,会自动跳过,所以设置标签的时候,不需要任何处理,直接跳过即可,下面看一下ScriptMark.js类中如何来具体实现标签的寻找。
/*
* ScriptMark.js
**/
var ScriptMark = function (){};
ScriptMark.analysis = function (value){
var start = value.indexOf("(");
var end = value.indexOf(")");
switch(value.substr(0,start)){
case "Mark.goto"://跳至标签位置
ScriptMark.goto(value,start,end);
break;
default:
LGlobal.script.analysis();
}
};
ScriptMark.goto = function (value,start,end){
var mark = LMath.trim(value.substring(start+1,end));
//copyList是当前正在解析的脚本序列的副本,再复制一个脚本序列的副本
var copyArray = LGlobal.script.copyList.concat();
var foundStr;
while(copyArray.length){
//从复制的脚本序列中开始查找标签,没查找一行,则将其删除
foundStr = copyArray.shift();
if(foundStr.indexOf("Mark."+mark) >= 0){
//如果找到标签,则将当前正在解析的脚本序列替换为复制序列
LGlobal.script.lineList = copyArray;
LGlobal.script.analysis();
return;
}
}
//如果没有找到标签,则什么都不做,进行下一行脚本的解析
LGlobal.script.analysis();
};
最后,来测试一下,修改Main.ls脚本文件如下
Layer.add(-,layer01,0,0);
//跳到标签drawTriangle
Mark.goto(drawTriangle);
//绘制矩形
Layer.drawRect(layer01,0,0,100,60,0xff0000);
Layer.drawRectLine(layer01,0,100,100,60,0xff0000,5);
//设置drawRoundRect标签
Mark.drawRoundRect;
//绘制圆角矩形
Layer.drawRoundRect(layer01,150,0,100,60,10,0x880000);
Layer.drawRoundRectLine(layer01,150,100,100,60,10,0x880000,5);
//跳到标签over
Mark.goto(over);
//设置drawTriangle标签
Mark.drawTriangle;
//绘制三角形
Layer.drawTriangle(layer01,350,0,300,60,400,60,0xff0000);
Layer.drawTriangleLine(layer01,350,100,300,160,400,160,0xff0000,5);
//跳到标签drawRoundRect
Mark.goto(drawRoundRect);
//设置over标签
Mark.over;
解释一下上面的脚本,如果没有这些标签操作的话,脚本按照顺序执行,会绘制两个矩形,两个圆角矩形和两个三角形,但是脚本一开始就遇到了跳到标签,跳转到了drawTriangle,开始绘制三角形,绘制完三角形,又跳转到了drawRoundRect标签,开始绘制圆角矩形,绘制完圆角矩形后,又直接跳转到了over标签,从而脚本结束,所以,最初的两个矩形最终没有绘制出来。
测试连接如下
http://lufylegend.com/demo/test/lsharp/06/index03.html
这个是运行效果
以上是本章的素有内容,下一章来扩展一下文字脚本,实现打字机效果文字显示,然后脚本引擎的第一部分算是讲的差不多了,会试着用这些脚本做个小游戏给大家看看。
本章为止的lufylegend.lsharp.js源码如下
http://lufylegend.com/demo/test/lsharp/06/lufylegend.lsharp.js
《游戏脚本的设计与开发》系列文章目录
http://blog.csdn.net/lufy_legend/article/details/8888787