本次开发,更新了一下库件至1.3,请点击下面的链接,下载库件1.3版以上版本
地图的滚动
关于地图的滚动原理,可以参照下图
按照上图说明,实现地图滚动,只需要先把即将出现的地图(图中黄色部分)画上,然后滚动地图,待地图滚动完毕之后,将屏幕之外的部分(图中绿色部分)移除
首先要添加一个变量来控制地图是否滚动
- //地图滚动
- var mapmove = false;
然后,在人物移动的时候,判断地图是否需要滚动
1.
2. Character.prototype.checkMap = function (dir){
3. var self = this;
4. mapmove = false;
5. //如果不是英雄,则地图不需要滚动
6. if(!self.isHero)return;
7.
8. switch (dir){
9. case UP:
10. if(self.y + charaLayer.y> STEP)break;
11. if(mapLayer.y >= 0)break;
12. addMap(0,-1);
13. mapmove = true;
14. break;
15. case LEFT:
16. if(self.x + charaLayer.x > STEP)break;
17. if(mapLayer.x >= 0)break;
18. addMap(-1,0);
19. mapmove = true;
20. break;
21. case RIGHT:
22. if(self.x < 480 - 2*STEP)break;
23. if(480 - mapLayer.x >= map[0].length*STEP)break;
24. addMap(1,0);
25. mapmove = true;
26. break;
27. case DOWN:
28. if(self.y < 288 - 2*STEP)break;
29. if(288 - mapLayer.y >= map.length*STEP)break;
30. addMap(0,1);
31. mapmove = true;
32. break;
33. }
34. };
在移动过程中,判断地图是否处于滚动状态,如果地图处于滚动,则滚动地图,否则移动人物
1.
2. Character.prototype.onmove = function (){
3. var self = this;
4. //设定一个移动步长中的移动次数
5. var ml_cnt = 4;
6. //计算一次移动的长度
7. var ml = STEP/ml_cnt;
8. //根据移动方向,开始移动
9. switch (self.direction){
10. case UP:
11. if(mapmove){
12. mapLayer.y += ml;
13. charaLayer.y += ml;
14. }
15. self.y -= ml;
16. break;
17. case LEFT:
18. if(mapmove){
19. mapLayer.x += ml;
20. charaLayer.x += ml;
21. }
22. self.x -= ml;
23. break;
24. case RIGHT:
25. if(mapmove){
26. mapLayer.x -= ml;
27. charaLayer.x -= ml;
28. }
29. self.x += ml;
30. break;
31. case DOWN:
32. if(mapmove){
33. mapLayer.y -= ml;
34. charaLayer.y -= ml;
35. }
36. self.y += ml;
37. break;
38. }
39. self.moveIndex++;
40. //当移动次数等于设定的次数,开始判断是否继续移动
41. if(self.moveIndex >= ml_cnt){
42. //一个地图步长移动完成后,如果地图处于滚动状态,则移除多余地图块
43. if(mapmove)delMap();
44. self.moveIndex = 0;
45. //如果已经松开移动键,或者前方为障碍物,则停止移动,否则继续移动
46. if(!isKeyDown || !self.checkRoad()){
47. self.move = false;
48. return;
49. }else if(self.direction != self.direction_next){
50. self.direction = self.direction_next;
51. self.anime.setAction(self.direction);
52. }
53. //地图是否滚动
54. self.checkMap(self.direction);
55. }
56. };
最后,将地图的数组和地形扩大为大于屏幕大小
1. //地图图片数组
2. var map = [
3. [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],
4. [18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],
5. [18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],
6. [18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],
7. [18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],
8. [18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],
9. [18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],
10. [18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],
11. [18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],
12. [18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],
13. [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]
14. ];
15. //地图地形数组
16. var mapdata = [
17. [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
18. [1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],
19. [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],
20. [1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],
21. [1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],
22. [1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],
23. [1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],
24. [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
25. [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
26. [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
27. [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
28. ];
为了实现地图滚动,修改添加地图的方法,根据参数来实现添加上面图片的黄色地图部分
1. //添加地图
2. function addMap(cx,cy){
3. var i,j,index,indexX,indexY;
4. var bitmapdata,bitmap;
5. var mapX = mapLayer.x / STEP;
6. var mapY = mapLayer.y / STEP;
7. var mx = cx<0?-1:0,my = cy<0?-1:0;
8. if(imageArray == null){
9. //地图图片数据
10. bitmapdata = new LBitmapData(imglist["map"]);
11. //将地图图片拆分,得到拆分后的各个小图片的坐标数组
12. imageArray = LGlobal.divideCoordinate(bitmapdata.image.width,bitmapdata.image.height,10,10);
13. }
14. mapLayer.removeAllChild();
15. //在地图层上,画出15*10的小图片
16. for(i=my;i<9 +Math.abs(cy) && i-mapY < map.length;i++){
17. for(j=mx;j<15 +Math.abs(cx)&& j-mapX < map[0].length;j++){
18. //从地图数组中得到相应位置的图片坐标
19. index = map[i-mapY][j-mapX];
20. //小图片的竖坐标
21. indexY = Math.floor(index /10);
22. //小图片的横坐标
23. indexX = index - indexY*10;
24. //得到小图片
25. bitmapdata = new LBitmapData(imglist["map"],indexX*32,indexY*32,32,32);
26. bitmap = new LBitmap(bitmapdata);
27. //设置小图片的显示位置
28. bitmap.x = j*STEP - mapLayer.x;
29. bitmap.y = i*STEP - mapLayer.y;
30. //将小图片显示到地图层
31. mapLayer.addChild(bitmap);
32. }
33. }
34. }
35. //移除多余地图块
36. function delMap(){
37. var bitmap,i;
38. for(i=0;i<mapLayer.childList.length;i++){
39. bitmap = mapLayer.childList[i];
40. if(bitmap.x + mapLayer.x < 0 || bitmap.x + mapLayer.x >= 480 ||
41. bitmap.y + mapLayer.y < 0 || bitmap.y + mapLayer.y >= 288){
42. mapLayer.removeChild(bitmap);
43. i--;
44. }
45. }
46. }
看一下效果如下
人物的对话
对话的实现,在点击控制按钮的方形按钮时添加,所以,先在鼠标抬起的时候,判断是否点击了方形按钮
1. function onup(event){
2. isKeyDown = false;
3. if(event.offsetX >= ctrlLayer.x + 280 && event.offsetX <= ctrlLayer.x+330){
4. if(event.offsetY >= ctrlLayer.y+40 && event.offsetY <= ctrlLayer.y+100){
5. //对话
6. addTalk();
7. }
8. }
9. }
在完善addTalk()方法的时候,首先准备好对话的内容
1. var talkScriptList = {
2. "talk1":new Array(
3. {img:"m",name:"鸣人",msg:"我是木叶村的鸣人,你是谁?"},
4. {img:"n",name:"黑衣忍者甲",msg:"你就是鸣人?九尾还在你身体里吗?"}
5. ),
6. "talk2":new Array(
7. {img:"n",name:"黑衣忍者乙",msg:"鸣人,听说忍者大战就要开始了。"},
8. {img:"m",name:"鸣人",msg:"真的吗?一定要想想办法啊。"}
9. )
10. };
talk1,talk2中talk后面的数字,代表人物的编号,其中每个对话单位的img为人物的头像,name为人物的名称,msg为对话的内容
添加对话时的做法是,当点击方形按钮后,判断小鸣人前方是否有人,如果有人,则将这个人物的编号取出来,再从上面的数组中获取相应的对话内容,然后,将相应的内容显示到游戏屏幕上,具体实现代码如下
1. //对话内容
2. var talkScript;
3. var talkScriptList = {
4. "talk1":new Array(
5. {img:"m",name:"鸣人",msg:"我是木叶村的鸣人,你是谁?"},
6. {img:"n",name:"黑衣忍者甲",msg:"你就是鸣人?九尾还在你身体里吗?"}
7. ),
8. "talk2":new Array(
9. {img:"n",name:"黑衣忍者乙",msg:"鸣人,听说忍者大战就要开始了。"},
10. {img:"m",name:"鸣人",msg:"真的吗?一定要想想办法啊。"}
11. )
12. };
13. //对话序号
14. var talkIndex = 0;
15. //对话中
16. var talking = false;
17.
18.
19. function addTalk(){
20. //如果对话内容为空,则开始判断是否可以对话
21. if(talkScript == null){
22. var key,tx = player.x,ty = player.y;
23. switch (player.direction){
24. case UP:
25. ty -= STEP;
26. break;
27. case LEFT:
28. tx -= STEP;
29. break;
30. case RIGHT:
31. tx += STEP;
32. break;
33. case DOWN:
34. ty += STEP;
35. break;
36. }
37. for(key in charaLayer.childList){
38. //判断前面又没有npc,有则开始对话
39. if(charaLayer.childList[key].x == tx && charaLayer.childList[key].y == ty){
40. if(talkScriptList["talk"+charaLayer.childList[key].index]){
41. talkScript = talkScriptList["talk"+charaLayer.childList[key].index];
42. talkIndex = 0;
43. }
44. }
45. }
46. //如果前方没有npc,则返回
47. if(talkScript == null)return;
48. }
49. //将对话层清空
50. talkLayer.removeAllChild();
51. //当对话开始,且按照顺序进行对话
52. if(talkIndex < talkScript.length){
53. //得到对话内容
54. var talkObject = talkScript[talkIndex];
55. //对话背景
56. bitmapdata = new LBitmapData(imglist["talk"]);
57. bitmap = new LBitmap(bitmapdata);
58. bitmap.width = 330;
59. bitmap.height = 70;
60. bitmap.x = 100;
61. bitmap.y = 20;
62. bitmap.alpha = 0.7;
63. talkLayer.addChild(bitmap);
64. //对话头像
65. bitmapdata = new LBitmapData(imglist[talkObject.img]);
66. bitmap = new LBitmap(bitmapdata);
67. bitmap.x = 0;
68. bitmap.y = 0;
69. talkLayer.addChild(bitmap);
70. //对话人物名称
71. var name = new LTextField();
72. name.x = 110;
73. name.y = 30;
74. name.size = "14";
75. name.color = "#FFFFFF";
76. name.text = "[" + talkObject.name + "]";
77. talkLayer.addChild(name);
78. //对话内容
79. var msg = new LTextField();
80. msg.x = 110;
81. msg.y = 55;
82. msg.color = "#FFFFFF";
83. msg.text = talkObject.msg;
84. talkLayer.addChild(msg);
85. //对话内容逐字显示
86. msg.wind();
87. talkLayer.x = 20;
88. talkLayer.y = 50;
89. talkIndex++;
90. }else{
91. //对话结束
92. talkScript = null;
93. }
94. }
效果看下图
游戏演示地址
http://fsanguo.comoj.com/html5/rpg3/index.html
之前其他地方也稍微做了修改,具体修改请看源代码,此次更新源代码,下载地址如下
http://legend-demo.googlecode.com/files/rpg3.zip