html5遊戲開發-零基礎開發RPG遊戲-開源講座(二)-跑起來吧英雄

lufy發表於2013-05-27

本文章首發自我的部落格 http://blog.csdn.net/lufy_legend/article/details/7076064

上一篇中,已經詳細講解了,如何新增地圖,以及新增了一個遊戲人物,現在我們來新增控制事件,讓這個小英雄走動起來

我們已經給遊戲人物建立了一個Character類, 現在先來在類里加入

Character.prototype.changeDir = function (dir){
};
/**
 * 設定人物座標
 * @param x方向座標,y方向座標 
 **/
Character.prototype.setCoordinate = function (sx,sy){
};
/**
 * 獲取人物座標
 **/
Character.prototype.getCoordinate = function (){
};

changeDir 這個方法用來從外部控制人物方向和移動 要控制遊戲的人物,首先,我們要由控制事件,當觸發這個事件的時候,就來呼叫相應的方法,做我們想要的做的處理setCoordinate和getCoordinate是設定和得到人物當前的座標

首先,為了適應智慧手機,我們暫時不用鍵盤事件,而是用點選事件,所以我們先來新增兩個控制按鈕,在Main.js的gameInit方法的最下方,新增如下程式碼

//新增控制按鈕
    bitmapdata = new LBitmapData(imglist["e1"]);
    bitmap = new LBitmap(bitmapdata);
    bitmap.x = 0;
    bitmap.y = 0;
    ctrlLayer.addChild(bitmap);
    bitmapdata = new LBitmapData(imglist["e2"]);
    bitmap = new LBitmap(bitmapdata);
    bitmap.x = 280;
    bitmap.y = 30;
    ctrlLayer.addChild(bitmap);
    ctrlLayer.x = 40;
    ctrlLayer.y = 180;

執行程式碼,得到預覽如下 enter image description here 在新增控制事件之前,為了實現控制方便,我們先來新增幾個變數

    //方向變數
    var DOWN = 0;
    var LEFT = 1;
    var RIGHT = 2;
    var UP = 3;
    var STEP = 32;
    //點選狀態
    var isKeyDown = false;
STEP代表移動步長,因為地圖是有32*32的小圖片來組成的,所以我們設定人物移動的步長為32
方向變數的0,1,2,3分別對應下面圖片中的第1,2,3,4行的方向
![enter image description here][3]
之所以新增點選狀態,是因為,當我們按下移動按鈕沒有抬起的時候,人物應該始終處於移動狀態,所以用這個變數來區分,我們是否按下或者抬起好了,做好了準備工作,現在就開始新增移動事件
//新增點選控制事件
    backLayer.addEventListener(LMouseEvent.MOUSE_DOWN,ondown);
    backLayer.addEventListener(LMouseEvent.MOUSE_UP,onup);

function ondown(event){
    //根據點選位置,判斷移動方向
    if(event.offsetX >= ctrlLayer.x + 40 && event.offsetX <= ctrlLayer.x+80){
        if(event.offsetY >= ctrlLayer.y && event.offsetY <= ctrlLayer.y+40){
            player.changeDir(UP);
        }else if(event.offsetY >= ctrlLayer.y+80 && event.offsetY <= ctrlLayer.y+120){
            player.changeDir(DOWN);
        }
    }else if(event.offsetX >= ctrlLayer.x && event.offsetX <= ctrlLayer.x+40){
        if(event.offsetY >= ctrlLayer.y +40 && event.offsetY <= ctrlLayer.y+80){
            player.changeDir(LEFT);
        }
    }else if(event.offsetX >= ctrlLayer.x+80 && event.offsetX <= ctrlLayer.x+120){
        if(event.offsetY >= ctrlLayer.y +40 && event.offsetY <= ctrlLayer.y+80){
            player.changeDir(RIGHT);
        }
    }
    isKeyDown = true;
}
function onup(event){
    isKeyDown = false;
}

