头歌软件设计植物大战僵尸第三关

僵尸有限状态机实现

根据提供的代码框架,我需要为僵尸实现有限状态机。主要需要补充以下几个文件:

IZombieState.java

package step3.CharacterSystem.ZombieFSMSystem;

import step3.CharacterSystem.Character.ICharacter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class IZombieState {
    protected Map<EnemyTransition, EnemyStateID> mMap = new HashMap<EnemyTransition, EnemyStateID>();
    protected EnemyStateID mstateID;
    protected ICharacter mCharacter;
    protected ZombieFSM mFSM;

    public IZombieState(ZombieFSM fsm, ICharacter character) {
        mFSM = fsm;
        mCharacter = character;
    }

    public void AddTransition(EnemyTransition trans, EnemyStateID id) {
        if (trans == EnemyTransition.NullTansition) {
            return;
        }
        if (id == EnemyStateID.NullState) {
            return;
        }
        if (mMap.containsKey(trans)) {
            return;
        }
        mMap.put(trans, id);
    }

    public void DeleteTransition(EnemyTransition trans) {
        if (mMap.containsKey(trans) == false) {
            return;
        }
        mMap.remove(trans);
    }

    public EnemyStateID GetOutPutState(EnemyTransition trans) {
        if (mMap.containsKey(trans) == false) {
            return EnemyStateID.NullState;
        } else {
            return mMap.get(trans);
        }
    }

    public abstract void DoBeforeEntering();
    public abstract void DoBeforeLeaving();
    public abstract void Reason(List<ICharacter> targets);
    public abstract void Act(List<ICharacter> targets);

    public EnemyStateID getMstateID() {
        return mstateID;
    }
}

ZombieAttackState.java

package step3.CharacterSystem.ZombieFSMSystem;

import step3.CharacterSystem.Character.ICharacter;
import java.util.List;

public class ZombieAttackState extends IZombieState {
    private float mAttackTime = 1;
    private float mAttackTimer = 0;

    public ZombieAttackState(ZombieFSM fsm, ICharacter c) {
        super(fsm, c);
        mstateID = EnemyStateID.Attack;
        mAttackTimer = mAttackTime;
    }

    @Override
    public void DoBeforeEntering() {
    }

    @Override
    public void DoBeforeLeaving() {
    }

    @Override
    public void Act(List<ICharacter> targets) {
        if (targets == null || targets.size() == 0) return;
        mAttackTimer += 0.1f;
        if (mAttackTimer >= mAttackTime) {
            for(ICharacter t : targets) {
                if (t.getPosRow() == mCharacter.getPosRow()) {
                    int temp = mCharacter.getPosition().x - t.getPosition().x;
                    if (temp <= mCharacter.getAttr().getmBaseAttr().getAtkdistance() && temp >= 0)
                        mCharacter.Attack(t);
                }
            }
            mAttackTimer = 0;
        }
    }

    @Override
    public void Reason(List<ICharacter> targets) {
        if (targets == null || targets.size() == 0) {
            mFSM.PerformTransition(EnemyTransition.LostSoldier);
            return;
        }
        
        boolean canAttack = false;
        for (ICharacter t : targets) {
            if (t.getPosRow() == mCharacter.getPosRow()) {
                int distance = mCharacter.getPosition().x - t.getPosition().x;
                if (distance >= 0 && distance <= mCharacter.getAttr().getmBaseAttr().getAtkdistance()) {
                    canAttack = true;
                    break;
                }
            }
        }
        
        if (!canAttack) {
            mFSM.PerformTransition(EnemyTransition.LostSoldier);
        }
    }
}

ZombieChaseState.java

package step3.CharacterSystem.ZombieFSMSystem;

import step3.CharacterSystem.Character.ICharacter;
import java.awt.*;
import java.util.List;

public class ZombieChaseState extends IZombieState {
    private Point mTargetPosition;

    public ZombieChaseState(ZombieFSM fsm, ICharacter c) {
        super(fsm, c);
        mstateID = EnemyStateID.Chase;
    }

    @Override
    public void DoBeforeEntering() {
        mTargetPosition = new Point(50, mCharacter.getPosition().y);
    }

    @Override
    public void DoBeforeLeaving() {
    }

