赞
踩
模式名称:状态模式
模式分类:行为型
模式意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
结构图:
适用于:
1、一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2、一个操作中含有庞大的多分支的条件语句,且这些分支依赖丁该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得开发者可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化。
主要成员:
在一般的游戏开发中状态值通常是一个枚举值,但在状态模式中,状态值是一个通过实现了 IUnitState
接口的对象表示的。这种方法的优点是它更加灵活和强大,因为这个状态值不仅仅是一个值,它还是一组行为的集合(即方法实现)。这允许您在不同的状态之间切换行为,而不是仅仅改变一个表示状态的值。
在游戏中的单位一般有以下几种状态:站立,移动,攻击,释放技能中,眩晕中,死亡。比较常见的是单位正在释放一个技能,这个时候一个飞锤飞过来,将他击晕了,他停止了技能的释放。
接下来我们修改一下我们的意图
意图:允许一个对象(单位)在其内部状态改变时(由其状态对象来)改变它的行为。对象看起来似乎修改了它的类(实际是状态对象干的)。
- export enum UnitStateType {
- Standing,
- Moving,
- Attacking,
- CastSkilling,
- Stuning,
- Die
- }
- export interface IUnitState {
- enterState(unitItem: IUnitItem): void
- //
- stand(): void; // 站立
- move(): void; // 移动
- attack(): void; // 攻击
- castSkill(): void; // 释放技能
- stun(): void; // 击晕
- die(): void; // 死亡
- //
- getType(): UnitStateType
- }
- // 状态基类,包含一个指向Unit的引用
- export abstract class BaseState implements IUnitState {
- protected unitItem: IUnitItem;
-
- enterState(unitItem: IUnitItem) {
- this.unitItem = unitItem;
- }
- // 获取状态的type值
- abstract getType(): UnitStateType;
- // 状态
- stand() {
- console.log(this.unitItem, "单位准备进入站立状态");
- this.unitItem.setState(new StandingState());
- }
- move() {
- console.log(this.unitItem, "单位准备进入移动状态");
- this.unitItem.setState(new MovingState());
- }
- attack(): void {
- console.log(this.unitItem, "单位准备进入攻击状态");
- this.unitItem.setState(new AttackingState());
- }
- castSkill(): void {
- console.log(this.unitItem, "单位准备进入释放技能状态");
- this.unitItem.setState(new CastSkillingState());
- }
- stun(): void {
- console.log(this.unitItem, "单位准备进入击晕状态");
- this.unitItem.setState(new StuningState());
- }
- die() {
- console.log(this.unitItem, "单位准备进入死亡状态");
- this.unitItem.setState(new DeadState());
- }
-
- }
-
- // 站立状态
- export class StandingState extends BaseState {
-
- getType(): UnitStateType {
- return UnitStateType.Standing;
- }
-
- // 重写方法
- stand() {
- console.log(this.unitItem, "单位已经进入站立状态");
- }
-
- }
-
- // 移动状态
- export class MovingState extends BaseState {
-
- getType(): UnitStateType {
- return UnitStateType.Moving;
- }
-
- // 重写方法
- move() {
- console.log(this.unitItem, "单位已经进入移动状态");
- }
-
- }
-
- // 攻击状态
- export class AttackingState extends BaseState {
-
- getType(): UnitStateType {
- return UnitStateType.Attacking;
- }
- enterState(unitItem: IUnitItem) {
- super.enterState(unitItem);
- this.doAction();
- }
-
- doAction() {
- // 执行攻击
- this.unitItem.role.attack(); // 攻击
- // 如果攻击顺利完成,进行清理并返回到正常状态
- // 例如,设置一个延时来模拟攻击动作的时间
- let attackDuration = 1000
- setTimeout(() => {
- if (this.unitItem.getCurrentState().getType() == UnitStateType.Attacking) {
- console.log('单位已从攻击状态到站立状态')
- this.unitItem.setState(new StandingState());
- }
- }, attackDuration);
- }
- // 重写方法
- attack(): void {
- console.log(this.unitItem, "单位已经进入攻击状态");
- }
-
- }
-
- // 释放技能状态
- export class CastSkillingState extends BaseState {
-
- getType(): UnitStateType {
- return UnitStateType.CastSkilling;
- }
-
- enterState(unitItem: IUnitItem) {
- super.enterState(unitItem);
- this.doAction();
- }
-
- doAction() {
- // 执行攻击
- // this.unitItem.role.attack(); // 攻击
- // 如果攻击顺利完成,进行清理并返回到正常状态
- // 例如,设置一个延时来模拟攻击动作的时间
- let attackDuration = 1000
- setTimeout(() => {
- if (this.unitItem.getCurrentState().getType() == UnitStateType.CastSkilling) {
- console.log('单位已从技能释放状态到站立状态')
- this.unitItem.setState(new StandingState());
- }
- }, attackDuration);
- }
- // 重写方法
- castSkill(): void {
- console.log(this.unitItem, "单位已经进入释放技能状态");
- }
-
- }
-
-
- // 击晕状态
- export class StuningState extends BaseState {
-
- getType(): UnitStateType {
- return UnitStateType.Stuning;
- }
-
- enterState(unitItem: IUnitItem) {
- super.enterState(unitItem);
- this.stopCurrentAction();
- }
- // 重写方法
- stun(): void {
- console.log(this.unitItem, "单位已经进入击晕状态");
- }
-
- stopCurrentAction() {
- console.log(this.unitItem, "单位所有动作停止,因为被击晕");
- // 如果有正在进行的释放技能的操作,这里将其中断
- // 这可能包括清除技能计时器、动画等
- }
-
- }
- // 死亡状态
- export class DeadState extends BaseState {
-
- getType(): UnitStateType {
- return UnitStateType.Dead;
- }
-
- enterState(unitItem: IUnitItem) {
- super.enterState(unitItem);
- this.stopCurrentAction();
- }
- // 重写方法
- die() {
- console.log(this.unitItem, "单位已经进入死亡状态");
- }
-
- stopCurrentAction() {
- console.log(this.unitItem, "单位所有动作停止,因为已死亡");
- // 如果有正在进行的释放技能的操作,这里将其中断
- // 这可能包括清除技能计时器、动画等
- }
- }
接着是单位里的
- export class UnitItem extends Component implements IItem, IUnitItem {
-
- ad: number = 100;
- mp: number = 0;
- role: Fighter;
- private currentState: IUnitState = null;
-
- accept(visitor: IAttackVisitor) {
- visitor.visitUnitItem(this)
- }
-
-
- setRole(role: Fighter): void {
- this.role = role;
- }
-
- setState(state: IUnitState) {
- this.currentState = state;
- state.enterState(this);
- }
- getCurrentState(): IUnitState {
- if (this.currentState == null) {
- this.setState(new StandingState())
- }
- return this.currentState;
- }
- move() {
- this.getCurrentState().move()
- }
- idle() {
- this.getCurrentState().stand()
- }
- attack(unitItem: UnitItem<T>) {
- if (!this.canAttack()) {
- // 不能处理攻击的逻辑,可能是显示消息或者进入其他状态
- return;
- }
- // 尝试进入攻击状态
- this.getCurrentState().attack()
- let damage = this.ad
- let attackVisitor = new MonomerAttackVisitor(damage)
- unitItem.accept(attackVisitor)
-
- // 临时 todo 删除
- console.log('假装本次攻击带有击晕效果')
- unitItem.getCurrentState().stun()
-
- }
- skill() {
- if (!this.canSkill()) {
- // 不能处理攻击的逻辑,可能是显示消息或者进入其他状态
- return;
- }
- // 尝试进入攻击状态
- this.getCurrentState().castSkill()
- }
-
- die() {
- this.getCurrentState().die()
- }
- private canSkill(): boolean {
- // 检查单位是否可以进行技能攻击
- // 例如,单位是否处于晕眩状态或者攻击是否冷却中
- if (this.mp < 100) {
- console.log('不能处理skill攻击的逻辑,因为魔法值不足100')
- return false
- }
- if (this.getCurrentState().getType() == UnitStateType.CastSkilling) {
- console.log('不能处理skill攻击的逻辑,因为已经处于技能释放中')
- return false
- }
- if (this.getCurrentState().getType() == UnitStateType.Stuning) {
- console.log('不能处理skill攻击的逻辑,因为已经被击晕')
- return false
- }
- if (this.getCurrentState().getType() == UnitStateType.Dead) {
- console.log('不能处理skill攻击的逻辑,因为已经死亡')
- return false
- }
- return true;
- }
-
- private canAttack(): boolean {
- // 检查单位是否可以进行攻击
- // 例如,单位是否处于晕眩状态或者攻击是否冷却中
- if (this.getCurrentState().getType() == UnitStateType.Attacking) {
- console.log('不能处理攻击的逻辑,因为已经处于攻击中')
- return false
- }
- if (this.getCurrentState().getType() == UnitStateType.Stuning) {
- console.log('不能处理攻击的逻辑,因为已经被击晕')
- return false
- }
- if (this.getCurrentState().getType() == UnitStateType.Dead) {
- console.log('不能处理攻击的逻辑,因为已经死亡')
- return false
- }
- return true;
- }
- }
在非状态对象类中使用时都是用以下的方式调用
- this.getCurrentState().stand()
- this.getCurrentState().move()
在方法里面会执行从当前状态到下一个状态所需要的动作
在状态类中,如果需要到下一个状态就需要再状态类中new一个新的状态,如
- castSkill(): void {
- console.log(this.unitItem, "单位准备进入释放技能状态");
- this.unitItem.setState(new CastSkillingState());
- }
接着在下一个状态CastSkillingState中的enterState,方法内其他动作
- let unitItem001 = xhgame.itemFactory.createUnitItem('kuloubing', UnitType.UnitSpine)
- let unitItem002 = xhgame.itemFactory.createUnitItem('kuloubing', UnitType.UnitSpine)
-
- unitItem001.idle()
- unitItem002.idle()
- unitItem002.skill()
- unitItem002.mp = 100;
- unitItem002.skill()
-
- unitItem001.setRole(new Cavalry(new Sword()));
- console.log('unitItem001(骑兵)准备使用【剑】对unitItem002发起了攻击')
- unitItem001.attack(unitItem002)
-
- unitItem001.setRole(new Cavalry(new Bow()));
- console.log('unitItem001(骑兵)准备使用【弓】对unitItem002发起了攻击')
- unitItem001.attack(unitItem002)
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。