Hello all,
I’m working on a Roguelike dungeon crawler and I am learning new game development/coding techniques along the way. I am having trouble creating a finite state machine that switches between states with user input as seen in the diagram below:
The issue I’m having is with using the same key for entering and leaving a state. (Eg. Normal Gameplay --> Full Map View --> Normal Gameplay). The method I am currently using just rapidly switches between states while the key is pressed.
I’m really struggling to come up with a logical way of keeping track of the user input for this.
I’m currently using a booean[256] array inside keyPressed() and keyReleased() to set each character either pressed (true) or not pressed (false).
Here is the relevant code:
// start, saveExit, death, win;
// 1, 2, 3, 4
int MAXKEYS = 256;
boolean[] keys = new boolean[MAXKEYS];
GameStates states;
void setup() {
states = GameStates.TitleScreen;
println(states.toString());
}
String prevString;
void draw() {
prevString = states.toString();
states = states.nextState(keys, keys['1'], keys['2'], keys['3'], keys['4']);
if (!prevString.equals(states.toString())) {
println(states.toString());
}
}
void keyPressed() {
updateKeys(true);
if (key == ESC) {
key = 0;
}
}
void keyReleased() {
updateKeys(false);
if (key == ESC) {
key = 0;
}
}
void updateKeys(boolean b) {
if (key < MAXKEYS && keys[key] != b) {
keys[key] = b;
}
}
public enum GameStates {
TitleScreen {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
if (start) {
return NormalGameplay;
} else {
return TitleScreen;
}
}
}
,
NormalGameplay {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
if (death) {
return DeathScreen;
} else if (win) {
return EndGame;
} else if (input[ESC]) {
return MenuScreen;
} else if (input['m']) {
return FullMapView;
} else if (input['c']) {
return CharacterInformationView;
} else {
return NormalGameplay;
}
}
}
,
MenuScreen {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
if (saveExit) {
return TitleScreen;
} else if (input[ESC]) {
return NormalGameplay;
} else {
return MenuScreen;
}
}
}
,
DeathScreen {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
int todo; // stats
return TitleScreen;
}
}
,
FullMapView {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
if (input['m']) {
return NormalGameplay;
} else if (input['c']) {
return CharacterInformationView;
} else {
return FullMapView;
}
}
}
,
CharacterInformationView {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
if (input['c']) {
return NormalGameplay;
} else if (input['m']) {
return FullMapView;
} else {
return CharacterInformationView;
}
}
}
,
EndGame {
@Override
GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win) {
int todo; // credits
return TitleScreen;
}
};
abstract GameStates nextState(boolean[] input, boolean start, boolean saveExit, boolean death, boolean win);
}