2D的RPG遊戲人物角色移動程式碼(以egret遊戲引擎、TypeScript語言為例)
一般2D的RPG人物移動有三種:
(一)背景固定,角色移動
(二)角色固定,背景移動
(三)角色移動,背景動態移動
第一種在移動端的遊戲比較少見,但在PC端的模擬類遊戲比較常見,因為螢幕較大,背景固定即可,角色在背景上移動;第二種在移動端比較多見,就是角色固定在螢幕中間,需要移動時只需要移動背景同時播放角色跑步的動畫即可達到角色移動的效果;第三種是第一和第二種的結合,是如今最常見的方式,先是背景固定,角色自由移動,當移動到螢幕邊緣時,背景移動來擴大角色的視野,或者,先是角色居中背景移動,當背景將要離開螢幕邊緣時,角色再移動。
在這篇文章,我只說說第二種方式的實現思路,因為第一種十分簡單沒什麼難度,而第三種又是第一第二種的結合,所以先掌握第二種,自然會了第一種,再兩種結合即可寫出。
假設有一個Bg類,這個類繼承顯示容器精靈egret.Sprite,這個類有一個公有成員stone石頭,這個石頭是阻礙物阻礙角色移動的。將這個Bg類例項化成一個bg變數。
假設有一個role顯示物件,這個物件固定顯示在螢幕中間。
因為我們是實現第二種移動方式,Bg這個背景需要移來移去,但是不是隨便移的,需要點選背景某目標座標時才移動,所以我們偵聽一下點選事件,當點選背景某個座標時,呼叫bgHandle函式。
<span style="font-size:18px;"> this.bg.addEventListener(egret.TouchEvent.TOUCH_TAP, this.bgHandle, this);</span>
bgHandle函式用來確定基於bg錨點的位置移動點座標,定義bg_move_x為移動點橫座標,bg_move_y為移動點縱座標,speed為背景速度速度,timeOnEnterFrame為移動過程的結束時間。
那麼bg_move_x和bg_move_y怎麼獲取呢?首先獲取點選背景的座標evt.stageX和evt.stageY,然後計算橫座標evt.stageX、this.player.x和縱座標evt.stageY、this.player.y的偏移值,通過這兩個偏移值與當前背景位置this.bg.x和this.bg.y按相應移動方向計算出bg_move_x和bg_move_y即可。
獲得bg移動點後,偵聽幀事件,當背景未移動到移動點,不斷呼叫bgMove函式。
private bg_move_x:number = 0; //背景移動位置
private bg_move_y:number = 0; //背景移動位置
private speed:number = 0.3; //角色移動速度
private timeOnEnterFrame = 0; //最後角色移動動畫結束時間
public bgHandle(evt:egret.TouchEvent):void{
if(this.bg.hasEventListener(egret.Event.ENTER_FRAME) ){
this.bg.removeEventListener(egret.Event.ENTER_FRAME,this.bgMove,this);
}
this.timeOnEnterFrame = egret.getTimer(); //初始化最後角色移動動畫結束時間
if(evt.stageX > this.player.x){
this.bg_move_x = this.bg.x - (evt.stageX - this.player.x);
}
else if(evt.stageX < this.player.x){
this.bg_move_x = this.bg.x + (this.player.x - evt.stageX);
}
if(evt.stageY > this.player.y){
this.bg_move_y = this.bg.y - (evt.stageY - this.player.y);
}
else if(evt.stageY < this.player.y){
this.bg_move_y = this.bg.y + (this.player.y - evt.stageY);
}
this.bg.addEventListener(egret.Event.ENTER_FRAME,this.bgMove,this);
}
bgMove函式根據bg_move_x和bg_move_y的值作背景移動,每次背景只移動【speed * (每次幀事件的開始時間 - 結束時間)】畫素,直到到達目的地才取消移動幀事件。當玩家突然點選背景另一個座標時,bgHandle函式會取消幀事件,重新計算bg_move_x和bg_move_y然後再重新偵聽移動幀事件來呼叫bgMove函式。
private bgMove(evt:egret.Event):void{
var now = egret.getTimer();
var pass = this.timeOnEnterFrame;
var time = now - pass;
if(this.bg.x > this.bg_move_x){
if((this.bg.x - this.speed * time) < this.bg_move_x ){
this.bg.x = this.bg_move_x;
}
else{
this.bg.x -= this.speed * time;
if(this.isStopMove()){
this.bg.x += this.speed * time;
}
}
}
else if(this.bg.x < this.bg_move_x){
if((this.bg.x + this.speed * time) > this.bg_move_x ){
this.bg.x = this.bg_move_x;
}
else{
this.bg.x += this.speed * time;
if(this.isStopMove()){
this.bg.x -= this.speed * time;
}
}
}
if(this.bg.y > this.bg_move_y){
if((this.bg.y - this.speed * time) < this.bg_move_y ){
this.bg.y = this.bg_move_y;
}
else{
this.bg.y -= this.speed * time;
if(this.isStopMove()){
this.bg.y += this.speed * time;
}
}
}
else if(this.bg.y < this.bg_move_y){
if((this.bg.y + this.speed * time) >this.bg_move_y ){
this.bg.y = this.bg_move_y;
}
else{
this.bg.y += this.speed * time;
if(this.isStopMove()){
this.bg.y -= this.speed * time;
}
}
}
this.timeOnEnterFrame = egret.getTimer();
if(this.bg.x == this.bg_move_x && this.bg.y == this.bg_move_y){
this.bg.removeEventListener(egret.Event.ENTER_FRAME,this.bgMove,this);
}
}
在bgMove函式中,有一個函式isStopMove(),這個函式用來判斷角色是否碰撞到背景裡的石頭障礙物,如果碰到返回true,bgMove()根據返回值來判斷背景是否移動。
private isStopMove():boolean{
if( this.bg.stone.hitTestPoint( this.player.x, this.player.y, true ) ){
return true;
}
else{
return false;
}
}
這幾段程式碼就是基於egret遊戲引擎的RPG背景移動模擬角色移動的思路,其實程式碼還能做優化得更加精簡,但是精簡也會變得難以看懂,所以這長長的程式碼耐心看還是沒什麼難度的(前提是學過egret引擎)。