前两篇,RPG的开发已经实现了添加地图和添加游戏人物,本篇来实现地图的卷轴滚动和人物对话的实现,效果如下
想要了解前两篇内容,请电击下面的链接
html5游戏开发-零基础开发RPG游戏-开源讲座(一)
http://blog.csdn.net/lufy_legend/article/details/7063316
html5游戏开发-零基础开发RPG游戏-开源讲座(二)-跑起来吧英雄
http://blog.csdn.net/lufy_legend/article/details/7076064
地图的滚动
关于地图的滚动原理,可以参照下图
按照上图说明,实现地图滚动,只需要先把即将出现的地图(图中黄色部分)画上,然后滚动地图,待地图滚动完毕之后,将屏幕之外的部分(图中绿色部分)移除
首先要添加一个变量来控制地图是否滚动
//地图滚动</p><p>var mapmove = false;
然后,在人物移动的时候,判断地图是否需要滚动
-
-
-
- Character.prototype.checkMap = function (dir){
- var self = this;
- mapmove = false;
-
- if(!self.isHero)return;
-
- switch (dir){
- case UP:
- if(self.y + charaLayer.y> STEP)break;
- if(mapLayer.y >= 0)break;
- addMap(0,-1);
- mapmove = true;
- break;
- case LEFT:
- if(self.x + charaLayer.x > STEP)break;
- if(mapLayer.x >= 0)break;
- addMap(-1,0);
- mapmove = true;
- break;
- case RIGHT:
- if(self.x < 480 – 2*STEP)break;
- if(480 – mapLayer.x >= map[0].length*STEP)break;
- addMap(1,0);
- mapmove = true;
- break;
- case DOWN:
- if(self.y < 288 – 2*STEP)break;
- if(288 – mapLayer.y >= map.length*STEP)break;
- addMap(0,1);
- mapmove = true;
- break;
- }
- };
/**</p><p> * 地图是否滚动</p><p> **/</p><p>Character.prototype.checkMap = function (dir){</p><p> var self = this;</p><p> mapmove = false;</p><p> //如果不是英雄,则地图不需要滚动</p><p> if(!self.isHero)return;</p><p> </p><p> switch (dir){</p><p> case UP:</p><p> if(self.y + charaLayer.y> STEP)break;</p><p> if(mapLayer.y >= 0)break;</p><p> addMap(0,-1);</p><p> mapmove = true;</p><p> break;</p><p> case LEFT:</p><p> if(self.x + charaLayer.x > STEP)break;</p><p> if(mapLayer.x >= 0)break;</p><p> addMap(-1,0);</p><p> mapmove = true;</p><p> break;</p><p> case RIGHT:</p><p> if(self.x < 480 - 2*STEP)break;</p><p> if(480 - mapLayer.x >= map[0].length*STEP)break;</p><p> addMap(1,0);</p><p> mapmove = true;</p><p> break;</p><p> case DOWN:</p><p> if(self.y < 288 - 2*STEP)break;</p><p> if(288 - mapLayer.y >= map.length*STEP)break;</p><p> addMap(0,1);</p><p> mapmove = true;</p><p> break;</p><p> }</p><p>};
在移动过程中,判断地图是否处于滚动状态,如果地图处于滚动,则滚动地图,否则移动人物
-
-
-
- Character.prototype.onmove = function (){
- var self = this;
-
- var ml_cnt = 4;
-
- var ml = STEP/ml_cnt;
-
- switch (self.direction){
- case UP:
- if(mapmove){
- mapLayer.y += ml;
- charaLayer.y += ml;
- }
- self.y -= ml;
- break;
- case LEFT:
- if(mapmove){
- mapLayer.x += ml;
- charaLayer.x += ml;
- }
- self.x -= ml;
- break;
- case RIGHT:
- if(mapmove){
- mapLayer.x -= ml;
- charaLayer.x -= ml;
- }
- self.x += ml;
- break;
- case DOWN:
- if(mapmove){
- mapLayer.y -= ml;
- charaLayer.y -= ml;
- }
- self.y += ml;
- break;
- }
- self.moveIndex++;
-
- if(self.moveIndex >= ml_cnt){
-
- if(mapmove)delMap();
- self.moveIndex = 0;
-
- if(!isKeyDown || !self.checkRoad()){
- self.move = false;
- return;
- }else if(self.direction != self.direction_next){
- self.direction = self.direction_next;
- self.anime.setAction(self.direction);
- }
-
- self.checkMap(self.direction);
- }
- };
/**</p><p> * 开始移动 </p><p> **/</p><p>Character.prototype.onmove = function (){</p><p> var self = this;</p><p> //设定一个移动步长中的移动次数</p><p> var ml_cnt = 4;</p><p> //计算一次移动的长度</p><p> var ml = STEP/ml_cnt;</p><p> //根据移动方向,开始移动</p><p> switch (self.direction){</p><p> case UP:</p><p> if(mapmove){</p><p> mapLayer.y += ml;</p><p> charaLayer.y += ml;</p><p> }</p><p> self.y -= ml;</p><p> break;</p><p> case LEFT:</p><p> if(mapmove){</p><p> mapLayer.x += ml;</p><p> charaLayer.x += ml;</p><p> }</p><p> self.x -= ml;</p><p> break;</p><p> case RIGHT:</p><p> if(mapmove){</p><p> mapLayer.x -= ml;</p><p> charaLayer.x -= ml;</p><p> }</p><p> self.x += ml;</p><p> break;</p><p> case DOWN:</p><p> if(mapmove){</p><p> mapLayer.y -= ml;</p><p> charaLayer.y -= ml;</p><p> }</p><p> self.y += ml;</p><p> break;</p><p> }</p><p> self.moveIndex++;</p><p> //当移动次数等于设定的次数,开始判断是否继续移动</p><p> if(self.moveIndex >= ml_cnt){</p><p> //一个地图步长移动完成后,如果地图处于滚动状态,则移除多余地图块</p><p> if(mapmove)delMap();</p><p> self.moveIndex = 0;</p><p> //如果已经松开移动键,或者前方为障碍物,则停止移动,否则继续移动</p><p> if(!isKeyDown || !self.checkRoad()){</p><p> self.move = false;</p><p> return;</p><p> }else if(self.direction != self.direction_next){</p><p> self.direction = self.direction_next;</p><p> self.anime.setAction(self.direction);</p><p> }</p><p> //地图是否滚动</p><p> self.checkMap(self.direction);</p><p> }</p><p>};
最后,将地图的数组和地形扩大为大于屏幕大小
-
- var map = [
- [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],
- [18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],
- [18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],
- [18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],
- [18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],
- [18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],
- [18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],
- [18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],
- [18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],
- [18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],
- [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]
- ];
-
- var mapdata = [
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
- [1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],
- [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],
- [1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],
- [1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],
- [1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],
- [1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
- [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
- [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
- ];
//地图图片数组</p><p>var map = [</p><p>[18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],</p><p>[18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],</p><p>[18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],</p><p>[18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],</p><p>[18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],</p><p>[18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],</p><p>[18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],</p><p>[18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],</p><p>[18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],</p><p>[18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],</p><p>[18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]</p><p>];</p><p>//地图地形数组</p><p>var mapdata = [</p><p>[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],</p><p>[1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],</p><p>[1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],</p><p>[1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],</p><p>[1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],</p><p>[1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],</p><p>[1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],</p><p>[1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],</p><p>[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],</p><p>[1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],</p><p>[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]</p><p>];
为了实现地图滚动,修改添加地图的方法,根据参数来实现添加上面图片的黄色地图部分
-
- function addMap(cx,cy){
- var i,j,index,indexX,indexY;
- var bitmapdata,bitmap;
- var mapX = mapLayer.x / STEP;
- var mapY = mapLayer.y / STEP;
- var mx = cx<0?-1:0,my = cy<0?-1:0;
- if(imageArray == null){
-
- bitmapdata = new LBitmapData(imglist[“map”]);
-
- imageArray = LGlobal.divideCoordinate(bitmapdata.image.width,bitmapdata.image.height,10,10);
- }
- mapLayer.removeAllChild();
-
- for(i=my;i<9 +Math.abs(cy) && i-mapY < map.length;i++){
- for(j=mx;j<15 +Math.abs(cx)&& j-mapX < map[0].length;j++){
-
- index = map[i-mapY][j-mapX];
-
- indexY = Math.floor(index /10);
-
- indexX = index – indexY*10;
-
- bitmapdata = new LBitmapData(imglist[“map”],indexX*32,indexY*32,32,32);
- bitmap = new LBitmap(bitmapdata);
-
- bitmap.x = j*STEP – mapLayer.x;
- bitmap.y = i*STEP – mapLayer.y;
-
- mapLayer.addChild(bitmap);
- }
- }
- }
-
- function delMap(){
- var bitmap,i;
- for(i=0;i<mapLayer.childList.length;i++){
- bitmap = mapLayer.childList[i];
- if(bitmap.x + mapLayer.x < 0 || bitmap.x + mapLayer.x >= 480 ||
- bitmap.y + mapLayer.y < 0 || bitmap.y + mapLayer.y >= 288){
- mapLayer.removeChild(bitmap);
- i–;
- }
- }
- }
//添加地图</p><p>function addMap(cx,cy){</p><p> var i,j,index,indexX,indexY;</p><p> var bitmapdata,bitmap;</p><p> var mapX = mapLayer.x / STEP;</p><p> var mapY = mapLayer.y / STEP;</p><p> var mx = cx<0?-1:0,my = cy<0?-1:0;</p><p> if(imageArray == null){</p><p> //地图图片数据</p><p> bitmapdata = new LBitmapData(imglist["map"]);</p><p> //将地图图片拆分,得到拆分后的各个小图片的坐标数组</p><p> imageArray = LGlobal.divideCoordinate(bitmapdata.image.width,bitmapdata.image.height,10,10);</p><p> }</p><p> mapLayer.removeAllChild();</p><p> //在地图层上,画出15*10的小图片</p><p> for(i=my;i<9 +Math.abs(cy) && i-mapY < map.length;i++){</p><p> for(j=mx;j<15 +Math.abs(cx)&& j-mapX < map[0].length;j++){</p><p> //从地图数组中得到相应位置的图片坐标</p><p> index = map[i-mapY][j-mapX];</p><p> //小图片的竖坐标</p><p> indexY = Math.floor(index /10);</p><p> //小图片的横坐标</p><p> indexX = index - indexY*10;</p><p> //得到小图片</p><p> bitmapdata = new LBitmapData(imglist["map"],indexX*32,indexY*32,32,32);</p><p> bitmap = new LBitmap(bitmapdata);</p><p> //设置小图片的显示位置</p><p> bitmap.x = j*STEP - mapLayer.x;</p><p> bitmap.y = i*STEP - mapLayer.y;</p><p> //将小图片显示到地图层</p><p> mapLayer.addChild(bitmap);</p><p> }</p><p> }</p><p>}</p><p>//移除多余地图块</p><p>function delMap(){</p><p> var bitmap,i;</p><p> for(i=0;i<mapLayer.childList.length;i++){</p><p> bitmap = mapLayer.childList[i];</p><p> if(bitmap.x + mapLayer.x < 0 || bitmap.x + mapLayer.x >= 480 || </p><p> bitmap.y + mapLayer.y < 0 || bitmap.y + mapLayer.y >= 288){</p><p> mapLayer.removeChild(bitmap);</p><p> i--;</p><p> }</p><p> }</p><p>}
看一下效果如下
人物的对话
对话的实现,在点击控制按钮的方形按钮时添加,所以,先在鼠标抬起的时候,判断是否点击了方形按钮
- function onup(event){
- isKeyDown = false;
- if(event.offsetX >= ctrlLayer.x + 280 && event.offsetX <= ctrlLayer.x+330){
- if(event.offsetY >= ctrlLayer.y+40 && event.offsetY <= ctrlLayer.y+100){
-
- addTalk();
- }
- }
- }
function onup(event){</p><p> isKeyDown = false;</p><p> if(event.offsetX >= ctrlLayer.x + 280 && event.offsetX <= ctrlLayer.x+330){</p><p> if(event.offsetY >= ctrlLayer.y+40 && event.offsetY <= ctrlLayer.y+100){</p><p> //对话</p><p> addTalk();</p><p> }</p><p> }</p><p>}
在完善addTalk()方法的时候,首先准备好对话的内容
- var talkScriptList = {
- “talk1”:new Array(
- {img:“m”,name:“鸣人”,msg:“我是木叶村的鸣人,你是谁?”},
- {img:“n”,name:“黑衣忍者甲”,msg:“你就是鸣人?九尾还在你身体里吗?”}
- ),
- “talk2”:new Array(
- {img:“n”,name:“黑衣忍者乙”,msg:“鸣人,听说忍者大战就要开始了。”},
- {img:“m”,name:“鸣人”,msg:“真的吗?一定要想想办法啊。”}
- )
- };
var talkScriptList = {</p><p> "talk1":new Array(</p><p> {img:"m",name:"鸣人",msg:"我是木叶村的鸣人,你是谁?"},</p><p> {img:"n",name:"黑衣忍者甲",msg:"你就是鸣人?九尾还在你身体里吗?"}</p><p> ),</p><p> "talk2":new Array(</p><p> {img:"n",name:"黑衣忍者乙",msg:"鸣人,听说忍者大战就要开始了。"},</p><p> {img:"m",name:"鸣人",msg:"真的吗?一定要想想办法啊。"}</p><p> )</p><p>};
talk1,talk2中talk后面的数字,代表人物的编号,其中每个对话单位的img为人物的头像,name为人物的名称,msg为对话的内容
添加对话时的做法是,当点击方形按钮后,判断小鸣人前方是否有人,如果有人,则将这个人物的编号取出来,再从上面的数组中获取相应的对话内容,然后,将相应的内容显示到游戏屏幕上,具体实现代码如下
-
- var talkScript;
- var talkScriptList = {
- “talk1”:new Array(
- {img:“m”,name:“鸣人”,msg:“我是木叶村的鸣人,你是谁?”},
- {img:“n”,name:“黑衣忍者甲”,msg:“你就是鸣人?九尾还在你身体里吗?”}
- ),
- “talk2”:new Array(
- {img:“n”,name:“黑衣忍者乙”,msg:“鸣人,听说忍者大战就要开始了。”},
- {img:“m”,name:“鸣人”,msg:“真的吗?一定要想想办法啊。”}
- )
- };
-
- var talkIndex = 0;
-
- var talking = false;
-
-
-
-
- function addTalk(){
-
- if(talkScript == null){
- var key,tx = player.x,ty = player.y;
- switch (player.direction){
- case UP:
- ty -= STEP;
- break;
- case LEFT:
- tx -= STEP;
- break;
- case RIGHT:
- tx += STEP;
- break;
- case DOWN:
- ty += STEP;
- break;
- }
- for(key in charaLayer.childList){
-
- if(charaLayer.childList[key].x == tx && charaLayer.childList[key].y == ty){
- if(talkScriptList[“talk”+charaLayer.childList[key].index]){
- talkScript = talkScriptList[“talk”+charaLayer.childList[key].index];
- talkIndex = 0;
- }
- }
- }
-
- if(talkScript == null)return;
- }
-
- talkLayer.removeAllChild();
-
- if(talkIndex < talkScript.length){
-
- var talkObject = talkScript[talkIndex];
-
- bitmapdata = new LBitmapData(imglist[“talk”]);
- bitmap = new LBitmap(bitmapdata);
- bitmap.width = 330;
- bitmap.height = 70;
- bitmap.x = 100;
- bitmap.y = 20;
- bitmap.alpha = 0.7;
- talkLayer.addChild(bitmap);
-
- bitmapdata = new LBitmapData(imglist[talkObject.img]);
- bitmap = new LBitmap(bitmapdata);
- bitmap.x = 0;
- bitmap.y = 0;
- talkLayer.addChild(bitmap);
-
- var name = new LTextField();
- name.x = 110;
- name.y = 30;
- name.size = “14”;
- name.color = “#FFFFFF”;
- name.text = “[“ + talkObject.name + “]”;
- talkLayer.addChild(name);
-
- var msg = new LTextField();
- msg.x = 110;
- msg.y = 55;
- msg.color = “#FFFFFF”;
- msg.text = talkObject.msg;
- talkLayer.addChild(msg);
-
- msg.wind();
- talkLayer.x = 20;
- talkLayer.y = 50;
- talkIndex++;
- }else{
-
- talkScript = null;
- }
- }
//对话内容</p><p>var talkScript;</p><p>var talkScriptList = {</p><p> "talk1":new Array(</p><p> {img:"m",name:"鸣人",msg:"我是木叶村的鸣人,你是谁?"},</p><p> {img:"n",name:"黑衣忍者甲",msg:"你就是鸣人?九尾还在你身体里吗?"}</p><p> ),</p><p> "talk2":new Array(</p><p> {img:"n",name:"黑衣忍者乙",msg:"鸣人,听说忍者大战就要开始了。"},</p><p> {img:"m",name:"鸣人",msg:"真的吗?一定要想想办法啊。"}</p><p> )</p><p>};</p><p>//对话序号</p><p>var talkIndex = 0;</p><p>//对话中</p><p>var talking = false;</p><p>/**</p><p> * 添加对话</p><p> * */</p><p>function addTalk(){</p><p> //如果对话内容为空,则开始判断是否可以对话</p><p> if(talkScript == null){</p><p> var key,tx = player.x,ty = player.y;</p><p> switch (player.direction){</p><p> case UP:</p><p> ty -= STEP;</p><p> break;</p><p> case LEFT:</p><p> tx -= STEP;</p><p> break;</p><p> case RIGHT:</p><p> tx += STEP;</p><p> break;</p><p> case DOWN:</p><p> ty += STEP;</p><p> break;</p><p> }</p><p> for(key in charaLayer.childList){</p><p> //判断前面又没有npc,有则开始对话</p><p> if(charaLayer.childList[key].x == tx && charaLayer.childList[key].y == ty){</p><p> if(talkScriptList["talk"+charaLayer.childList[key].index]){</p><p> talkScript = talkScriptList["talk"+charaLayer.childList[key].index];</p><p> talkIndex = 0;</p><p> }</p><p> }</p><p> }</p><p> //如果前方没有npc,则返回</p><p> if(talkScript == null)return;</p><p> }</p><p> //将对话层清空</p><p> talkLayer.removeAllChild();</p><p> //当对话开始,且按照顺序进行对话</p><p> if(talkIndex < talkScript.length){</p><p> //得到对话内容</p><p> var talkObject = talkScript[talkIndex];</p><p> //对话背景</p><p> bitmapdata = new LBitmapData(imglist["talk"]);</p><p> bitmap = new LBitmap(bitmapdata);</p><p> bitmap.width = 330;</p><p> bitmap.height = 70;</p><p> bitmap.x = 100;</p><p> bitmap.y = 20;</p><p> bitmap.alpha = 0.7;</p><p> talkLayer.addChild(bitmap);</p><p> //对话头像</p><p> bitmapdata = new LBitmapData(imglist[talkObject.img]);</p><p> bitmap = new LBitmap(bitmapdata);</p><p> bitmap.x = 0;</p><p> bitmap.y = 0;</p><p> talkLayer.addChild(bitmap);</p><p> //对话人物名称</p><p> var name = new LTextField();</p><p> name.x = 110;</p><p> name.y = 30;</p><p> name.size = "14";</p><p> name.color = "#FFFFFF";</p><p> name.text = "[" + talkObject.name + "]";</p><p> talkLayer.addChild(name);</p><p> //对话内容</p><p> var msg = new LTextField();</p><p> msg.x = 110;</p><p> msg.y = 55;</p><p> msg.color = "#FFFFFF";</p><p> msg.text = talkObject.msg;</p><p> talkLayer.addChild(msg);</p><p> //对话内容逐字显示</p><p> msg.wind();</p><p> talkLayer.x = 20;</p><p> talkLayer.y = 50;</p><p> talkIndex++;</p><p> }else{</p><p> //对话结束</p><p> talkScript = null;</p><p> }</p><p>}
效果看下图
游戏演示地址
http://lufylegend.com/demo/rpg/index.html
lufylegend.js引擎包内包含这个demo,请直接下载lufylegend.js引擎,查看引擎包内源码
lufylegend.js引擎下载地址
http://lufylegend.com/lufylegend
下一篇,将研究地图的切换,和如何将游戏脚本化,请大家多支持
html5游戏开发-零基础开发RPG游戏-开源讲座(一)
http://blog.csdn.net/lufy_legend/article/details/7063316
html5游戏开发-零基础开发RPG游戏-开源讲座(二)-跑起来吧英雄
http://blog.csdn.net/lufy_legend/article/details/7076064
lufylegend.js引擎的官方网址
http://lufylegend.com/lufylegend
来源URL:http://blog.csdn.net/lufy_legend/article/details/7094567