《游戏脚本的设计与开发》-1.6 按钮,脚本的暂停和标签

按钮

按钮在任何程序中都是必不可少的,本次先来看看如何脚本来实现按钮的各种功能。文章中要实现的几个脚本如下。

/*
游戏脚本的设计与开发 第六章
*/
//添加按钮
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



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

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

没有更多推荐了,返回首页