Java tutorial
/******************************************************************************* Copyright 2014 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. ******************************************************************************/ package com.sidereal.dolphinoes.architecture; import com.badlogic.gdx.Game; import com.badlogic.gdx.Screen; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap.Entry; import com.sidereal.dolphinoes.architecture.core.Assets; import com.sidereal.dolphinoes.architecture.core.Debug; import com.sidereal.dolphinoes.architecture.core.DolphinOESConfiguration; import com.sidereal.dolphinoes.architecture.core.GameData; import com.sidereal.dolphinoes.architecture.core.Time; import com.sidereal.dolphinoes.architecture.core.input.Input; import com.sidereal.dolphinoes.util.DolphinOESException; /** Bridge between LibGDX {@link ApplicationListener} and DolphinOES' {@link DolphinOES}. * <p> * Creates a {@link DolphinOES} instance using a {@link DolphinOESConfiguration} instance for changing framework * settings, as well as a {@link GameScene} instance to redirect to. The DolphinOES {@link DolphinOESConfiguration} * parameter is not necessary, as there are 2 constructors that can be called, {@link DolphinOES#DolphinOES(GameScene)} * and {@link DolphinOES#DolphinOES(GameScene, DolphinOESConfiguration)} * * @author Claudiu Bele */ public class DolphinOES extends Game { // region fields @SuppressWarnings("unused") private static final String version = "Beta 0.4.9.3"; public static final Time time = new Time(); public static final Debug debug = new Debug(); public static final Assets assets = new Assets(); public static final GameData data = new GameData(); public static final Input input = new Input(); /** Array containing all of the functionality modules. */ private static ObjectMap<Class<? extends Module>, Module> modules; private static DolphinOES instance; private GameScene targetScene; private boolean isFocused; // endregion // region constructors /** DolphinOES constructor that does not require a {@link DolphinOESConfiguration} parameter. This constructor calls * {@link #DolphinOES(GameScene, DolphinOESConfiguration)} by creating a new <code>DolphinOES</code> instance (thus * the application has default configuration). * <P> * Is to be used in the platform-dependent main methods. * * @throws DolphinOESException * see {@link #DolphinOES(GameScene, DolphinOESConfiguration)} for exception * @param initialScene * The scene to switch to after initialisation */ public DolphinOES(GameScene initialScene) { this(initialScene, new DolphinOESConfiguration()); } /** DolphinOES constructor that requires scene and a configuration. If the configuration is null, a new instance is * created with default values. * <p> * The default application modules are configured, by calling the configure method in them with the * DolphinOESConfiguration parameters. All custom modules found in {@link DolphinOESConfiguration#modules} are added * to {@link DolphinOES#modules}. * * * @throws DolphinOESException * when the <code>initialscene</code> parameter is null * @param initialScene * @param cfg */ public DolphinOES(GameScene initialScene, DolphinOESConfiguration cfg) { if (initialScene == null) throw new DolphinOESException("DolphinOES(GameScene,DolphinOESConfiguration) constructor " + "parameter 'initialScene' of type GameScene is null"); if (cfg == null) cfg = new DolphinOESConfiguration(); debug.configure(cfg); assets.configure(cfg); data.configure(cfg); input.configure(cfg); time.configure(cfg); DolphinOES.modules = new ObjectMap<Class<? extends Module>, Module>(); DolphinOES.modules.putAll(cfg.modules); DolphinOES.instance = this; targetScene = initialScene; } /** Method called after initialising the LibGDX backend. The modules' (default and custom) {@link Module#create()} * method is called, in which LibGDX data can be accessed. * <p> * The method also sets the screen to render as the one passed in the constructors. */ @Override public void create() { // create the default modules debug.create(); assets.create(); data.create(); input.create(); time.create(); // create all custom modules, now they can access Gdx functionality for // proper setup for (Entry<Class<? extends Module>, Module> entry : modules.entries()) { entry.value.create(); } setScreen(targetScene); } /** Method called when unfocusing the window. Sets {@link DolphinOES#isFocused} to true, which can be accessed using * {@link #isFocused()} for background actions to run ( nothing happens by default) */ @Override public void pause() { isFocused = true; super.pause(); } /** Method called when focusing the window. Sets {@link DolphinOES#isFocused} to false, which can be accessed using * {@link #isFocused()} for background actions to run ( nothing happens by default) */ @Override public void resume() { isFocused = false; super.resume(); } /** Method called when every frame that handles scene transitions, updating modules( default and custom) as well as * calling {@link GameScene#render(float)} from the parent class implementation of {@link Game#render()}. */ @Override public void render() { if (getScene() != targetScene) handleSceneTrasition(); // update time data // update default modules debug.update(); assets.update(); data.update(); time.update(); // update all custom Modules for (Entry<Class<? extends Module>, Module> entry : modules.entries()) { entry.value.update(); } super.render(); input.update(); } /** Method for changing the screen. The transition between scenes and the objects they share will be handled * automatically in {@link #handleSceneTrasition()}. If the passed parameter is not an instance of {@link GameScene} * , an exception is thrown * * @throws {@link DolphinOESException} if the passed parameter is not an instance of {@link GameScene}. * @param screen * The screen to change to */ @Override public void setScreen(Screen screen) { if (instance.getScreen() == null) { if (!(screen instanceof GameScene)) throw new DolphinOESException( "DolphinOES.setScreen parameter screen has to be a subclass of GameScene"); super.setScreen(screen); ((GameScene) screen).createGameBatches(); ((GameScene) screen).createScene(); } else { instance.targetScene = (GameScene) screen; ((GameScene) targetScene).createGameBatches(); } } /** Returns the current scene that is being rendered. * * @return the current scene */ public static GameScene getScene() { return (GameScene) instance.getScreen(); } public static DolphinOES getInstance() { return instance; } /** Returns whether or not the application is focused. * * @return boolean value for whether or not the application is focused. */ public static boolean isFocused() { return instance.isFocused; } // endregion // region methods /** Adds a module to run throughout the entire application. This method is to be used at runtime, as for * initialisation, you can add {@link Module} to {@link DolphinOESConfiguration} using * {@link DolphinOESConfiguration#addModule(Module)}, * * <p> * The module will be accessible from game scenes, batches, objects and behaviors through {@link #getModule(Class)}. * * @param module * @return */ public static <T extends Module> Class<DolphinOES> addModule(T module) { if (module == null) throw new NullPointerException( "DolphinOESConfiguration.addModule parameter 'module' of type Module is null"); if (modules.get(module.getClass()) != null) throw new DolphinOESException("DolphinOESConfiguration.addModule parameter type " + module.getClass() + " is already in the list of modules"); modules.put(module.getClass(), module); return DolphinOES.class; } /** Returns a custom module, retrieved by passing the class we want the Module we want to retrieve has. * * @throws DolphinOESException * if the module class parameter does not implement the Module interface or is not in the list of * modules * @param moduleClass * The class of the module we want to return. * * @return Module implementation, or an exception */ @SuppressWarnings("unchecked") public static <T extends Module> T getModule(Class<T> moduleClass) { if (!moduleClass.getInterfaces()[0].equals(Module.class)) throw new DolphinOESException( "DolphinOES.getModule parameter 'moduleClass' does not" + " implement the Module interface"); if (modules.get(moduleClass) == null) throw new DolphinOESException("DolphinOES.getModule parameter type " + moduleClass.getClass() + " can't be found in the list of modules"); return (T) modules.get(moduleClass); } /** Returns a boolean for whether or not the system contains a custom module with the passed parameter as a class. * * @param moduleClass * the Module implementation class to find in the list of custom modules * @return a boolean for whether or not the system contains desired module */ public static boolean containsModule(Class<? extends Module> moduleClass) { return modules.get(moduleClass) != null; } /** Internal method for passing objects from one scene to another, as well as disposing objects from the old scene * that are not required in the next scene. */ private void handleSceneTrasition() { GameScene currScene = DolphinOES.getScene(); // iterate over gamebatches to find all objects to remove for (int i = 0; i < currScene.gameBatches.size(); i++) { GameBatch gamebatch = currScene.gameBatches.get(i); // iterate over the objects in the gamebatch, finding if it has to // be removed // or not. for (int j = 0; j < gamebatch.objects.size(); j++) { GameObject obj = gamebatch.objects.get(j); if (currScene.getToKeepForNextScene().contains(obj) || obj.isPersistent()) { obj.scene = targetScene; obj.setGameBatch(obj.gameBatch.name); j--; // decreasing index for object in gamebatch list due to // calling setGameBatch // the object is removed from the previous gamebatch that it // was in. for (int k = 0; k < obj.behaviors.size(); k++) { obj.behaviors.get(k).scene = targetScene; } obj.handleSceneChange(); } else { obj.disposeInternal(); } } // end of iterating over gamebatch objects } for (int i = 0; i < currScene.gameBatches.size(); i++) { currScene.gameBatches.get(i).dispose(); } super.setScreen(targetScene); ((GameScene) targetScene).createScene(); return; } // endregion methods }