Skip to content

Commit 5e66fea

Browse files
author
houko
committed
状态机
1 parent 5a5fc0b commit 5e66fea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+4190
-47
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package info.xiaomo.gengine.ai.fsm;
2+
3+
import java.util.concurrent.ThreadLocalRandom;
4+
import lombok.Data;
5+
6+
@Data
7+
public class AIData {
8+
9+
/**
10+
* 已经睡眠的时间,整个AI系统都要用,主要是用于战斗和移动
11+
*/
12+
private int sleepTime = 0;
13+
14+
15+
/**
16+
* 上次寻找周围怪物的时间
17+
*/
18+
private int findNearestFightAbleTime = 0;
19+
20+
21+
/**
22+
* 随机走动的参数 (1w-2w之间)
23+
*/
24+
private int randomMoveTime = (int) (ThreadLocalRandom.current().nextDouble() * 10000 + 10000);
25+
26+
/**
27+
* 仇恨清除时间
28+
*/
29+
private int clearThreatTime = 13500;
30+
31+
/**
32+
* 蓝血恢复时间
33+
*/
34+
private int recoverHpAndMapTime = 0;
35+
36+
/**
37+
* 死亡时间
38+
*/
39+
private long dieTime = 0;
40+
41+
/**
42+
* 下一次复活时间
43+
*/
44+
private long nextReliveTime = 0;
45+
46+
47+
/**
48+
* 攻击我的对象
49+
*/
50+
private long whoAttackMe;
51+
private long whoAttackMeTime;
52+
53+
/**
54+
* 我的攻击目标
55+
*/
56+
private long whoMyTarget;
57+
58+
private long whoMyTargetTime;
59+
60+
61+
public void updateFightAITime(int dt) {
62+
this.findNearestFightAbleTime -= dt;
63+
this.recoverHpAndMapTime -= dt;
64+
this.clearThreatTime -= dt;
65+
this.sleepTime -= dt;
66+
}
67+
68+
public void updateActiveAITime(int dt) {
69+
this.findNearestFightAbleTime -= dt;
70+
this.randomMoveTime -= dt;
71+
this.recoverHpAndMapTime -= dt;
72+
this.sleepTime -= dt;
73+
74+
}
75+
76+
public void updatePetFollowAITime(int dt) {
77+
this.sleepTime -= dt;
78+
this.recoverHpAndMapTime -= dt;
79+
}
80+
81+
public void updatePetFightAITime(int dt) {
82+
this.sleepTime -= dt;
83+
this.recoverHpAndMapTime -= dt;
84+
}
85+
86+
87+
public void updateMyTargetOrAttackedMe(int dt) {
88+
89+
if (this.whoAttackMe > 0) {
90+
this.whoAttackMeTime -= dt;
91+
if (this.whoAttackMeTime <= 0) {
92+
this.whoAttackMe = 0;
93+
}
94+
}
95+
96+
if (this.whoMyTarget > 0) {
97+
this.whoMyTargetTime -= dt;
98+
if (this.whoMyTargetTime <= 0) {
99+
this.whoMyTarget = 0;
100+
}
101+
}
102+
}
103+
104+
public void clearMyTargetOrAttackedMe() {
105+
106+
this.whoAttackMeTime = 0;
107+
this.whoAttackMe = 0;
108+
109+
this.whoMyTargetTime = 0;
110+
this.whoMyTarget = 0;
111+
}
112+
113+
114+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package info.xiaomo.gengine.ai.fsm;
2+
3+
public interface AIType {
4+
5+
/**
6+
* 不能行走和攻击的采集怪
7+
* 0#采集读条需要的时间#每次采集到的个数下限#每次采集到的个数上限
8+
*/
9+
int NONE = 0;
10+
11+
/**
12+
* 主动出击(在攻击范围内会主动发起攻击)
13+
*/
14+
int Threat_ACTIVE = 1;
15+
16+
/**
17+
* 被动仇恨(被攻击了才会发起攻击)
18+
*/
19+
int THREAT_PASSIVE = 2;
20+
21+
/**
22+
* 有技能的怪
23+
*/
24+
int SKILL_MONSTER = 3;
25+
26+
/**
27+
* 脚本策略
28+
*/
29+
int SCRIPT = 4;
30+
31+
32+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package info.xiaomo.gengine.ai.fsm;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import info.xiaomo.gengine.map.AbstractGameMap;
6+
import info.xiaomo.gengine.map.obj.Performer;
7+
import lombok.Data;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
/**
12+
* 状态机,用于控制AI等,包括玩家的战斗状态
13+
*
14+
* @param <T>
15+
* @author 张力
16+
*/
17+
@Data
18+
public class FSMMachine<T extends Performer> {
19+
20+
private static final Logger LOGGER = LoggerFactory.getLogger(FSMMachine.class);
21+
22+
/**
23+
* 可用状态
24+
*/
25+
private List<FSMState<T>> states = new ArrayList<>();
26+
27+
/**
28+
* 当前状态
29+
*/
30+
private FSMState<T> state;
31+
32+
/**
33+
* 是否正在运行(这里只至少update一次以后才算运行)
34+
*/
35+
private boolean running = false;
36+
37+
private AIData aiData = new AIData();
38+
39+
public FSMMachine(List<FSMState<T>> states, FSMState<T> init) {
40+
this.states.addAll(states);
41+
this.state = init;
42+
this.aiData.setClearThreatTime(5000);
43+
}
44+
45+
public void updateMachine(AbstractGameMap map, int delta) {
46+
47+
if (states.isEmpty()) {
48+
return;
49+
}
50+
51+
if (this.state == null) {
52+
return;
53+
}
54+
int curType = this.state.type;
55+
int nextType = this.state.checkTransition(map);
56+
if (nextType != curType) {
57+
FSMState<T> nextState = getStateByType(nextType);
58+
if (nextState != null) {
59+
// 复制时间
60+
int sleepTime = this.state.getTime();
61+
this.state.exit(map);
62+
this.state = nextState;
63+
this.state.enter(map);
64+
this.state.copyTime(sleepTime);
65+
return;
66+
}
67+
}
68+
69+
this.state.update(map, delta);
70+
this.running = true;
71+
}
72+
73+
public FSMState<T> getStateByType(int goal) {
74+
for (FSMState<T> state : states) {
75+
if (state.type == goal) {
76+
return state;
77+
}
78+
}
79+
return null;
80+
}
81+
82+
public int getState() {
83+
return state != null ? state.type : 0;
84+
}
85+
86+
87+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package info.xiaomo.gengine.ai.fsm;
2+
3+
import info.xiaomo.gengine.map.AbstractGameMap;
4+
import info.xiaomo.gengine.map.obj.Performer;
5+
import lombok.extern.slf4j.Slf4j;
6+
7+
/**
8+
* 状态机中的状态
9+
*
10+
* @param <T>
11+
* @author 张力
12+
*/
13+
@Slf4j
14+
public abstract class FSMState<T extends Performer> {
15+
16+
17+
/**
18+
* 不显示在场景中,不活动
19+
*/
20+
public static final int Sleep = 1;
21+
22+
/**
23+
* 活动状态
24+
*/
25+
public static final int Active = 2;
26+
27+
/**
28+
* 战斗状态
29+
*/
30+
public static final int Fight = 3;
31+
32+
/**
33+
* 死亡状态
34+
*/
35+
public static final int Die = 4;
36+
37+
/**
38+
* 类型
39+
*/
40+
protected int type;
41+
42+
/**
43+
* 执行者
44+
*/
45+
protected T performer;
46+
47+
public FSMState(int type, T performer) {
48+
this.type = type;
49+
this.performer = performer;
50+
}
51+
52+
/**
53+
* 进入状态
54+
*
55+
* @param map
56+
*/
57+
public void enter(AbstractGameMap map) {
58+
59+
}
60+
61+
/**
62+
* 退出状态
63+
*
64+
* @param map
65+
*/
66+
public void exit(AbstractGameMap map) {
67+
68+
}
69+
70+
/**
71+
* 更新状态
72+
*
73+
* @param map
74+
* @param delta
75+
*/
76+
public void update(AbstractGameMap map, int delta) {
77+
}
78+
79+
/**
80+
* 检查状态转换
81+
*
82+
* @param map
83+
* @return
84+
*/
85+
public int checkTransition(AbstractGameMap map) {
86+
return 0;
87+
}
88+
89+
/**
90+
* 拷贝原状态机休眠时间到当前状态机
91+
*
92+
* @param sleepTime
93+
*/
94+
public void copyTime(int sleepTime) {
95+
96+
}
97+
98+
/**
99+
* 获取当前状态机休眠时间
100+
*
101+
* @return
102+
*/
103+
public int getTime() {
104+
return 0;
105+
}
106+
107+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package info.xiaomo.gengine.ai.fsm.monster;
2+
3+
4+
import info.xiaomo.gengine.map.AbstractGameMap;
5+
import info.xiaomo.gengine.map.obj.AbstractMonster;
6+
7+
/**
8+
* 怪物AI接口, 用于做不同的怪物AI,所有这些方法都在怪物状态机中调用
9+
*
10+
* @author zhangli
11+
* 2017年6月6日 下午9:55:45
12+
*/
13+
public interface MonsterAI {
14+
15+
boolean activeEnter(AbstractGameMap map, AbstractMonster monster);
16+
17+
boolean activeUpdate(AbstractGameMap map, AbstractMonster monster, int dt);
18+
19+
boolean activeExit(AbstractGameMap map, AbstractMonster monster);
20+
21+
22+
boolean battleEnter(AbstractGameMap map, AbstractMonster monster);
23+
24+
boolean battleUpdate(AbstractGameMap map, AbstractMonster monster, int dt);
25+
26+
boolean battleExit(AbstractGameMap map, AbstractMonster monster);
27+
28+
boolean dieEnter(AbstractGameMap map, AbstractMonster monster);
29+
30+
boolean dieUpdate(AbstractGameMap map, AbstractMonster monster, int dt);
31+
32+
boolean dieExit(AbstractGameMap map, AbstractMonster monster);
33+
34+
boolean sleepEnter(AbstractGameMap map, AbstractMonster monster);
35+
36+
boolean sleepUpdate(AbstractGameMap map, AbstractMonster monster, int dt);
37+
38+
boolean sleepExit(AbstractGameMap map, AbstractMonster monster);
39+
40+
41+
}

0 commit comments

Comments
 (0)