    public void Act(List<ICharacter> targets) {
        if (mCharacter.getPosition().x > mTargetPosition.x) {
            mCharacter.MoveTo(mTargetPosition.x);
        }
    }

    @Override
    public void Reason(List<ICharacter> targets) {
        if (targets != null && targets.size() > 0) {
            int distance = 2000;
            int temp = 2000;
            for (ICharacter t : targets) {
                if(t.getPosRow() == mCharacter.getPosRow()) {
                    temp = mCharacter.getPosition().x - t.getPosition().x;
                    if (distance > temp && temp >= 0)
                        distance = temp;
                }
            }
            if (distance <= mCharacter.getAttr().getmBaseAttr().getAtkdistance()) {
                mFSM.PerformTransition(EnemyTransition.CanAttack);
            }
        }
    }
}

ZombieFSM.java

package step3.CharacterSystem.ZombieFSMSystem;

import java.util.ArrayList;
import java.util.List;

public class ZombieFSM {
    private List<IZombieState> mStates = new ArrayList();
    private IZombieState currentState;

    public IZombieState getCurrentState() { return currentState; }

    public void AddState(IZombieState[] states) {
        for(IZombieState s : states) {
            AddState(s);
        }
    }

    public void AddState(IZombieState state) {
        if (state == null) {
            return;
        }
        if (mStates.size() == 0) {
            mStates.add(state);
            currentState = state;
            currentState.DoBeforeEntering();
            return;
        }
        for(IZombieState s : mStates) {
            if (s.mstateID == state.mstateID) {
                return;
            }
        }
        mStates.add(state);
    }

    public void DeleteState(EnemyStateID stateID) {
        if (stateID == EnemyStateID.NullState) {
            return;
        }
        for (IZombieState s : mStates) {
            if (s.mstateID == stateID) {
                mStates.remove(s);
                return;
            }
        }
    }

    public void PerformTransition(EnemyTransition trans) {
        if (trans == EnemyTransition.NullTansition) {
            return;
        }
        EnemyStateID nextStateID = currentState.GetOutPutState(trans);
        if (nextStateID == EnemyStateID.NullState) {
            return;
        }
        for (IZombieState s : mStates) {
            if (s.mstateID == nextStateID) {
                currentState.DoBeforeLeaving();
                currentState = s;
                currentState.DoBeforeEntering();
                return;
            }
        }
    }
}

ZombieNormal.java

package step3.CharacterSystem.Character;

import step3.CharacterSystem.Attr.CharacterAttr;
import step3.CharacterSystem.ZombieFSMSystem.*;
import java.awt.*;
import java.util.List;

public class ZombieNormal extends ICharacter {
    private ZombieFSM mFSMSystem;

    public ZombieNormal(CharacterAttr attr, Point position, int posrow) {
        super(attr, position, posrow);
        attackimg = "/data/workspace/myshixun/images/Zombies/Zombie/ZombieAttack.gif";
        chaseimg = "/data/workspace/myshixun/images/Zombies/Zombie/Zombie.gif";
        GetImageSize(chaseimg);
    }

    @Override
    public void Killed() {
    }

    @Override
    public void MakeFSM() {
        mFSMSystem = new ZombieFSM();
        
        ZombieChaseState chaseState = new ZombieChaseState(mFSMSystem, this);
        chaseState.AddTransition(EnemyTransition.CanAttack, EnemyStateID.Attack);
        
        ZombieAttackState attackState = new ZombieAttackState(mFSMSystem, this);
        attackState.AddTransition(EnemyTransition.LostSoldier, EnemyStateID.Chase);
        
        mFSMSystem.AddState(chaseState);
        mFSMSystem.AddState(attackState);
    }

    @Override
    public void UpdateFSMAI(List<ICharacter> targets) {
        if (mIsKilled) return;
        mFSMSystem.getCurrentState().Reason(targets);
        mFSMSystem.getCurrentState().Act(targets);
    }

    @Override
    public void Attack(ICharacter target) {
        PlayAnim(attackimg);
        target.UnderAttack(attr.getmBaseAttr().getDamage());
    }
}
posted @ 2025-06-04 21:38  是否未晚  阅读(49)  评论(0)    收藏  举报