HTML 5開發(fā)RPG游戲之三(卷軸和對話)
前兩篇,RPG的開發(fā)已經(jīng)實現(xiàn)了添加地圖和添加游戲人物,本篇來實現(xiàn)地圖的卷軸滾動和人物對話的實現(xiàn),效果如下
本次開發(fā),更新了一下庫件至1.3,請點擊下面的鏈接,下載庫件1.3版以上版本
http://code.google.com/p/legendforhtml5programming/downloads/list
地圖的滾動
關(guān)于地圖的滾動原理,可以參照下圖
按照上圖說明,實現(xiàn)地圖滾動,只需要先把即將出現(xiàn)的地圖(圖中黃色部分)畫上,然后滾動地圖,待地圖滾動完畢之后,將屏幕之外的部分(圖中綠色部分)移除
首先要添加一個變量來控制地圖是否滾動
- //地圖滾動
- 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;
- }
- };
在移動過程中,判斷地圖是否處于滾動狀態(tài),如果地圖處于滾動,則滾動地圖,否則移動人物
- /**
- * 開始移動
- **/
- Character.prototype.onmove = function (){
- var self = this;
- //設(shè)定一個移動步長中的移動次數(shù)
- var ml_cnt = 4;
- //計算一次移動的長度
- var ml = STEP/ml_cnt;
- //根據(jù)移動方向,開始移動
- 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++;
- //當(dāng)移動次數(shù)等于設(shè)定的次數(shù),開始判斷是否繼續(xù)移動
- if(self.moveIndex >= ml_cnt){
- //一個地圖步長移動完成后,如果地圖處于滾動狀態(tài),則移除多余地圖塊
- if(mapmove)delMap();
- self.moveIndex = 0;
- //如果已經(jīng)松開移動鍵,或者前方為障礙物,則停止移動,否則繼續(xù)移動
- 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);
- }
- };
最后,將地圖的數(shù)組和地形擴大為大于屏幕大小
- //地圖圖片數(shù)組
- 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]
- ];
- //地圖地形數(shù)組
- 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]
- ];
為了實現(xiàn)地圖滾動,修改添加地圖的方法,根據(jù)參數(shù)來實現(xiàn)添加上面圖片的黃色地圖部分
- //添加地圖
- 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){
- //地圖圖片數(shù)據(jù)
- bitmapdata = new LBitmapData(imglist["map"]);
- //將地圖圖片拆分,得到拆分后的各個小圖片的坐標(biāo)數(shù)組
- 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++){
- //從地圖數(shù)組中得到相應(yīng)位置的圖片坐標(biāo)
- index = map[i-mapY][j-mapX];
- //小圖片的豎坐標(biāo)
- indexY = Math.floor(index /10);
- //小圖片的橫坐標(biāo)
- indexX = index - indexY*10;
- //得到小圖片
- bitmapdata = new LBitmapData(imglist["map"],indexX*32,indexY*32,32,32);
- bitmap = new LBitmap(bitmapdata);
- //設(shè)置小圖片的顯示位置
- 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#
人物的對話
對話的實現(xiàn),在點擊控制按鈕的方形按鈕時添加,所以,先在鼠標(biāo)抬起的時候,判斷是否點擊了方形按鈕
- 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()方法的時候,首先準(zhǔn)備好對話的內(nèi)容
- var talkScriptList = {
- "talk1":new Array(
- {img:"m",name:"鳴人",msg:"我是木葉村的鳴人,你是誰?"},
- {img:"n",name:"黑衣忍者甲",msg:"你就是鳴人?九尾還在你身體里嗎?"}
- ),
- "talk2":new Array(
- {img:"n",name:"黑衣忍者乙",msg:"鳴人,聽說忍者大戰(zhàn)就要開始了。"},
- {img:"m",name:"鳴人",msg:"真的嗎?一定要想想辦法啊。"}
- )
- };
talk1,talk2中talk后面的數(shù)字,代表人物的編號,其中每個對話單位的img為人物的頭像,name為人物的名稱,msg為對話的內(nèi)容
添加對話時的做法是,當(dāng)點擊方形按鈕后,判斷小鳴人前方是否有人,如果有人,則將這個人物的編號取出來,再從上面的數(shù)組中獲取相應(yīng)的對話內(nèi)容,然后,將相應(yīng)的內(nèi)容顯示到游戲屏幕上,具體實現(xiàn)代碼如下
- //對話內(nèi)容
- var talkScript;
- var talkScriptList = {
- "talk1":new Array(
- {img:"m",name:"鳴人",msg:"我是木葉村的鳴人,你是誰?"},
- {img:"n",name:"黑衣忍者甲",msg:"你就是鳴人?九尾還在你身體里嗎?"}
- ),
- "talk2":new Array(
- {img:"n",name:"黑衣忍者乙",msg:"鳴人,聽說忍者大戰(zhàn)就要開始了。"},
- {img:"m",name:"鳴人",msg:"真的嗎?一定要想想辦法啊。"}
- )
- };
- //對話序號
- var talkIndex = 0;
- //對話中
- var talking = false;
- /**
- * 添加對話
- * */
- function addTalk(){
- //如果對話內(nèi)容為空,則開始判斷是否可以對話
- 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;
- }
- }
- }
- //如果前方?jīng)]有npc,則返回
- if(talkScript == null)return;
- }
- //將對話層清空
- talkLayer.removeAllChild();
- //當(dāng)對話開始,且按照順序進行對話
- if(talkIndex < talkScript.length){
- //得到對話內(nèi)容
- 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);
- //對話內(nèi)容
- var msg = new LTextField();
- msg.x = 110;
- msg.y = 55;
- msg.color = "#FFFFFF";
- msg.text = talkObject.msg;
- talkLayer.addChild(msg);
- //對話內(nèi)容逐字顯示
- msg.wind();
- talkLayer.x = 20;
- talkLayer.y = 50;
- talkIndex++;
- }else{
- //對話結(jié)束
- talkScript = null;
- }
- }
效果看下圖
游戲演示地址: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開發(fā)RPG游戲之一(地圖人物實現(xiàn))
- HTML 5開發(fā)RPG游戲之二(跑起來吧英雄)
- HTML 5開發(fā)RPG游戲之四(游戲腳本化)
- 開發(fā)HTML5跨平臺游戲相關(guān)經(jīng)驗
- HTML 5開發(fā)的優(yōu)秀網(wǎng)頁游戲