在红警游戏里有菜单切换,基于状态机写了下大概的代码,不过不太确定代码对不对。。。。
?
?
?
?
import java.util.AbstractMap;
import java.util.Comparator;
import java.util.TreeMap;
//游戏页面一共有多少状态
class State
{
public final static int MainMenu = 1; //主菜单
public final static int SinglePlayer = 2; // 单人游戏
public final static int Encounter = 3; // 遭遇战
public final static int GameStarted = 4; // 游戏已启动
public final static int Exit = 5; // 退出游戏
}
//在不同游戏页面的时候,有哪些用户可以输入的事件
class Input{
//主菜单页面
public final static int MainMenu_Single = 11;
public final static int MainMenu_Exit = 12;
//单人游戏页面
public final static int Single_NewCampaign = 21; //新战役
public final static int Single_Load = 22; // 加载历史存档
public final static int Single_Enconter = 23; //遭遇战
public final static int Single_MainMenu = 24; //返回主菜单
//遭遇战页面
public final static int Enconter_StartGame = 31; //开始游戏
public final static int Enconter_MapSet = 32; //地图设置
public final static int Enconter_LastPage = 31; //返回上一页
}
//用于记录当前游戏的状态和用户的输入
class Record{
public int currentState;
public int input;
public Record(int currentState, int input) {
this.currentState = currentState;
this.input = input;
}
}
//页面的基类,比如,可以从JFrame继承,这样都有画面
class Base
{
String name;
Base(String name)
{
this.name = name;
}
public String getName() {
return name;
}
}
//游戏主菜单页面,正常来说,上边会有很多按钮
class Main extends Base
{
Main()
{
super("Main");
}
}
//单人游戏菜单,正常来说,上边会有很多按钮
class Single extends Base
{
Single()
{
super("Single");
}
}
//遭遇战菜单页面,正常来说,上边会有很多按钮
class Enconter extends Base
{
Enconter()
{
super("Enconter");
}
}
//已经开始游戏页面,正常来说,上边会有玩家、坦克、军队等等
class Game extends Base
{
Game()
{
super("Game started");
}
}
//地图设置菜单页面,正常来说,上边会有很多按钮
class Map extends Base
{
Map()
{
super("Map");
}
}
//根据状态机当前状态以及用户输入,通过查找treeMap返回的新的状态,以及一个页面的类。
class Result
{
int newState;
Base base;
public Result(int newState, Base base) {
this.newState = newState;
this.base = base;
}
}
public class FSM
{
public TreeMap<Record, Result> treeMap;
int CurrentState;
Base CurrentPage;
FSM()
{
//游戏开始运行时,会在第一个主菜单页面
CurrentState = State.MainMenu;
//重写了下比较器,为了把当前状态和用户的输入作为Map的key参数
treeMap = new TreeMap<>(new Comparator<Record>() {
@Override
public int compare(Record record1, Record record2) {
if (record1.currentState != record2.currentState)
{
return record1.currentState - record2.currentState;
}
else if (record1.input != record2.input)
{
return record1.input - record2.input;
}
else
{
return 0;
}
}
});
/**
*这里是把状态机初始化,当前只添加了三行:
* 1、第一行是从主菜单页面跳转到单人模式菜单页面;
* 2、第二行是从单人模式菜单页面跳转到遭遇战菜单页面;
* 3、第三行是从遭遇战菜单页面跳转到开始游戏遭遇战菜单页面;
* 这里实际上可以根据菜单的多少可以添加和删除。
*/
treeMap.put(new Record(State.MainMenu, Input.MainMenu_Single), new Result(State.SinglePlayer, new Single()));
treeMap.put(new Record(State.SinglePlayer, Input.Single_Enconter), new Result(State.Encounter, new Enconter()));
treeMap.put(new Record(State.Encounter, Input.Enconter_StartGame), new Result(State.GameStarted, new Game()));
}
public AbstractMap<Record,Result> getTreeMap() {
return treeMap;
}
public void setTreeMap(TreeMap<Record, Result> treeMap) {
this.treeMap = treeMap;
}
public Base getCurrentPage() {
return CurrentPage;
}
public void setCurrentPage(Base currentPage) {
CurrentPage = currentPage;
}
public int getCurrentState() {
return CurrentState;
}
public void setCurrentState(int currentState) {
CurrentState = currentState;
}
//状态机的运行,比如:当用户进入游戏,首先会在主菜单,当用户不断输入的时候,这里会不断的切换当前页面
public void Run(int Input)
{
//基于当前状态和用户的输入,看用户输入是否合法,如果合法则进行状态切换
Result result = treeMap.get(new Record(getCurrentState(), Input));
if (result != null)
{
//如果合法则切换新的状态,并把对应页面的类返回
setCurrentState(result.newState);
setCurrentPage(result.base);
System.out.println(result.base.getName());
}
};
public static void main(String[] args) {
FSM fsm = new FSM();
fsm.Run(Input.MainMenu_Single);
fsm.Run(Input.Single_Enconter);
fsm.Run(Input.Enconter_StartGame);
}
}