這裡需要知道的是,在智慧手機裡,其實點選事件是TOUCH_START,TOUCH_MOVE,TOUCH_END事件 使用legendForHtml5Programming庫件的時候,只需要新增MOUSE_DOWN,MOUSE_MOVE,MOUSE_UP事件,然後庫件會自動判斷是載入TOUCH事件還是MOUSE事件 在ondown方法中,我們將isKeyDown的狀態變為true,表示我們正處於按下狀態 然後,根據我們點選的位置,來呼叫Character類的changeDir方法,並且傳入點選的方向

有了控制事件,現在的關鍵就在於changeDir方法,只要根據傳進來的值,來實現移動就可以了 我們試想,如果每次移動一個步長的話,那麼人物就會由一個小方格跳到令一個方格,而我們需要的是,讓它緩慢的移動到下一個方格,有一個移動的過程 為了實現這個過程,我們在移動的時候不是讓人物的座標馬上就改變,而是改變人物的狀態,由靜止到移動,然後處於移動狀態的時候,再讓人物一小步一小步的移動到目標點 修改Character類的構造器,如下

function Character(data,row,col,speed){
    base(this,LSprite,[]);
    var self = this;
    //設定人物動作速度
    self.speed = speed==null?3:speed;
    self.speedIndex = 0;
    //設定人物大小
    data.setProperties(0,0,data.image.width/col,data.image.height/row);
    //得到人物圖片拆分陣列
    var list = LGlobal.divideCoordinate(data.image.width,data.image.height,row,col);
    //設定人物動畫
    self.anime = new LAnimation(this,data,list);
    //調整人物位置
    self.anime.y -= 16;
    //設定不移動
    self.move = false;
    //在一個移動步長中的移動次數設定
    self.moveIndex = 0;
};

調整人物位置是因為,人物的圖片分割後,每個動作的大小為32*48,而地圖每個小格的大小是32*32, 然後設定人物狀態為不移動,然後修改changeDir 方法

/**
 * 改變人物方向
 **/
Character.prototype.changeDir = function (dir){
    var self = this;
    //如果正在移動,則無效
    if(!self.move){
        //設定人物方向
        self.direction = dir;
        //設定圖片動畫
        self.anime.setAction(dir);
        //開始移動
        self.move = true;
        self.moveIndex = 0;
    }
};

這裡要簡單說明一下LAnimation類的setAction方法,setAction(rowindex,colindex)方法有兩個引數,LAnimation裡傳進來的圖片陣列是一個二維陣列,這兩個引數分別可以改變目前顯示的圖片的動作,當然,也可以只傳其中一個引數。 我這次是將4*4的人物動作圖片分割為4*4的二維陣列傳給了LAnimation類,所以現在每一行圖片代表一個方向 人物狀態設定為移動後,就應該在迴圈事件裡開始一步步的移動了

/**
 * 迴圈事件 
 **/
Character.prototype.onframe = function (){
    var self = this;
    //人物動作速度控制
    if(self.speedIndex++ < self.speed)return;
    self.speedIndex = 0;
    //當人物可移動,則開始移動
    if(self.move)self.onmove();
    //人物動畫播放
    self.anime.onframe();
};
/**
 * 開始移動 
 **/
Character.prototype.onmove = function (){
    var self = this;
    //設定一個移動步長中的移動次數
    var ml_cnt = 4;
    //計算一次移動的長度
    var ml = STEP/ml_cnt;
    //根據移動方向,開始移動
    switch (self.direction){
        case UP:
            self.y -= ml;
            break;
        case LEFT:
            self.x -= ml;
            break;
        case RIGHT:
            self.x += ml;
            break;
        case DOWN:
            self.y += ml;
            break;
    }
    self.moveIndex++;
    //當移動次數等於設定的次數,開始判斷是否繼續移動
    if(self.moveIndex >= ml_cnt){
        self.moveIndex = 0;
        //如果已經鬆開移動鍵,則停止移動,否則繼續移動
        if(!isKeyDown){
            self.move = false;
            return;
        }
    }
};

