在一款rpg游戏中,与各处的npc对话,或是在地图中翻箱倒柜都是能令玩家深入挖掘的要素,
特别是在一款rpg游戏中一般有着众多的npc,而且丰富的npc对话可以很好的还原游戏的世界观和塑造人物性格,所以对于一款rpg游戏来说,丰富的对话是必不可少的,下面就来介绍一下使用lufylegend如何实现这个功能,下面以npc对话为列子来进行介绍。(宝箱的实现方式一致,稍微改一下所调用的东西即可)
既然是npc对话,就需要先看一下一般游戏是什么样的形式,大致的情况是,接近npc后提示对话按键,按键后出现对话,并可以反复对话,不同npc对话不同,这几个条件,
那么首先需要实现的就是npc类,用以显示npc,npc类需要的就是npc模型,以及npc的对话,npc的位置,大致这几个需要载入的变量,那么类的定义就变的很容易了,下面是类的实现,npcdata代表npc的位置,img代表npc的模型,(这里把对话拉出来定义了,一般是放在类里面定义的)
function LNpc(npcdata,img){
var s = this;
base(s,LSprite,[]);
s.NpcData = npcdata;
s.imgData=img;
s.onshow();
}
ohshow函数的定义如下,和之前的人物类形式并没有太大的区别
LNpc.prototype.onshow = function(){
var s = this;
var mapdata = s.NpcData;
var bitmapdata,bitmap;
for(var i=0;i<s.NpcData.length;i++){
var sprite=new LSprite();
bitmapdata=new LBitmapData(s.imgData,240,0,80,80);
bitmap=new LBitmap(bitmapdata);
bitmap.scaleX=0.4;
bitmap.scaleY=0.4;
sprite.width=32;
sprite.height=32;
sprite.x=s.NpcData[i][0];
sprite.y=s.NpcData[i][1];
sprite.addChild(bitmap);
s.addChild(sprite);
}
}
接下来实现接近npc后提示对话按键这个需求,为了实现这个需求,就有必要判断是否与npc接触这个条件,这里采用贴身为判定条件,所以需要在人物类中添加检测碰撞的函数,因为采用贴身所以相比一般的判定来说多了一个贴身的条件
LCharcter.prototype.CheckboxContact=function(box){
var s=this;
//box在右侧
if((s.x>box.x)&&(box.x+box.width==s.x)&&(s.y==box.y)){
return true;
//box在左侧
}else if((s.x<box.x)&&(s.x+s.width==box.x)&&(s.y==box.y)){
return true;
//box在下测
}else if((s.y<box.y)&&(s.y+s.height==box.y)&&(s.x==box.x)){
return true;
//box在上测
}else if((s.y>box.y)&&(box.y+box.height==s.y)&&(s.x==box.x)){
return true;
}else{
return false;
}
}
之后将这个函数加入游戏的刷新函数里面进行判断,如果为贴身就提示按键,这里选择用A键来触发对话,需要注意的是这里的break,因为npc的位置是不同的,因为是全量判断,所以如果一直做就会将 buttonLayer.text赋值为空,所以这里选择一旦与其中一个npc解除就直接break,避免后续将赋值重置
function onframe(){
//checkscene();
for(var i=0;i<npcLayer.childList.length;i++){
if(playerLayer.CheckboxContact(npcLayer.childList[i])){
buttonLayer.text="A键";
npcnumber=i;
break;
}else{
buttonLayer.text="";
npcnumber=-1;
}
}
if(diaflag==false){
checkdialog();
}
}
接下来需要实现的就是载入对话,这个在之前已经实现了对话类,这里直接使用,相关可以参考之前的blog:
http://blog.youkuaiyun.com/qq_26786555/article/details/45541539
修改一下按键触发函数,这样就可以在按下a键并与npc解除时触发对话了,因为npc对话并不同于剧情对话,所以这里并没有设置不可重复触发的flag
function move(e){
if(!diastartflag){
if(e.keyCode==37||e.keyCode==38||e.keyCode==39||e.keyCode==40){
playerLayer.move(e.keyCode);
}else if((buttonLayer.text=="A键")&&(e.keyCode==65)){
var dia2=new LDialog(dia[npcnumber]);
diaLayer.addChild(dia2);
}
}
}
这样与npc对话就实现了,效果如下:
源代码:
index.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LTileMap</title>
<script type="text/javascript" src="lufylegend.js-lufylegend-1.9.7/lufylegend-1.9.7.min.js"></script>
<script type="text/javascript" src="LCharcter.js"></script>
<script type="text/javascript" src="LDialog.js"></script>
<script type="text/javascript" src="map.js"></script>
<script type="text/javascript" src="LNpc.js"></script>
<script src="jquery/jquery-1.8.3.js"></script>
<script>
LInit(30,"legend",448,320,main);
LGlobal.setDebug(true);
var backLayer,loadingLayer,mapLayer,playerLayer,diaLayer;
var boxLayer;//宝箱层
var npcLayer;//npc所在位置
var boxData=[];
var npcData=[[64,96],[160,192]];
var buttonLayer;
var npcnumber=-1;//-1为无npc可对话
var diaflag=false;//false代表未发生对话,true代表发生
var diastartflag=false;//代表对话开始,禁用操作
var dia;
var loadData = [
{name:"cr",path:"./images/charc.jpg"},
{name:"map",path:"./images/map.jpg"},
{name:"money",path:"./images/bird.png"},
{name:"photo1",path:"./images/66RPG_002_f.png"},
{name:"photo2",path:"./images/66RPG_005_f.png"}
];
var mapData=[[[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[55,1],[55,1],[18,1]],
[[18,1],[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[55,1],[55,1],[18,1]],
[[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[55,1],[55,1],[18,1]],
[[18,1],[17,0],[17,2],[17,0],[18,1],[18,1],[18,1],[18,1],[18,1],[17,0],[17,0],[55,1],[55,1],[17,0],[18,1]],
[[18,1],[17,0],[17,0],[18,1],[22,1],[23,1],[23,1],[23,1],[24,1],[18,1],[17,0],[55,1],[55,1],[17,0],[18,1]],
[[18,1],[17,0],[17,0],[18,1],[25,1],[28,1],[26,1],[79,1],[27,1],[18,1],[55,1],[55,1],[17,0],[17,0],[18,1]],
[[18,1],[17,0],[17,0],[17,0],[17,0],[10,2],[11,0],[12,0],[18,1],[18,1],[55,1],[55,1],[17,0],[17,0],[18,1]],
[[18,1],[18,1],[17,0],[17,0],[10,0],[16,0],[16,0],[16,0],[11,0],[55,1],[55,1],[17,0],[17,0],[17,0],[18,1]],
[[18,1],[18,1],[17,0],[17,0],[77,0],[16,0],[16,0],[16,0],[16,0],[21,0],[21,0],[17,0],[17,0],[17,0],[18,1]],
[[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[55,1],[55,1],[18,1],[18,1],[18,1],[18,1]]];
var imglist=[];
function main(){
//加入进度条
loadingLayer = new LoadingSample3();
addChild(loadingLayer);
//加载图片并显示进度
LLoadManage.load(
loadData,
function(progress){
loadingLayer.setProgress(progress);
},
gameInit
);
}
function gameInit(result){
removeChild(loadingLayer);
imglist = result;
backLayer = new LSprite();
addChild(backLayer);
mapLayer = new LTileMap(mapData,imglist["map"],32,32);
dia=[[[imglist["photo2"],"hello,My name is lianggong",1],
[imglist["photo1"],"well,you are so fast",2],
[imglist["photo2"],"em,I am the fastest",1],
[imglist["photo2"],"I am the lightning nova",1]],
[[imglist["photo2"],"hello,My name is lianggongzhazha",1],
[imglist["photo1"],"well,you are so fast",2],
[imglist["photo2"],"em,I am the fastest",1],
[imglist["photo2"],"I am the lightning nova",1]]];
backLayer.addChild(mapLayer);
playerLayer=new LCharcter(imglist["cr"]);
backLayer.addChild(playerLayer);
//加入宝箱层
boxLayer=new LSprite();
backLayer.addChild(boxLayer);
//加入npc层
npcLayer=new LNpc(npcData,imglist["cr"]);
npcLayer.x=0;
npcLayer.y=0;
backLayer.addChild(npcLayer);
//加入对话层
diaLayer=new LSprite();
backLayer.addChild(diaLayer);
//加入按键提示层
buttonLayer=new LTextField();
buttonLayer.x=422;
buttonLayer.y=300;
buttonLayer.size=12;
backLayer.addChild(buttonLayer);
//加入动画和按键事件监听
backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);
LEvent.addEventListener(LGlobal.window, LKeyboardEvent.KEY_DOWN,move);
LEvent.addEventListener(LGlobal.window, LKeyboardEvent.KEY_UP,stop);
}
function onframe(){
//checkscene();
for(var i=0;i<npcLayer.childList.length;i++){
if(playerLayer.CheckboxContact(npcLayer.childList[i])){
buttonLayer.text="A键";
npcnumber=i;
break;
}else{
buttonLayer.text="";
npcnumber=-1;
}
}
if(diaflag==false){
checkdialog();
}
}
function move(e){
if(!diastartflag){
if(e.keyCode==37||e.keyCode==38||e.keyCode==39||e.keyCode==40){
playerLayer.move(e.keyCode);
}else if((buttonLayer.text=="A键")&&(e.keyCode==65)){
var dia2=new LDialog(dia[npcnumber]);
diaLayer.addChild(dia2);
}
}
}
function stop(e){
playerLayer.stop();
}
function checkscene(){
if((playerLayer.x==192)&&(playerLayer.y==192))
{
window.location.href="nextmap.php";
}
}
function checkdialog(){
var dia1=new Array(dia.length);
if((playerLayer.x==192)&&(playerLayer.y==192))
{
diastartflag=true;
var dia2=new LDialog(dia[0]);
diaLayer.addChild(dia2);
diaflag=true;
}
}
function loaddialog(dia){
/* var i=0;
var dia1=new LDialog(dia[i]);
diaLayer.addChild(dia1);
dia1.onshow(function(){if(i<dia.length){i=i+1;var dia1=new LDialog(dia[i]);diaLayer.addChild(dia1);dia1.onshow(function(){if(i<dia.length){i=i+1;
var dia1=new LDialog(dia[i]);diaLayer.addChild(dia1);dia1.onshow()}else{
i=i+1;var dia1=new LDialog(dia[i]);diaLayer.addChild(dia1);dia1.onshow();
}})}else{
i=i+1;var dia1=new LDialog(dia[i]);diaLayer.addChild(dia1);dia1.onshow();
}})
*/
}
function onMouseDown(){
for(i=0;i<diaLayer.childList.length;i++){
diaLayer.childList[i].clear();
}
}
</script>
</head>
<body>
<div id="legend"></div>
</body>
</html>
LNPc.js
var NpcLayer;
function LNpc(npcdata,img){
var s = this;
base(s,LSprite,[]);
s.NpcData = npcdata;
s.imgData=img;
s.onshow();
}
LNpc.prototype.GetMapData = function(){
var s=this;
return s.NpcData;
}
//0是x坐标,1是Y坐标
LNpc.prototype.onshow = function(){
var s = this;
var mapdata = s.NpcData;
var bitmapdata,bitmap;
for(var i=0;i<s.NpcData.length;i++){
var sprite=new LSprite();
bitmapdata=new LBitmapData(s.imgData,240,0,80,80);
bitmap=new LBitmap(bitmapdata);
bitmap.scaleX=0.4;
bitmap.scaleY=0.4;
sprite.width=32;
sprite.height=32;
sprite.x=s.NpcData[i][0];
sprite.y=s.NpcData[i][1];
sprite.addChild(bitmap);
s.addChild(sprite);
}
}