package com.arretadogames.pilot.game;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.Log;
import aurelienribon.tweenengine.BaseTween;
import aurelienribon.tweenengine.Timeline;
import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenAccessor;
import aurelienribon.tweenengine.TweenCallback;
import com.arretadogames.pilot.config.GameSettings;
import com.arretadogames.pilot.loading.LoadManager;
import com.arretadogames.pilot.render.opengl.GLCanvas;
import com.arretadogames.pilot.screens.CharacterSelectionScreen;
import com.arretadogames.pilot.screens.GameScreen;
import com.arretadogames.pilot.screens.GameStore;
import com.arretadogames.pilot.screens.InputEventHandler;
import com.arretadogames.pilot.screens.MainMenuScreen;
import com.arretadogames.pilot.screens.PremiationScreen;
import com.arretadogames.pilot.screens.SplashScreen;
import com.arretadogames.pilot.screens.StageSelectionScreen;
import com.arretadogames.pilot.screens.TournamentSelectionScreen;
import com.arretadogames.pilot.ui.AnimationManager;
import com.arretadogames.pilot.util.Assets;
import com.arretadogames.pilot.world.GameWorld;
import java.util.HashMap;
/**
* Game class represents our Game.
* This entity should hold all information related to <b>Game Logic</b>
*/
public class Game implements TweenAccessor<Game>, LoadManager.LoadFinisherCallBack {
private static final int LEFT = 1;
private static final int RIGHT = 2;
private static Game game;
private GameState currentState;
private HashMap<GameState, GameScreen> gameScreens;
// Transition
private boolean transitionStateOn;
private Rect transitionRect;
private LoadManager loadManager;
private GameState nextState;
private GameMode gameMode;
/**
* Creates a Game
*/
private Game() {
nextState = GameState.SPLASH;
loadManager = LoadManager.getInstance();
gameScreens = new HashMap<GameState, GameScreen>();
setGameMode(GameMode.UNDEFINED);
Assets.load();
gameScreens.put(GameState.RUNNING_GAME, new GameWorld());
gameScreens.put(GameState.MAIN_MENU, new MainMenuScreen());
gameScreens.put(GameState.SPLASH, new SplashScreen());
// gameScreens.put(GameState.GAME_OVER, new FinishRaceScreen());
gameScreens.put(GameState.CHARACTER_SELECTION, new CharacterSelectionScreen());
gameScreens.put(GameState.LEVEL_SELECTION, new StageSelectionScreen());
gameScreens.put(GameState.TOURNAMENT_SELECTION, new TournamentSelectionScreen());
gameScreens.put(GameState.PREMIATION, new PremiationScreen());
gameScreens.put(GameState.GAME_STORE, new GameStore());
transitionStateOn = false;
loadManager.prepareLoad(new GameState[] { nextState });
currentState = GameState.LOADING;
}
/**
* Gets the GameScreen related to the given GameState
* @param state
* GameState
* @return GameScreen, or null if there's not screen related to this GameState
*/
public GameScreen getScreen(GameState state) {
return gameScreens.get(state);
}
/**
* Renders the current state of the game
*
* @param canvas
* GameCanvas to draw
* @param timeElapsed
* Time Elapsed since last frame
*/
public void render(GLCanvas canvas, float timeElapsed) {
AnimationManager.getInstance().update(timeElapsed);
if (currentState.equals(GameState.LOADING)) {
loadManager.swapTextures(game, canvas);
return;
} else {
if (gameScreens.containsKey(currentState))
getScreen(currentState).render(canvas, timeElapsed);
}
if (transitionStateOn) {
canvas.drawRect(transitionRect.left, transitionRect.top,
transitionRect.right, transitionRect.bottom,
Color.rgb(0, 0, 0));
}
}
/**
* Performs a step in the current game state's logic
*
* @param timeElapsed
* Time Elapsed since last frame
*/
public void step(float timeElapsed) {
if (currentState.equals(GameState.LEVEL_RESTART)) {
goTo(GameState.RUNNING_GAME);
return;
}
if (gameScreens.containsKey(currentState))
gameScreens.get(currentState).step(timeElapsed);
}
/**
* Handles the input in the current game state
*
* @param event
* Input Event to be handled
*/
public void input(InputEventHandler event) {
if (transitionStateOn)
return; // Input Disabled when Transition
// Safe-check
if (gameScreens.get(currentState) != null) {
gameScreens.get(currentState).input(event);
}
}
/**
* (Asynchronous method) Switch the current game state
*
* @param state
* new game's current state
*/
public void goTo(GameState state) {
if (transitionStateOn) {
Log.e("Game", "Tried to call goTo while on transition state");
return;
}
nextState = state;
if (getScreen(nextState) != null) // Loads if there is a screen
getScreen(nextState).onLoading();
loadManager.prepareLoad(new GameState[] { nextState });
startTransitionAnimation();
}
/*
* (Asynchronous method) Changes the current state of the Game
*/
private void changeState(GameState state) {
if (state != null) {
if (getScreen(currentState) != null) // Unloads if there is a screen
getScreen(currentState).onUnloading();
currentState = state;
}
}
/**
* Gets the only and single instance of Game
* @return Game
*/
public static Game getInstance() {
if (game == null)
game = new Game();
return game;
}
@Override
public int getValues(Game game, int type, float[] returnValues) {
switch (type) {
case LEFT:
returnValues[0] = transitionRect.left;
break;
case RIGHT:
returnValues[0] = transitionRect.right;
break;
}
return 1;
}
@Override
public void setValues(Game game, int type, float[] setValues) {
switch (type) {
case LEFT:
transitionRect.left = (int) setValues[0];
break;
case RIGHT:
transitionRect.right = (int) setValues[0];
break;
}
}
/*
* (Synchronous method) Starts the transition to the next state
*/
private void startTransitionAnimation() {
transitionStateOn = true;
// Stop All tweens associated with game
AnimationManager.getInstance().killTarget(this);
transitionRect = new Rect(
(int) GameSettings.TARGET_WIDTH, 0,
(int) GameSettings.TARGET_WIDTH, (int) GameSettings.TARGET_HEIGHT);
Timeline.createSequence()
.push(Tween.to(this, LEFT, 0.4f).target(0f))
.push(Tween.call(new TweenCallback() {
@Override
public void onEvent(int arg0, BaseTween<?> arg1) {
changeState(GameState.LOADING);
}
}))
.start(AnimationManager.getInstance());
}
/**
* (Asynchronous method) Causes the Game to pause
*/
public void onPause() {
if (currentState == GameState.RUNNING_GAME) {
((GameWorld)getScreen(GameState.RUNNING_GAME)).onPause();
}
}
/**
* (Asynchronous method) Causes the Game to resume
*/
public void onResume() {
}
@Override
public void onLoadFinished(boolean error) { // TODO @yuri: Handle error
if (nextState.equals(GameState.SPLASH)) {
//Don't perform animation on splash screen
changeState(nextState);
nextState = null;
transitionStateOn = false;
return;
}
Timeline.createSequence()
.push(Tween.call(new TweenCallback() {
@Override
public void onEvent(int arg0, BaseTween<?> arg1) {
changeState(nextState);
nextState = null;
transitionRect.left = 0;
}
}))
.push(Tween.to(game, RIGHT, 0.5f).target(0f))
.push(Tween.call(new TweenCallback() {
@Override
public void onEvent(int arg0, BaseTween<?> arg1) {
transitionStateOn = false;
}
}))
.start(AnimationManager.getInstance());
}
public void onBackPressed() {
if (gameScreens.get(currentState) != null)
gameScreens.get(currentState).onBackPressed();
}
public GameMode getGameMode() {
return gameMode;
}
public void setGameMode(GameMode gameMode) {
this.gameMode = gameMode;
}
}