這裡,我選擇了讓人物每個步長分四次進行移動,這樣就實現了緩慢移動的效果,執行程式,點選畫面中的方向鍵,看到了把,人物已經可以開始移動了,而且是緩慢的移動 enter image description here 但是,光這樣還是不行,我們發現,人物是可以移動了,但是他現在是超人,飛簷走壁無所不入,移動的暢通無阻 這就需要我們在移動過程中,加入移動判斷,看看是否可以移動, 為了實現這個判斷,我們必須要知道地圖什麼地方可以移動,什麼地方不可以移動 所以,我們需要一個地圖的地形,如下

//地圖地形陣列
var mapdata = [
[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,1],
[1,1,0,0,0,0,1,1,0,0,0,0,1,1,1],
[1,0,0,0,1,1,1,1,1,0,0,1,1,0,1],
[1,0,0,1,1,1,1,1,1,1,0,1,1,0,1],
[1,0,0,1,1,1,0,1,1,1,1,1,0,0,1],
[1,0,0,0,0,0,0,0,1,1,1,1,0,0,1],
[1,1,0,0,0,0,0,0,0,1,1,0,0,0,1],
[1,1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
];

地形陣列中,0代表可以移動,1代表障礙物,是不可移動的, 接下來,給Character類新增判斷方法

/**
 * 障礙物判斷
 * @param 判斷方向 
 **/
Character.prototype.checkRoad = function (dir){
    var self = this;
    var tox,toy,myCoordinate;
    //當判斷方向為空的時候,預設當前方向
    if(dir==null)dir=self.direction;
    //獲取人物座標
    myCoordinate = self.getCoordinate();
    //開始計算移動目的地的座標
    switch (dir){
        case UP:
            tox = myCoordinate.x;
            toy = myCoordinate.y - 1;
            break;
        case LEFT:
            tox = myCoordinate.x - 1;
            toy = myCoordinate.y ;
            break;
        case RIGHT:
            tox = myCoordinate.x + 1;
            toy = myCoordinate.y;
            break;
        case DOWN:
            tox = myCoordinate.x;
            toy = myCoordinate.y + 1;
            break;
    }
    //如果移動的範圍超過地圖的範圍,則不可移動
    if(tox <= 0 || toy <= 0)return false;
    if(toy >= mapdata.length || tox >= mapdata[0].length)return false;
    //如果目的地為障礙,則不可移動
    if(mapdata[toy][tox] == 1)return false;
    return true;
};

然後,在changeDir方法,和onmove方法中,新增相應的判斷,如下

/**
 * 開始移動 
 **/
Character.prototype.onmove = function (){
    var self = this;
    //設定一個移動步長中的移動次數
    var ml_cnt = 4;
    //計算一次移動的長度
    var ml = STEP/ml_cnt;
    //根據移動方向,開始移動
    switch (self.direction){
        case UP:
            self.y -= ml;
            break;
        case LEFT:
            self.x -= ml;
            break;
        case RIGHT:
            self.x += ml;
            break;
        case DOWN:
            self.y += ml;
            break;
    }
    self.moveIndex++;
    //當移動次數等於設定的次數,開始判斷是否繼續移動
    if(self.moveIndex >= ml_cnt){
        self.moveIndex = 0;
        //如果已經鬆開移動鍵,或者前方為障礙物,則停止移動,否則繼續移動
        if(!isKeyDown || !self.checkRoad()){
            self.move = false;
            return;
        }
    }
};
/**
 * 改變人物方向,並判斷是否可移動
 **/
Character.prototype.changeDir = function (dir){
    var self = this;
    //如果正在移動,則無效
    if(!self.move){
        //設定人物方向
        self.direction = dir;
        //設定圖片動畫
        self.anime.setAction(dir);
        //判斷是否可移動
        if(!self.checkRoad(dir))return;
        //如果可以移動,則開始移動
        self.move = true;
        self.moveIndex = 0;
    }
};

好了,大功告成,開始執行吧

測試URL如下 http://lufylegend.com/demo/rpg/index.html

lufylegend.js引擎包內包含這個demo,請直接下載lufylegend.js引擎,檢視引擎包內原始碼

lufylegend.js引擎下載地址

http://lufylegend.com/lufylegend

相關文章