PHP前端开发

html5游戏开发-零基础开发RPG游戏-开源讲座(三)-卷轴&对话实现

百变鹏仔 2个月前 (10-18) #H5教程
文章标签 卷轴

前两篇,rpg的开发已经实现了添加地图和添加游戏人物,本篇来实现地图的卷轴滚动和人物对话的实现,效果如下


地图的滚动

关于地图的滚动原理,可以参照下图

立即学习“前端免费学习笔记(深入)”;

按照上图说明,实现地图滚动,只需要先把即将出现的地图(中黄色部分)画上,然后滚动地图,待地图滚动完毕之后,将屏幕之外的部分(图中绿色部分)移除

首先要添加一个变量来控制地图是否滚动

//地图滚动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;}};

在移动过程中,判断地图是否处于滚动状态,如果地图处于滚动,则滚动地图,否则移动人物

/** * 开始移动  **/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);}};

最后,将地图的数组和地形扩大为大于屏幕大小

//地图图片数组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]];

为了实现地图滚动,修改添加地图的方法,根据参数来实现添加上面图片的黄色地图部分

//添加地图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.pideCoordinate(bitmapdata.image.width,bitmapdata.image.height,10,10);}mapLayer.removeAllChild();//在地图层上,画出15*10的小图片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--;	}}}

看一下效果如下


人物的对话

对话的实现,在点击控制按钮的方形按钮时添加,所以,先在鼠标抬起的时候,判断是否点击了方形按钮

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();	}}}

在完善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:"真的吗?一定要想想办法啊。"}	)};

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){		//判断前面又没有npc,有则开始对话		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;			}		}	}	//如果前方没有npc,则返回	if(talkScript == null)return;}//将对话层清空talkLayer.removeAllChild();//当对话开始,且按照顺序进行对话if(talkIndex 

效果看下图


游戏演示地址

http://lufylegend.com/demo/rpg/index.html

lufylegend.js引擎包内包含这个demo,请直接下载lufylegend.js引擎,查看引擎包内源码

lufylegend.js引擎下载地址

http://lufylegend.com/lufylegend