Using a switch statement to determine state of game

I’m making a tower defense game using libgdx and scene2d. For my UI during gameplay, I implemented a State Pattern (or at least a variant) along with MVP and Observer pattern.
To do this, I have a view, presenter, and uiStateManager class. The uiStateManager is referenced by various presenters and services to alter that state of the UI. For instance, when placing a tower on the map, the HUD should disable buttons, hide certain widgets, etc.

The following is my uiStateManager class:


public class GameUIStateManager {
	
	private GameUIState state;
	private CopyOnWriteArrayList<IGameUIStateObserver> observers = new CopyOnWriteArrayList<IGameUIStateObserver>(); 
	public GameUIStateManager(){
		this.setState(GameUIState.STANDBY); //init in standby
	}
	public void attach(IGameUIStateObserver observer){
		observers.add(observer);
	}
	public void notifyObservers(){
		for(IGameUIStateObserver observer : observers){
			observer.changeUIState(state);
		}
	}
	public void setState(GameUIState state){
		this.state = state;
		notifyObservers();
	}
	public GameUIState getState(){
		return state;
	}
	
	public enum GameUIState {
	    INSPECTING,
	    OPTIONS,
	    STANDBY,
	    GAME_OVER,
	    PLACING_TOWER;
	    
	}
}

So the UIStateManager holds a list of IGameUIStateObservers which looks like:


public interface IGameUIStateObserver {
	public void changeUIState(GameUIState state);
}

The State Manager notifies all of its observers whenever it changes states.
So for instance, my HUD Presenter implements IGameUIStateObserver and attaches itself to the uiGameStateManager object.
When it is notified that the uiStateManager has changed states, it uses a switch to determine how the HUD View should update itself.

Method inside HUD Presenter:


	@Override
	public void changeUIState(GameUIState state) {
		switch(state){
		case GAME_OVER:
			view.gameOverState();
			break;
		case OPTIONS:
			view.optionsState();
			break;
		case STANDBY:
			view.standByState();
			break;
		default:
			break;
		}
	}

So for example when the StateManager changes to GAME_OVER, it notifies my HUD Presenter which calls the gameOverState method on the HUD View. The HUD view then updates itself to disable buttons.

Method in HUD View:


	public void gameOverState(){
		btnEnlist.setTouchable(Touchable.disabled);
		btnWave.setTouchable(Touchable.disabled);
		btnSpeedGroup.setTouchable(Touchable.disabled);
		btnOptions.setTouchable(Touchable.disabled);
	}

The GameOver Presenter is also notified to render itself and show the GameOver overlay which shows various buttons and other widgets. However, the game is still in the background with the disabled buttons.

Method in GameOver Presenter:


	public void changeUIState(GameUIState state) {
		switch(state){
		case GAME_OVER:
			view.gameOverState();
			setWavesCompleted();
			break;
		default:
			view.standByState();
			break;
		}		
	}

	public void setWavesCompleted() {
		view.setWavesCompleted(String.valueOf(player.getWavesCompleted()));
	}

Method in GameOverView:


	@Override
	public void gameOverState(){
		this.setVisible(true);
	}
	@Override
	public void setWavesCompleted(String wavesCompleted){
		lblWavesCompletedCount.setText(wavesCompleted);
	}

So the GameOverView also updates itself, although it isn’t as complex as the HUD.

I know switch statements are a code smell, and I’ve been trying to come up with a way to improve on this design. However, nothing seems to be as flexible and easy as this. I tried to come up with a polymorphic way to handle this with actual concrete state classes, but the issue is that the views update themselves. I could do away with the whole MVP pattern and just have State classes and Views. Then pass in as a parameter the various views to the State Class. So for example, a state class called GameOver would have references to the HUD View and GameOverView. It would then call hudView.gameOverState() and gameOverView.gameOverState() on the views themselves, but I’m not sure if that helps at all.

How can I refactor my design pattern? I like what I have now, but I would like to learn other alternatives and if possible, improvements.

Thanks!

Usually, when I don’t know how to design something or have some trouble with it, the first thing I do is to get rid of all design patterns and try to come up with the most straightforward and unobstrusive solution possible. Which in many cases happens to be the best solution in the end.
Point being: Don’t introduce design patterns and then try to force your application into them, but design your solution straightforward (concrete methods calling concrete other methods in concrete classes and not via dynamical dependencies (aka. observer)).
Design patterns always come at a cost and when time comes you have to weigh out whether introducing them actually makes anything easier. And in the past I found that they really hardly make things easier.
This is not meant as a rant on design patterns, but just to make sure one uses them when needed.
When we want flexibility it is usually not because we know we need it but because we don’t know whether we don’t need it. And that is because we don’t know what our application actually does (i.e. which concrete state changes exist and via which conrete methods they are being triggered).
So maybe draw a state diagram first and then implement that straightforward via method calls.
Probably you realize that you just end up with a single class with concrete methods for each concrete state. Who knows? But simpler is always better. :slight_smile:

Also: Who told you that using switch statements on enums is a code smell?

Thanks for the reply.

I agree in that sometimes it’s best to not worry about a design pattern. It’s what I originally did. However, my goal in making my game was mostly to become a better programmer. Therefore, I tried to implement different design patterns to learn more and further improve my code. I probably went a bit overboard, but I definitely learned a lot!

The one thing I couldn’t help but notice was the amount of circular dependency, specifically with the framework I’m using (libgdx w/ scene2d). I often found my self in places where I had no option but to have some circular dependency. I felt like most of the examples I was following or repositories I was viewing also suffered from this and didn’t really show a way to correct it. They too often had parent classes passing references to itself to classes that they owned (specifically the Game and Stage classes in libgdx/scene2d). Therefore, in an effort to improve my code, I decided to implement my State Manager classes. That way different classes could subscribe to a specific state manager and receive notifications and react accordingly. The state manager/states(enums) have almost zero knowledge. It’s up to the observers to decide what to do. Sometimes they update themselves, other times they just ignore the state because it has nothing to do with them so they go/stay in standby. I still think there are a few issues with that idea, but it was a vast improvement of what I had before. I felt that it was best to still describe them as StateManagers, but perhaps it’s isn’t much of a state pattern.

My understanding with switch statements was that they are often the cause of poor design and can be replaced with polymorphism. I tried to do that, but I didn’t really see much of an improvement. Perhaps the fact that I’m using an enum makes it better?

Maybe it’s late over here, but I found it difficult to read your first post. I think part of my brain switches off when it encounters texts with a high degree of references to design patterns! At least I find it more helpful to proceed on the basis of building something that works and then improving it. Refactoring tools are powerful these days and I prefer not to invest in upfront design.

[quote]Therefore, I tried to implement different design patterns to […] further improve my code.
[/quote]

[quote]Therefore, in an effort to improve my code, I […]
[/quote]

[quote]I tried to do that, but I didn’t really see much of an improvement.
[/quote]
The question in all three quoted cases above is: on what basis do we evaluate which design decision is better or worse? Feeling will not help in most cases when the domain is probably not known well.
If you are maybe a Java EE/Spring/Web programmer you are probably used to design patterns applicable in web applications. That may not be the case with games.
I agree with ags1 that in your problem description you rushed in with design patterns and left interesting aspects about the actual game design (the business logic if you will) unmentioned.
The only thing that is known so far is that it is a tower defense game. And then there are some technicalities known, such as that you use libGDX.
That’s why I feared that design-pattern-envy may be the problem in your case. :slight_smile:

So also like ags1 said: Don’t concern yourself with big upfront design and whether some decision will hold under the test of time, because we usually don’t know that upfront.
Keep the design simple, so that it can always be refactored easily.