上一节中 给地图加入了遮挡功能,尝试着加入了一个可以控制的测试人物,并且实现了人物行走时的各个动作变换的控制。本节中接下来要做的事情就是把之前的工作全部脚本化,并且使用游戏脚本加入多个人物角色,最后通过点击地图上的人物,来实现游戏中的对话功能。文章中贴出的只是部分主要的代码,你在看的时候,有些代码可能会不理解,这个不要紧,最后我会放出完整源码的下载。
首先,使用之前已经开发好的脚本来给游戏添加一个logo页面。
Main.ls
//添加显示层back
Layer.add(-,back,0,0);
Layer.drawRectLine(back,0,0,800,480,#000000);
//显示文字,读取中
Text.label(-,loading,图片读取中...,300,200,15,#000000);
//读取图片
Load.img(logobtnover,./images/logo/logobtnover.png);
Load.img(logobtnup,./images/logo/logobtnup.png);
Load.img(logo,./images/logo/logo.jpg);
//删除文字,读取中
Text.remove(loading);
Img.add(back,logo01,logo,0,0,800,480,1);
//显示游戏名称
Text.label(back,logo,RPG脚本测试,470,50,40,#000000);
//在back层上添加一个按钮,作为选项
Button.add(back,btn01,游戏开始,500,150,logobtnup,logobtnover,logobtnover,#ffffff);
function btn01click();
Button.remove(btn01);
Text.label(-,loading,脚本读取中...,300,200,20,#ffffff);
Load.script(script/R01.ls);
endfunction;
//为按钮添加点击事件
Button.mousedown(btn01,btn01click);
使用脚本添加图片,按钮,函数等功能,在
第一章 基本功能里都已经详细介绍过了,不了解的朋友可以看一下第一章的内容,上面的脚本效果如下图。
点击[游戏开始]按钮后,进入脚本R01.ls,先来预设一下本地要实现的所有功能所需要的脚本内容,一会儿我来一点点儿的实现它。
R01.ls
//清除画面
Layer.clear(-);
//RPG地图设定开始
RPGMap.start();
//RPG地图初始化开始
initialization.start;
//地图数据设定,包括地形和图片等
addMap(r01.rmap);
//加入人物角色,参数以此为 人物index,动作action,方向direction,坐标x,坐标y,是否可控ishero
RPGCharacter.add(1,stand,right,20,9,true);
RPGCharacter.add(2,stand,down,22,13,false);
RPGCharacter.add(3,stand,down,55,15,false);
RPGCharacter.add(4,stand,up,35,40,false);
RPGCharacter.add(5,stand,left,35,7,false);
//RPG地图初始化结束
initialization.end;
//RPG地图中各函数初始化开始
function.start;
//函数名称为“characterclick”+人物序号的函数,功能是当点击到某人物的时候,会调用相应的函数
function characterclick2();
RPGTalk.set(2,0,你知道lufy吗,听说那家伙除了做游戏,啥都不会。);
RPGTalk.set(1,0,怪不得啊,哈哈哈。);
endfunction;
function characterclick3();
RPGTalk.set(3,0,。。。。。。);
RPGTalk.set(1,0,少年,你能帮我捡肥皂吗?);
endfunction;
function characterclick4();
RPGTalk.set(4,0,请不要跟我说话,我只是过来打酱油的。);
RPGTalk.set(1,0,不跟我说话是因为看不起我吗?);
endfunction;
function characterclick5();
RPGTalk.set(5,0,你现在进入的是由lufylegend.js制作的一个虚幻的游戏脚本世界。目前正在执行是对话脚本。);
endfunction;
//RPG地图中各函数初始化结束
function.end;
//RPG地图设定结束
RPGMap.end();
以上的脚本,已经足够满足接下来要完成的工作了,实现的效果为
下面一个一个的来看,这些脚本如何来实现。
1,进入地图脚本
//RPG地图设定开始
RPGMap.start();
//RPG地图设定结束
RPGMap.end();
包括第二章的战旗部分,前面已经介绍了多种脚本,RPG脚本当然要与其他脚本区分开,所以RPG部分的脚本我会全部以RPG开头,上面这两个脚本,分别会进入和退出RPG部分的地图脚本。
RPG脚本部分有区别于其他部分脚本,当然有自己的一个脚本解析函数,如下
/*
* LScriptRPG.js
**/
var LScriptRPG = function (){};
LScriptRPG.analysis = function (childType, lineValue){
var start,end,params;
start = lineValue.indexOf("(");
end = lineValue.indexOf(")");
switch(childType){
case "RPGMap":
LGlobal.script.scriptLayer.controller.mapLoad();
break;
case "RPGTalk":
LRPGTalkScript.analysis(lineValue);
break;
default:
LGlobal.script.analysis();
}
};
修改LScript.analysis脚本解析函数中的switch部分,可以很容易的进入到上面RPG脚本解析函数里,稍后大家可以看一下源码,上面的RPG脚本解析函数里,遇到RPGMap脚本,会调用LGlobal.script.scriptLayer.controller.mapLoad(),我已经提前在IndexController中把LGlobal.script.scriptLayer设定成了程序中的IndexView,所以这里其实是调用了IndexController的mapLoad函数,
IndexController.prototype.mapLoad=function(){
var self = this;
self.loadMvc("Map",self.mapComplete);
};
当Map的相关的文件读取完成之后,会自动调用LRPGMapScript.analysis();进行下一个脚本的解析。
2,地图的初始化
//RPG地图初始化开始
initialization.start;
//RPG地图初始化结束
initialization.end;
地图的初始化,包括地图图片和地形的设定,人物角色的添加等等,看一下RPG地图脚本的解析函数
/*
* LRPGMapScript.js
**/
LRPGMapScript = function(){};
LRPGMapScript.analysis=function(){
var script = LGlobal.script;
if(script.lineList.length == 0)return;
var lineValue = LMath.trim(script.lineList.shift());
if(lineValue.length == 0){
LRPGMapScript.analysis();
return;
}
trace("LRPGMapScript analysis lineValue = " + lineValue);
switch(lineValue){
case "RPGMap.end()":
setTimeout(function(){
LRPGObject.RPGMap.initOver=true;
LGlobal.script.analysis();
},100);
return;
case "initialization.start":
LRPGMapScript.initialization();
break;
case "function.start":
LRPGMapScript.addFunction();
break;
default:
LRPGMapScript.analysis();
}
};
当遇到脚本initialization.start的时候,会调用LRPGMapScript.initialization();函数来进行地图初始化。
LRPGMapScript.initialization=function(){
var script = LGlobal.script;
var lineValue = LMath.trim(script.lineList.shift());
trace("LRPGMapScript initialization lineList = " + lineValue);
if(lineValue.length == 0){
LRPGMapScript.initialization();
return;
}
if(lineValue == "initialization.end"){
LRPGMapScript.analysis();
return;
}
var params,i;
var start = lineValue.indexOf("(");
var end = lineValue.indexOf(")");
switch(lineValue.substr(0,start)){
case "addMap":
params = lineValue.substring(start+1,end).split(",");
LRPGObject.RPGMap.addMap.apply(LRPGObject.RPGMap,params);
break;
case "RPGCharacter.add":
params = lineValue.substring(start+1,end).split(",");
LRPGObject.RPGMap.addCharacter.apply(LRPGObject.RPGMap,params);
break;
default:
LRPGMapScript.initialization();
}
};
可以看到,LRPGMapScript.initialization();函数进行地图的初始化工作,目前里面包括addMap地图数据添加,RPGCharacter.add人物角色添加等功能。
3,地图数据添加
//地图数据设定,包括地形和图片等
addMap(r01.rmap);
r01.rmap文件中的内容就是前面所介绍过的地图数据,如下
{
"width":1280
,"height":960
,"data":[
[1,1,1,......]
,[0,0,0,......]
......
]
,"pieceWidth":1280
,"pieceHeight":960
,"imgs":[
[{"img":"map-1","rect":[0,0],"path":"map-1.png"}]
]
,"builds":[
[{"img":"build-1","rect":[0,0],"path":"build-1.png"}]
]
}
解析函数遇到addMap脚本之后,读取相应的地图数据文件,然后进行地图的相关的设定。
4,人物角色的添加
//加入人物角色,参数以此为 人物index,动作action,方向direction,坐标x,坐标y,是否可控ishero
RPGCharacter.add(1,stand,right,20,9,true);
RPGCharacter.add(2,stand,down,22,13,false);
上一节中我为了测试,临时加入了一个可以控制的人物,上面脚本RPGCharacter.add用来添加一个人物角色,我只需要解析这个脚本,然后把相应的参数分离出来,和上一节用同样的方法,就可以加入一个人物了,当然地图上可以控制行走的人物通常只有一个(或者说是一组,因为有些游戏中是控制一个队伍的行走,如fc版《吞食天地》),所以在加入人物角色的时候,要设定这些人物哪些是可以控制的,哪些是不可以控制的。
5,函数的添加
//RPG地图中各函数初始化开始
function.start;
//函数名称为“characterclick”+人物序号的函数,功能是当点击到某人物的时候,会调用相应的函数
function characterclick2();
RPGTalk.set(2,0,你知道lufy吗,听说那家伙除了做游戏,啥都不会。);
RPGTalk.set(1,0,怪不得啊,哈哈哈。);
endfunction;
//RPG地图中各函数初始化结束
function.end;
之前也已经介绍了,如何用脚本来实现一个函数的添加和调用,但是函数的解析需要在LScript.analysis脚本解析函数中进行,而现在脚本解析已经进入到了RPG部分的解析,所以这里我加入了function.start;和function.end;来做一下特殊的处理,调用原来的ScriptFunction脚本,来解析里面的函数脚本。
6,对话脚本
RPGTalk.set(1,0,少年,你能帮我捡肥皂吗?);
对话的显示,要分两部分,一个是人物头像的显示,一个是对话内容的显示。
头像的显示,我用下面的类来实现。
function Face(index,subindex){
var self = this;
base(self,LSprite,[]);
loader = new LLoader();
loader.parent = self;
loader.addEventListener(LEvent.COMPLETE,self.loadOver);
loader.load(LMvc.IMG_PATH+"face/"+index+"-"+subindex+".png","bitmapData");
}
Face.prototype.loadOver = function(event){
var self = event.target.parent;
var bitmapData = new LBitmapData(event.currentTarget);
var bitmap = new LBitmap(bitmapData);
self.addChild(bitmap);
};
index是人物的头像序号,subindex是人物的表情,因为在游戏里一个人物,通常有多种表情,所以,我们要为每个人物准备多个头像,并且能分别调用它们。
接着,先准备一张背景图,
然后,将人物的名字和对话的名称显示到相应的位置上就可以了,下面是Talk的所有代码。
function Talk(){
if(arguments.length == 6){
TalkRun.apply(this,arguments);
}else if(arguments.length == 4){
TalkRun.call(this,LMvc.layer,150,arguments[0],arguments[1],arguments[2],arguments[3]);
}else{
TalkRun.call(this,arguments[0],150,arguments[1],arguments[2],arguments[3],arguments[4]);
}
}
function TalkRun(layer,y,index,faceindex,msg,callback){
if(LGlobal.talkLayer && LGlobal.talkLayer.parent){
LGlobal.talkLayer.parent.removeChild(LGlobal.talkLayer);
}
var talkLayer = new LSprite();
talkLayer.y = y;
talkLayer.x = 50;
var charaLayer = new Face(LMvc.datalist["chara"]["peo"+index]["Face"],faceindex);
charaLayer.x = 200;
talkLayer.addChild(charaLayer);
var back = new LBitmap(new LBitmapData(LMvc.datalist["talkbox"]));
back.y = 130;
back.alpha = 0.7;
talkLayer.addChild(back);
var nameText = new LTextField();
nameText.size = 18;
nameText.color = "#FFFFFF";
nameText.text = LMvc.datalist["chara"]["peo"+index]["Name"];
nameText.x = 30+(90 - nameText.getWidth())*0.5;
nameText.y = back.y + 22;
talkLayer.addChild(nameText);
var msgText = new LTextField();
msgText.x = 25;
msgText.y = 225;
msgText.text = msg;
msgText.size = 12;
msgText.color = "#FFFFFF";
msgText.width = 430;
msgText.setWordWrap(true,23);
msgText.wind(callback);
talkLayer.addChild(msgText);
layer.addChild(talkLayer);
LRPGObject.talkOver = false;
LRPGObject.talkLayer = talkLayer;
}
function TalkRemove(){
LRPGObject.talkLayer.remove();
LRPGObject.talkOver = false;
LRPGObject.talkLayer = null;
LGlobal.script.analysis();
}
OK,是不是已经迫不及待的想要看到效果了?测试连接如下:
http://lufylegend.com/demo/test/lsharp/rpg-lshape-03/index.html
预览效果:
最后,给出本次的代码下载:
https://github.com/lufylegend/lsharp/archive/3.3.zip
※源码运行说明:
1,需要服务器支持,详细请看本系列文章《序》和《第一章》
2,源码中不含lufylegend.js引擎代码,请自己到官方下载引擎
预告:
现在地图上的NPC人物都是静止不动的,在实际的游戏中有些NPC会随即的走动,使得游戏效果更为生动,
另外大家都知道,RPG游戏中有一个重要的功能,就是任务系统,玩家完成某一项人物会得到什么奖励,然后接着出现一个新的任务等等,
后面我接着来给大家介绍地图的切换效果,NPC人物的随即走动,以及地图脚本中的任务系统,请期待下次更新。
《游戏脚本的设计与开发》系列文章目录
http://blog.csdn.net/lufy_legend/article/details/8888787