Since you are talking about screens, I feel it's best to separate all that logic into different Screens. What I normally do:
Define an interface called screen, and have multiple screens implement it. Like LoadingScreen, MainMenuScreen, GameScreen, GameOverScreen, HighScoreScreen etc.
In your game you put a variable that holds the current screen. Each loop, you call screen.update() and render the current screen. This will save you a lot of "if this state do that" as your state is defined by current screen.
This will separate your logic very nicely.
Example code:
### Screen interface ###
public interface Screen {
public void show();
public void update(float delta);
public void render(float delta);
public void hide ();
}
### An implementation of screen ###
public class MainMenuScreen implements Screen {
private Game game;
public MainMenuScreen(Game game) {
this.game = game;
}
public void show() {
// init stuff
}
public void update(float delta) {
// react to clicks, update animations etc.
if (buttonwasclicked) {
game.setScreen(new GameScreen(game)); // change the screen
}
}
public void render(float delta) {
// draw everything
}
public void hide() {
// release all resources, as the screen is being hidden
}
}
### Game, drawing the appropriate screen ###
public class Game {
public Screen screen;
public void update() {
screen.update(getDeltaTime);
screen.render();
}
public void setScreen(Screen screen) {
this.screen.hide();
this.screen = screen;
this.screen.show();
}
}
Or depending on your game setup, you maybe have an infinite loop as your game.
while(true) {
calculatetimesincelastframe()
screen.update(time);
screen.render(time);
}