/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package es.eucm.ead.engine.game;
import aurelienribon.tweenengine.Tween;
import aurelienribon.tweenengine.TweenManager;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.scenes.scene2d.Event;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import es.eucm.ead.engine.factories.EffectFactory;
import es.eucm.ead.engine.factories.EventFactory;
import es.eucm.ead.engine.game.interfaces.EffectsHandler;
import es.eucm.ead.engine.game.interfaces.EngineHook;
import es.eucm.ead.engine.game.interfaces.GUI;
import es.eucm.ead.engine.gameobjects.EventedGO;
import es.eucm.ead.engine.gameobjects.effects.EffectGO;
import es.eucm.ead.engine.tracking.GameTracker;
import es.eucm.ead.model.elements.AdventureGame;
import es.eucm.ead.model.elements.Chapter;
import es.eucm.ead.model.elements.effects.Effect;
import es.eucm.ead.model.elements.operations.ElementField;
import es.eucm.ead.model.elements.scenes.SceneElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Singleton
public class Game {
static private Logger logger = LoggerFactory.getLogger(Game.class);
public static final String HOOK_AFTER_UPDATE = "after_update";
public static final String HOOK_AFTER_MODEL_READ = "after_model_read";
public static final String HOOK_AFTER_CHAPTER_READ = "after_chapter_read";
public static final String HOOK_AFTER_RENDER = "after_render";
/**
* Game gui
*/
private GUI gui;
/**
* Game state
*/
private GameState gameState;
/**
* Game tween manager
*/
private TweenManager tweenManager;
/**
* If the game state is paused
*/
private boolean paused;
/**
* Engine hooks
*/
private Map<String, List<EngineHook>> hooks;
/**
* Game tracker
*/
private GameTracker tracker;
/**
* Current adventure
*/
private AdventureGame adventure;
/**
* Current chapter
*/
private Chapter chapter;
/**
* Current adventure game object
*/
private EventedGO adventureGO;
/**
* Current chapter game object
*/
private EventedGO chapterGO;
/**
* Effects handler. Deals with adding, removing and updating effects
*/
private EffectsHandler effectsHandler;
// Aux
private ArrayList<String> hookNameDelete;
private ArrayList<EngineHook> hookDelete;
@Inject
public Game(GUI gui, GameState gameState, EventFactory eventFactory,
GameTracker tracker, EffectFactory effectFactory) {
this.gui = gui;
this.gameState = gameState;
this.tweenManager = new TweenManager();
this.tracker = tracker;
this.effectsHandler = new EffectsHandler(gameState, effectFactory);
// Init tween manager
Tween.registerAccessor(ElementField.class, gameState);
Tween.registerAccessor(ElementField.class, gameState);
hooks = new HashMap<String, List<EngineHook>>();
// Aux
hookNameDelete = new ArrayList<String>();
hookDelete = new ArrayList<EngineHook>();
// Adventure and chapter game object
adventureGO = new EventedGO(eventFactory);
chapterGO = new EventedGO(eventFactory);
}
/**
* Returns the game state
*
* @return
*/
public GameState getGameState() {
return gameState;
}
/**
* @return Returns the gui
*/
public GUI getGUI() {
return gui;
}
/**
* Sets the current adventure
* @param adventure the current adventure
*/
public void setAdventure(AdventureGame adventure) {
logger.debug("Setting adventure");
this.adventure = adventure;
adventureGO.setElement(adventure);
reset();
}
/**
* Sets the current chapter
* @param chapter the current chapter
*/
public void setChapter(Chapter chapter) {
logger.debug("Setting chapter");
this.chapter = chapter;
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
chapterGO.setElement(Game.this.chapter);
}
});
reset();
}
public TweenManager getTweenManager() {
return tweenManager;
}
/**
* @return true if the game loop is paused
*/
public boolean isPaused() {
return paused;
}
/**
* Change the paused status of the game loop
*
* @param paused sets if the game is paused
*/
public void setPaused(boolean paused) {
this.paused = paused;
}
/**
* Returns the milliseconds since last update
*
* @return
*/
public int getSkippedMilliseconds() {
return isPaused() ? 0 : (int) (Gdx.graphics.getDeltaTime() * 1000);
}
/**
* Returns the current adventure game model ({@link AdventureGame})
*
* @return The adventure game model
*/
public AdventureGame getAdventureModel() {
return adventure;
}
/**
* Returns the current chapter
*
* @return
*/
public Chapter getCurrentChapter() {
return chapter;
}
/**
* Disposes all the resources allocated by the engine and destroys the GUI
*/
public void dispose() {
tracker.stop();
}
/**
* Resets all necessary in the game to start a new chapter (effects, tweens...)
*/
public void reset() {
effectsHandler.clearEffects(true);
tweenManager.killAll();
}
/**
* Updates the game state
*
* @param delta milliseconds since last update
*/
public void act(float delta) {
// Remove hooks
for (int i = 0; i < this.hookNameDelete.size(); i++) {
removeHookImpl(hookNameDelete.get(i), hookDelete.get(i));
}
hookNameDelete.clear();
hookDelete.clear();
// Scene
if (!isPaused()) {
effectsHandler.act(delta);
// Tween manager
tweenManager.update(delta);
this.adventureGO.act(delta);
this.chapterGO.act(delta);
}
doHook(HOOK_AFTER_UPDATE);
}
public void addHook(String hookName, EngineHook hook) {
List<EngineHook> hooksList = hooks.get(hookName);
if (hooksList == null) {
hooksList = new ArrayList<EngineHook>();
hooks.put(hookName, hooksList);
}
hooksList.add(hook);
Collections.sort(hooksList);
}
public void removeHook(String filterName, EngineHook hook) {
this.hookNameDelete.add(filterName);
this.hookDelete.add(hook);
}
private void removeHookImpl(String hookName, EngineHook hook) {
List<EngineHook> hooksList = hooks.get(hookName);
if (hooksList != null) {
hooksList.remove(hook);
}
}
public void doHook(String hookName) {
List<EngineHook> hooksList = hooks.get(hookName);
if (hooksList != null) {
for (EngineHook h : hooksList) {
h.execute(this, gameState, gui);
}
}
}
public EffectsHandler getEffectsHandler() {
return effectsHandler;
}
/**
* Returns a list with all game objects linked to the current effects.
*
* @return a list with all game objects linked to the current effects.
*/
public List<EffectGO<?>> getEffects() {
return effectsHandler.getEffects();
}
/**
* Clears all the current effects
*
* @param clearPersistents sets if persistent effects should also be deleted
*/
public void clearEffects(boolean clearPersistents) {
effectsHandler.clearEffects(clearPersistents);
}
/**
* Adds an effect without any gui action associated
*
* @param e the effect
*/
public void addEffect(Effect e) {
addEffect(e, null, null);
}
/**
* Adds a new effect to the effects' tail
*
* @param e the new effect
* @param action the action that launched the effect
* @param parent scene element who launched the effect
* @return the effect game object create from the effect element
*/
public EffectGO<?> addEffect(Effect e, Event action, SceneElement parent) {
return effectsHandler.addEffect(e, action, parent);
}
}