cocos creator中使用行爲樹(BehaviorTree) 六

cocos creator中使用行爲樹(BehaviorTree) 六

本節代碼在我的github上: https://github.com/kirikayakazuto/BehaviorTreeGame

繼續完善我們的遊戲, 這一節我們實現

  1. 控制玩家攻擊, 防守
  2. 敵人自動防禦

先把控制玩家攻擊防守完成

打開cocos creator, 

這是我們現在的player結點, 因爲現在要實現一些複雜一點的功能, 我決定給他們換一下皮膚

左邊這個就是我們的玩家了, 紅色矩形表示武器, 藍色表示盾牌, 右邊的是敵人

我預計實現的效果是, 玩家點擊攻擊, 紅色塊上下移動, 點擊防禦顯示藍色塊,  且點擊防禦時不能攻擊, 點擊攻擊時不能防禦

因爲需要進行碰撞檢測, 我使用了cocos creator的碰撞組件, 在arms, shield和sp 上添加碰撞組件

我這裏是對每一個子結點加上了碰撞組件, 而碰撞組件的碰撞回調是通過 訪問改碰撞組件的結點上的任意腳本上的onCollisionEnter, onCollisionStay, onCollisionExit方法, 

但是我想在player腳本統一處理回調, 所以我添加了shield腳本, arms腳本, sp腳本

import PlayerCtl from "./PlayerCtl"
import { GameStatus } from "./GameInterface";
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    speed = 100;
    state = GameStatus.STOP;
    // LIFE-CYCLE CALLBACKS:
    playerCtl: PlayerCtl = null;

    // onLoad () {}

    init(playerCtl: PlayerCtl) {
        this.playerCtl = playerCtl;
    }


    start () {

    }

    onCollisionEnter(other, self) {
        this.playerCtl.onCollisionEnter(other, self);
    }

    onCollisionStay(other, self) {
        this.playerCtl.onCollisionStay(other, self);
    }

    onCollisionExit(other, self) {
        this.playerCtl.onCollisionStay(other, self);
    }

    



    // update (dt) {}
}


通過上圖的代碼, 我們將所有的碰撞結果 統一發送給playerCtl腳本處理

接下來, 我們實現玩家的攻擊和防禦

回顧一下功能,

  1. 點擊攻擊J鍵, 顯示武器(紅色塊), 武器上下移動
  2. 鬆開攻擊J鍵, 武器停止移動, 隱藏武器
  3. 點擊防禦 k鍵, 顯示盾牌(藍色塊)
  4. 鬆開K鍵, 隱藏盾牌
  5. 在攻擊時不允許防禦, 在防禦時不允許攻擊

以上5點, 開始編寫代碼

首先我們引入一個變量, 表示玩家當前的狀態, 是攻擊, 還是防禦, 還是既不攻擊也沒防禦

state = GameStatus.DAZING;

還是把代碼全貼出來吧

import GameScene from "./GameSCene"
import ArmsCtl from "./ArmsCtl"
import ShieldCtl from "./ShieldCtl"
import HeroSpriteClt from "./HeroSpriteClt"
import { GameStatus } from "./GameInterface";
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

    direction = 0;      // 當前狀態 -1表示向左, 1表示向用, 0表示不動
    faceTo = 1;         // 當前面向
    speed = 100;
    state = GameStatus.DAZING;

    gameCtl: GameScene = null;

    @property(ArmsCtl)
    armsCtl: ArmsCtl = null;
    @property(ShieldCtl)
    shieldCtl: ShieldCtl = null;
    @property(HeroSpriteClt)
    HeroSpriteClt: HeroSpriteClt = null;

    // onLoad () {}
    init(gameCtl: GameScene) {        // 初始化子節點init, 把playerCtl實例傳過去
        this.gameCtl = gameCtl;
        this.armsCtl.init(this);
        this.shieldCtl.init(this);
        this.HeroSpriteClt.init(this);
    }

    start () {
    }

    getPosition() {
        return this.node.position;
    }
    /**
     * 設置玩家方向
     * @param dir 
     */
    setDirection(dir: number) {
        this.direction = dir;
        this.faceTo = dir == 0 ? this.faceTo : dir;
        this.node.scaleX = this.faceTo;
    }
    /**
     * 設置武器狀態
     */
    setArmsState(state: number) {
        if(this.state == GameStatus.DEFENSING) {
            return ;
        }
        this.armsCtl.setArmsState(state);
        this.state = state == GameStatus.RUNNING ? GameStatus.ATTACKING : GameStatus.STOP;
    }
    /**
     * 設置防禦狀態
     */
    setShieldState(state: number) {
        if(this.state == GameStatus.ATTACKING) {
            return ;
        }
        this.shieldCtl.setShieldState(state);
        this.state = state == GameStatus.RUNNING ? GameStatus.DEFENSING : GameStatus.STOP;
    }
    /**
     * 更新玩家位置
     * @param dt 
     */
    playerUpdate(dt: number) {
        this.armsCtl.armsUpdate(dt);
        if(this.direction == 0) {
            return ;
        }
        this.node.x += this.direction * dt * this.speed;
    }

    /**
     * ---------------------------------- 碰撞回調 ---------------------------------------
     */
    onCollisionEnter(other, self) {
        
    }

    onCollisionStay(other, self) {

    }

    onCollisionExit(other, self) {

    }

}

恩, 也沒什麼好說的, 還是說說我的設計思想吧

對於腳本之間的通訊我比較喜歡樹狀通訊 結構

如圖是一個結點樹, A向B傳遞信息, 採用的方式是把B結點實例拖到A上, A中直接調用B的方法

B向A傳遞信息, 就是使用上圖的init方法,A中調用B的init方法將A實例傳給B, 在B中調用A的方法

那麼B, C間通訊呢, 我這裏不允許B,C直接通訊, B,C通訊需要藉助A(即是BC的共同父節點), B調用A的方法(A調用C的方法)

 

這就是我代碼中腳本通訊的思想,

回到代碼, 在ArmsCtl中, 因爲武器也是實時改變位置的

添加一個update方法, 注意我使用的不是系統的update方法, 而是在playerClt中調用子節點的自定義update方法, 這樣可以確定update的調用順序

效果如下圖

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章