用23种设计模式打造一个cocos creator的游戏框架----(十五)策略模式

1、模式标准

模式名称:策略模式

模式分类:行为型

模式意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。此模式使得算法可以独立于使用它们的客户而变化

结构图:

适用于:

1、许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
2、需要使用一个算法的不同变体。例如,定义一些反映不同空间的空间/时间权衡的算法当这些变体实现为一个算法的类层次时,可以使用策略模式。
3、算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
4、一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,将相关的条件分支移入它们各自的 Strategy 类中,以代替这些条件语句。 

2、分析与设计  

策略和桥接模式看起来可能非常相似,但策略模式是行为型,桥接模式是结构型。策略模式是直接引用实现类,而桥接模式是引用一个实现类的接口。当前策略模式关键是可以相互替换算法。前面我们已经通过武器的使用用了桥接模式,攻击者将抽象中的攻击方法桥接到了具体武器中的攻击方法。接下来我们来具体实现武器是如何攻击敌人的算法。

一般游戏可分为近程攻击和远程攻击。

近程攻击在单位发动后,0.1~0.5内就产生伤害。

远程攻击在单位发动后,生成一个火球,火球到达受攻击单位后,产生伤害。

2种攻击在武器使用上是2个完全不同的算法。我们假设还有其他的比如“衍射攻击”,被攻击单位附近的单位也收到1%的伤害。“火球反弹”,火球遇到障碍物后,可以反弹等等。

为了体现策略模式的可替换性。假设的场景为我方所有步兵的攻击方式,开始的时候是攻击方式1。因为基地科技升级后升级了剑属性,攻击方式变为了攻击方式2。只需对剑进行算法更换。

意图:定义一系列的算法(攻击算法),把它们一个个封装起来,并且使它们可以相互替换。

3、开始打造


export interface IAttackStrategy {
    doAction(fromUnitItem: IUnitItem, toUnitItem: IUnitItem, effectNo: string): void;
}
// 近程攻击
export class MeleeAttack implements IAttackStrategy {
    doAction(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>, effectNo: string): void {
        console.log("当前是:近程攻击,攻击0.1秒后生效");
        console.log("武器决定了刀影的效果todo");
        xhgame.timer.scheduleOnce(() => {
            let attackVisitor = xhgame.flyweightFactory.getAttackVisitor(AttackVisitorType.Monomer)
            toUnitItem.accept(attackVisitor, fromUnitItem.ad)
        }, 0.1)
    }
}

// 远程攻击
export class RangedAttack implements IAttackStrategy {
    doAction(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>, effectNo: string): void {
        console.log("当前:远程攻击,产生一个bullet,从攻击者到攻击目标,假设等待2秒后生效");
        console.log("武器决定了飞行单位的效果todo");

        let bullet = xhgame.itemFactory.createEffectItem(effectNo)
        bullet.visitorcallback = () => {
            let attackVisitor = xhgame.flyweightFactory.getAttackVisitor(AttackVisitorType.Monomer)
            toUnitItem.accept(attackVisitor, fromUnitItem.ad)
        }
    }
}

武器

// 武器(单位攻击属性)接口
export interface IWeapon {
    attackStrategy: IAttackStrategy
    price: number
    sell(): number
    getEffect(): string;
    attack(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>): void
    setAttackStrategy(attackStrategy: IAttackStrategy): void
}
export abstract class Weapon implements IWeapon {
    attackStrategy: IAttackStrategy
    price: number
    itemNo: string

    constructor(attackStrategy: IAttackStrategy, price: number, itemNo: string) {
        this.attackStrategy = attackStrategy
        this.price = price
        this.itemNo = itemNo
    }

    sell(): number {
        return this.price
    }
    getEffect(): string {
        return this.itemNo
    }
    // 攻击者的抽象attack方法桥接到了此处武器的attack方法
    attack(fromUnitItem: UnitItem<any>, toUnitItem: UnitItem<any>): void {
        // 武器的attack实现,用具体攻击策略实现
        this.attackStrategy.doAction(fromUnitItem, toUnitItem, this.getEffect())
    }

    setAttackStrategy(attackStrategy: IAttackStrategy) {
        this.attackStrategy = attackStrategy
    }
}

// 剑
export class Sword extends Weapon {
    constructor(ItemNo: string) {
        super(new MeleeAttack(), 100, ItemNo)
    }
}

// 斧头
export class Axe extends Weapon {
    constructor(ItemNo: string) {
        super(new MeleeAttack(), 100, ItemNo)
    }
}
// 弓
export class Bow extends Weapon {
    constructor(ItemNo: string) {
        super(new RangedAttack(), 100, ItemNo)
    }
}

 

 4、开始使用

单位

export class UnitItem  extends Component implements IItem, IUnitItem {

    ad: number = 100;
    mp: number = 0;
    // 攻击方式
    fighter: Fighter;
    private currentState: IUnitState = null;

    ......

    setFighter(fighter: Fighter): void {
        this.fighter = fighter;
    }
}

升级攻击方式

let unitItem2 = xhgame.itemFactory.createUnitItem('kuloubing')
// 替换攻击算法
let newMeleeAttack = new MeleeAttack()
unitItem.fighter.getWeapon().setAttackStrategy(newMeleeAttack)

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值