《游戏脚本的设计与开发》-(RPG部分)3.4 map跳转
注意:本系列教程为长篇连载无底洞,半路杀进来的朋友,如果看不懂的话,请从第一章开始看起,文章目录请点击下面链接。
http://blog.****.net/lufy_legend/article/details/8888787
一眨眼,离上次更新已经两个月了,中间有几个朋友咨询地图跳转和任务系统具体怎么做,为了证明该系列文章会继续写下去,这一次先来实现一下地图跳转。
先看一下效果预览:
地图跳转,顾名思义,就是从一张地图跳转到另一张地图(这不是废话嘛),体现在游戏程序中,就是当人物走到了某一个坐标区域,或者在游戏中触发了某事件之后,游戏程序将当前地图和地图上的所有东西清除,简单说就是清空画面,然后再加载另一张地图并显示。
我们把游戏中事件的触发归类到任务系统中,本次来实现人物移动到某个坐标区域后的地图跳转,要实现这一过程,大约是下面的四个步骤:
1,地图跳转的坐标区域的设置
2,人物移动时,与地图上所设置的坐标区域的判定
3,画面清空
4,新地图加载
画面清空和地图加载两个功能在前面的章节已经实现完毕,所以这一次我们重点来看前面的两步。
首先,来看一下接下来要实现的脚本。
//RPG地图中各函数初始化开始 function.start; function mapR02(); //地图跳转 endfunction; function.end; //RPG地图中实时判定部分 loop.start; //添加地图坐标区域判定,参数(人物序号,起始坐标x,起始坐标y,终了坐标x,终了坐标y,触发函数名称) RPGCharacter.atCoordinate(1,43,27,45,29,mapR02); loop.end;其中的mapR02是创建函数脚本,不了解的朋友可以看一下第一章的内容。
loop.start;和loop.end;中间的脚本用来处理游戏中需要实时判定的内容,比如这次的地图跳转,每次人物移动都需要判断一次地图是否应该发生跳转。
atCoordinate这个脚本函数是设定地图跳转区域,几个参数都在上面做了注释,不多说了,下面看一下具体实现。
LRPGMapScript.loop=function(){ var script = LGlobal.script; var lineValue = LMath.trim(script.lineList.shift()); if(lineValue.length == 0){ LRPGMapScript.loop(); return; } trace("LRPGMapScript loop lineValue = " + lineValue); if(lineValue == "loop.end"){ LRPGMapScript.analysis(); return; } var params,i; var start = lineValue.indexOf("("); var end = lineValue.indexOf(")"); switch(lineValue.substr(0,start)){ case "RPGCharacter.atCoordinate": params = lineValue.substring(start+1,end).split(","); LRPGObject.RPGMap.addCoordinateCheck.apply(LRPGObject.RPGMap,params); LRPGMapScript.loop(); break; default: LRPGMapScript.loop(); } };
直接贴了全部代码,是不是太敷衍了?哈哈,其实这些代码都是依葫芦画瓢,跟前面介绍过的一样,就是解析一下函数名和参数,重点是解析之后,调用了
LRPGObject.RPGMap.addCoordinateCheck.apply(LRPGObject.RPGMap,params);
LRPGObject.RPGMap是之前设定好的MapController的实例,
MapController.prototype.addCoordinateCheck=function(index,startX,startY,endX,endY,funName){ this.model.addCoordinateCheck(index,startX,startY,endX,endY,funName); };在这个控制器里面调用了模型的同名函数。
MapModel.prototype.addCoordinateCheck=function(index,startX,startY,endX,endY,funName){ var self = this; var child = { "index":index, "rect":new LRectangle( parseInt(startX), parseInt(startY), parseInt(endX)-parseInt(startX), parseInt(endY)-parseInt(startY) ), "fun":funName }; self.atRect.push(child); };
把相应的参数,保存到控制器的atRect数组中,然后在人物移动的时候,和这个数组中的信息做判定就可以了。
因为人物移动是在Character类中实现的,所以修改Character类,在人物移动完一个坐标之后,与地图模型的atRect做一下判断,判断部分如下。
Character.prototype.checkCoordinate = function(controller,initFlag){ var self = this; var model=controller.model,i,obj,rect,rects = model.atRect,coor; for(i=0;i<rects.length;i++){ obj = rects[i]; rect = obj.rect; if(obj.index != self.index){ continue; } coor = self.getTo(); if(coor[0] >= rect.x && coor[0] <= rect.right && coor[1] >= rect.y && coor[1] <= rect.bottom){ if(self.coordinateRects[obj.fun]){ continue; } self.coordinateRects[obj.fun] = true; if(initFlag){ continue; } ScriptFunction.analysis("Call."+obj.fun + "();"); }else if(self.coordinateRects[obj.fun]){ self.coordinateRects[obj.fun]= null; } } };人物移动到指定坐标区域后,将该区域的函数信息添加到self.coordinateRects里,离开区域后,将self.coordinateRects中的信息删除。之所以这么做是为了防止2次触发同一事件。另外,initFlag的作用是在地图初始化的时候用的,因为有时候,人物可能一开始就已经站在指定的坐标区域中,而事件的判定是需要人物发生移动走入该区域才触发的,比如人物走进一间屋子,可能地图加载完后人物就站在门口,而人物走到门口的时候应该是走出这间的区域范围,所以,一开始将该地区设置为已判断,等人物离开门口区域,再走回去的时候,就正常判断离开屋子了。这个initFlag就是起到了这个作用,将人物一开始所站的位置设置为已判断。
上面的代码可以看到,当人物走到了指定的区域后,就会调用相应的脚本函数。但是,目前这个脚本函数是这个样子的。
function mapR02(); //地图跳转 endfunction;是一个空函数,我们在里面添加点东西,如下。
function mapR02(); //清空画面 Layer.clear(-); //读取下一地图脚本 Load.script(script/R02.ls); endfunction;看到了吧,先清空画面,然后读取另一个地图脚本文件,就这么两行代码就可以实现地图跳转了。不信看下面的图,已经到了第二张地图了。
稍等了,虽然我们已经可以设定地图跳转的坐标区域了,但是在画面上我们什么也看不到,看下面的图,谁知道走到哪里会发生跳转啊。
那怎么办呢?不用担心,我们来给地图的跳转区域做个记号。
先准备一个Entrance类,放到Libraries下。
function Entrance(){ var self = this; base(self,LSprite,[]); loader = new LLoader(); loader.parent = self; loader.addEventListener(LEvent.COMPLETE,self.loadOver); loader.load(LMvc.IMG_PATH+"items/entrance.png","bitmapData"); } Entrance.prototype.loadOver = function(event){ var self = event.target.parent; var bitmapData = new LBitmapData(event.currentTarget,0,0,148,142); var list = LGlobal.divideCoordinate(444,142,1,3); self.anime = new LAnimationTimeline(bitmapData,list); self.anime.speed = 4; self.anime.x = -70; self.anime.y = -70; self.addChild(self.anime); };
有了记号的类了,怎么添加呢,比如我们设定以下面的脚本来往地图上添加一个元件。
RPGItem.add(entrance,44,28);这个脚本解析起来也很简单,下面是脚本解析部分。
LRPGItemScript = function(){}; LRPGItemScript.analysis=function(value){ var start = value.indexOf("("); var end = value.indexOf(")"); switch(value.substr(0,start)){ case "RPGItem.add": LRPGItemScript.add(value,start,end); break; default: LGlobal.script.analysis(); } }; LRPGItemScript.add = function (value,start,end){ var params = value.substring(start+1,end).split(","); if(LRPGObject.RPGMap){ LRPGObject.RPGMap.addItem.apply(LRPGObject.RPGMap,params); } LGlobal.script.analysis(); };控制器和视图中的addItem函数如下:
//控制器部分 MapController.prototype.addItem = function(name,x,y){ this.view.addItem(name,parseInt(x),parseInt(y)); }; ...... //视图部分 MapView.prototype.addItem = function(name,x,y){ var self = this,item; switch(name){ case "entrance": item = new Entrance(); item.x = x*self.model.stepWidth; item.y = y*self.model.stepHeight; self.mapLayer.addChild(item); break; } };看下效果如何:
咦!效果还不错嘛,哈。地图跳转后,也给酒店里加上跳转记号,看效果:
好了,自己来测试下效果吧,URL连接如下:
http://lufylegend.com/demo/test/lsharp/rpg-lshape-04/index.html
最后,给出本次的代码下载:
http://lufylegend.com/demo/test/lsharp/rpg-lshape-04/rpg-lshape-04.zip
《游戏脚本的设计与开发》系列文章目录
http://blog.****.net/lufy_legend/article/details/8888787
- 2楼shanpolei昨天 19:13
- 太好了,可以继续学习了,照着这样的学习步骤,现在该学习做战斗系统了,希望能尽快学习战斗系统和装备系统方面的知识!
- Re: lufy_Legend昨天 19:34
- 回复shanpolein战斗系统作为RPG游戏的一个重要组成部分,当然是很重要的,n但是在此之前,必须先完成另一个关键的系统,就是任务系统,没有它的话,游戏的各个剧情和战斗就无法连接起来了。
- Re: shanpolei昨天 19:35
- 回复lufy_Legendn也是,希望可以尽快更新。n还有就是怎么这次下载的代码运行时在游戏界面下方会显示游戏中的代码,这是怎么回事?还想请教
- Re: lufy_Legend昨天 20:27
- 回复shanpolein因为开启了debug模式,把index.html里的LGlobal.setDebug(true);注释掉就行了。
- 1楼u014156468昨天 19:03
- [code=plain]nn[/code]好漂亮