前两篇,RPG的开发已经实现了添加地图和添加游戏人物,本篇来实现地图的卷轴滚动和人物对话的实现,效果如下
本次开发,更新了一下库件至1.3,请点击下面的链接,下载库件1.3版以上版本
http://code.google.com/p/legendforhtml5programming/downloads/list
地图的滚动
关于地图的滚动原理,可以参照下图
按照上图说明,实现地图滚动,只需要先把即将出现的地图(图中黄色部分)画上,然后滚动地图,待地图滚动完毕之后,将屏幕之外的部分(图中绿色部分)移除
首先要添加一个变量来控制地图是否滚动
//地图滚动
var mapmove = false;
- 1.
- 2.
然后,在人物移动的时候,判断地图是否需要滚动
/**
* 地图是否滚动
**/
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;
}
};
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
在移动过程中,判断地图是否处于滚动状态,如果地图处于滚动,则滚动地图,否则移动人物
/**
* 开始移动
**/
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);
}
};
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
最后,将地图的数组和地形扩大为大于屏幕大小
//地图图片数组
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]
];
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
为了实现地图滚动,修改添加地图的方法,根据参数来实现添加上面图片的黄色地图部分
//添加地图
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();
//在地图层上,画出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--;
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
看一下效果如下
#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();
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
在完善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:"真的吗?一定要想想办法啊。"}
)
};
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
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 < 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;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
效果看下图
游戏演示地址:http://fsanguo.comoj.com/html5/rpg3/index.html
之前其他地方也稍微做了修改,具体修改请看源代码,此次更新源代码,下载地址如下:http://fsanguo.comoj.com/html5/rpg5/rpg5.rar
原文链接:http://www.cnblogs.com/html5cn/articles/2337032.html
【编辑推荐】
- HTML 5开发RPG游戏之一(地图人物实现)
- HTML 5开发RPG游戏之二(跑起来吧英雄)
- HTML 5开发RPG游戏之四(游戏脚本化)
- 开发HTML5跨平台游戏相关经验
- HTML 5开发的优秀网页游戏