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的调用顺序

效果如下图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值