头歌软件设计植物大战僵尸第三关
僵尸有限状态机实现
根据提供的代码框架,我需要为僵尸实现有限状态机。主要需要补充以下几个文件:
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());
}
}
浙公网安备 33010602011771号