Android Open Source - DolphinOES Game Batch






From Project

Back to project page DolphinOES.

License

The source code is released under:

Apache License

If you think the Android project DolphinOES listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/******************************************************************************* Copyright 2014 See AUTHORS file.
 * //from w  ww  .ja  v  a  2s. c o m
 * 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 java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.sidereal.dolphinoes.architecture.core.GameData.Settings;
import com.sidereal.dolphinoes.behaviors.input.Clickable;
import com.sidereal.dolphinoes.behaviors.triggers.Hoverable;
import com.sidereal.dolphinoes.util.BooleanWrapper;

/** An object used for handling multiple {@link GameObject} instances at the same time, rendering them using
 * {@link #camera} and {@link #spriteBatch}, with the possibility of adding a shader and sorting the objects, as well as
 * access to the mouse position translated to {@link #camera}'s coordinate system.
 * <p>
 * GameBatch objects are added in {@link GameScene#addGameBatch(GameBatch)} , and are iterated over in
 * {@link GameScene#render(float)}.
 * 
 * @author Claudiu */
public class GameBatch
{

  // region fields

  /** Area that the camera sees and outside of which images are not rendered. */
  public Rectangle renderingArea;

  public enum ShaderType
  {
    Initialisation, Update, Resize
  };

  /** Sprite batch on which to render all objects that are using the {@link GameBatch} that the {@link SpriteBatch} is
   * tied to.
   * <p>
   * The shader found in {@link #shaderProgram} will be applied to this rendering batch. */
  public SpriteBatch spriteBatch;

  /** Shape renderer focused on the {@link GameBatch}'s camera. */
  public ShapeRenderer shapeRenderer;

  /** Camera used for rendering objects tied to {@link #spriteBatch}.
   * <p>
   * The camera's position can be made to target a certain {@link GameObject} by assigning {@link #target}. */
  public OrthographicCamera camera;

  /** Variable used for sorting the {@link GameBatch} rendering order in the scene. Is used in
   * {@link GameScene#gameBatchComparator}. */
  public int priorityLevel;

  /** Name of the gamebatch.
   * <p>
   * Is set in the constructor and used in {@link GameObject#setGameBatch}. */
  public String name;

  /** List of {@link GameObject} entries tied to the {@link GameBatch}. */
  public List<GameObject> objects;

  /** Whether to translate the mouse position to the {@link #camera}'s projection matrix. This will make using certain
   * IO-related behaviors such as {@link Clickable} or {@link Hoverable} work in {@link GameObject} objects tied to
   * the {@link GameBatch} */
  public boolean translateMousePosition;

  /** If not null, the {@link GameBatch} will be using the referencing batch's {@link #camera}, {@link #mousePosition}.
   * Will be set in {@link #GameBatch(GameScene, String, GameBatch)}. */
  public GameBatch referencingBatch;

  /** Whether to sort the GameObjects in {@link #objects} before updating them or not. Set in {@link #setSort(boolean, Comparator)} */
  private boolean sort;

  /** The sorting algorithm to run if {@link #sort} is true on {@link #objects} . Set in {@link #setSort(boolean, Comparator)}
   * <p>
   * By default, will first render objects at the top of the screen, with a lower level. */
  private Comparator<GameObject> objectsComparator;

  /** Thread that updates the batch, calling {@link #doUpdate()} every frame. Is called in {@link #run()}. */
  private Thread updateThread;

  /** The {@link GameScene} that the batch is found in. Set up in {@link #initialiseBatch(GameScene, String)}. */
  private GameScene scene;

  /** Object used for translating the mouse position to the camera's coordinate system. After translating it, will be
   * used to set variables in {@link #mousePosition}. */
  private Vector3 tempMousePosition;

  /** The position of the mouse, translated to the camera's coordinate system. */
  public Vector2 mousePosition;

  /** Shader to run every frame on {@link #spriteBatch}. Is set in
   * {@link #setShader(ShaderProgram, AbstractEvent, ShaderType)}. */
  private ShaderProgram shaderProgram;

  /** Event with the purpose of passing uniform values to the shader. Will be called based on {@link #shaderType}. */
  private AbstractEvent shaderUniformValuesEvent;

  /** The type of shader. Affects when {@link #shaderUniformValuesEvent} runs.
   * <p>
   * If {@link #shaderType} is set to {@link ShaderType#Initialisation}, the event is running when set in
   * {@link #setShader(ShaderProgram, AbstractEvent, ShaderType)} only.
   * <p>
   * If {@link #shaderType} is set to {@link ShaderType#Resize}, the event is running whenever {@link #resize()} is
   * called.
   * <p>
   * If {@link #shaderType} is set to {@link ShaderType#Update}, the event runs every frame in {@link #doUpdate()}. */
  private ShaderType shaderType;

  // endregion

  // region constructors

  /** Constructor for a GameBatch that calls {@link #initialiseBatch(GameScene, String)}, as well as set up the camera
   * and the mouse position as the batch does not reference anything.
   * 
   * @param scene
   *            The scene in which to add the game batch.
   * @param name
   *            name of the gameBatch, used for retrieval of Batch using {@link GameScene#getGameBatch(String)}. */
  public GameBatch(GameScene scene, String tag)
  {

    initialiseBatch(scene, tag);

    this.tempMousePosition = new Vector3();
    this.mousePosition = new Vector2();

    this.camera = new OrthographicCamera();
    camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

    this.translateMousePosition = false;

    this.renderingArea = new Rectangle();
  }

  /** Constructor for a GameBatch that uses resources from the <code>
   * referencingBatch</code> parameter to keep consistency.
   * <p>
   * Throws a {@link GdxRuntimeException} if passed {@link GameBatch} is null.
   * 
   * @param scene
   *            The scene in which to add the game batch.
   * @param name
   *            name of the gameBatch, used for retrieval of Batch using {@link GameScene#getGameBatch(String)}.
   * @param referencingBatch */
  public GameBatch(GameScene scene, String tag, GameBatch referencingBatch)
  {

    initialiseBatch(scene, tag);

    if (referencingBatch == null)
      throw new GdxRuntimeException("Referencing batch in constructor for the " + tag
        + " batch was null. Use the constructor without a batch as a parameter if no referencing batch is "
        + "needed");

    this.referencingBatch = referencingBatch;
    this.camera = referencingBatch.camera;
    this.mousePosition = referencingBatch.mousePosition;
    this.renderingArea = referencingBatch.renderingArea;
  }

  /** Common initialisation code between the two constructors of {@link GameBatch}, initialising variables in the
   * scene.
   * <p>
   * If the scene or the batch name are null, a {@link GdxRuntimeException} is thrown.
   * 
   * @param scene
   *            The scene in which to add the game batch.
   * @param name
   *            name of the gameBatch, used for retrieval of Batch using {@link GameScene#getGameBatch(String)}. */
  private final void initialiseBatch(GameScene scene, String name)
  {

    if (scene == null)
      throw new GdxRuntimeException("GameScene parameter passed to GameBatch is null");
    if (name == null)
      throw new GdxRuntimeException("String parameter passed to GameBatch is null");

    this.scene = scene;
    this.name = name;

    this.shapeRenderer = new ShapeRenderer();
    this.shapeRenderer.setAutoShapeType(true);
    this.spriteBatch = new SpriteBatch();
    this.objects = new ArrayList<GameObject>();
    this.priorityLevel = 0;
    this.sort = true;

    this.objectsComparator = new Comparator<GameObject>()
    {
      @Override
      public int compare(GameObject o1, GameObject o2)
      {

        if (o1.pos.getZ() != o2.pos.getZ())
        {
          return (int) (o1.pos.getZ() - o2.pos.getZ());
        } else
        {
          return (int) o2.pos.getY() - (int) o1.pos.getY();
        }

      }
    };

    updateThread = new Thread(new Runnable()
    {
      @Override
      public void run()
      {

        doUpdate();
      }
    });
  }

  // endregion

  // region methods

  /** Updates the area within which objects will be drawn. */
  private final void updateRenderingArea()
  {

    renderingArea.set(camera.position.x - ((camera.viewportWidth / 2f) * camera.zoom), camera.position.y
      - ((camera.viewportHeight / 2f) * camera.zoom), camera.viewportWidth * camera.zoom, camera.viewportHeight
      * camera.zoom);
  }

  /** Runs every frame, updating all game objects and the mouse position to the camera's location. Gets called from
   * {@link GameScene#render(float)}
   * 
   * @param info
   *            the game information */
  final void run()
  {

    if (translateMousePosition)
    {
      tempMousePosition.set(Gdx.input.getX(), Gdx.input.getY(), 0);

      // translate the pixel to world
      camera.unproject(tempMousePosition);

      // updating mouse position.
      mousePosition.x = tempMousePosition.x;
      mousePosition.y = tempMousePosition.y;
    }

    if (((BooleanWrapper) DolphinOES.data.getSettings(Settings.MULTI_THREADED)).get())
      updateThread.run();
    else
      doUpdate();
  }

  /** Handles setting the shader for the {@link #spriteBatch}.
   * 
   * @param program
   *            The shader to run every frame
   * @param uniformValuesEvent
   *            the event for setting uniforms.
   * @param type
   *            The type of shader, which affects when <code>uniformValuesEvent</code> gets called. */
  public final void setShader(ShaderProgram program, AbstractEvent uniformValuesEvent, ShaderType type)
  {

    // not using shaders in the settings.
    if (!((BooleanWrapper) DolphinOES.data.getSettings(Settings.USE_SHADERS)).get())
      return;

    // don't handle shader if it GLSL failed compilation
    if (!program.isCompiled())
    {
      DolphinOES.debug.log(program.getLog());
      return;
    }

    // handling null variables
    if (program == null || type == null)
    {
      this.shaderProgram = null;
      this.shaderUniformValuesEvent = null;
      this.spriteBatch.setShader(null);

      return;
    }
    ShaderProgram.pedantic = false;
    this.shaderProgram = program;
    this.shaderType = type;

    this.shaderUniformValuesEvent = uniformValuesEvent;
    spriteBatch.setShader(this.shaderProgram);

    DolphinOES.debug.log("Shader compiled successfully? " + this.shaderProgram.isCompiled());

    // run initialisation or resize event
    if (this.shaderUniformValuesEvent != null
      && (shaderType.equals(ShaderType.Initialisation) || shaderType.equals(ShaderType.Resize))
      && this.shaderProgram.isCompiled())
    {
      shaderProgram.begin();
      this.shaderUniformValuesEvent.run(shaderProgram);
      shaderProgram.end();
    }

  }

  /** Resizes the GameBatch, updating the camera's size, as well as the objects that depend on it, such as
   * {@link #shaderProgram}, {@link #spriteBatch} or {@link #shapeRenderer}.
   * <p>
   * All of the objects tied to the GameBatch ( the ones in {@link #objects}) are being resized by calling
   * {@link GameObject#onResize(float, float, float, float)} on all of them. */
  public final void resize()
  {

    float oldWidth = camera.viewportWidth;
    float oldHeight = camera.viewportHeight;

    // set up new width
    camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

    // if camera has a target, set pos back to target

    camera.update();
    spriteBatch.setProjectionMatrix(camera.combined);

    shapeRenderer.setProjectionMatrix(camera.combined);

    // run resize event
    if (this.shaderUniformValuesEvent != null && this.shaderType.equals(ShaderType.Resize)
      && this.shaderProgram.isCompiled())
    {
      shaderProgram.begin();
      this.shaderUniformValuesEvent.run(shaderProgram);
      shaderProgram.end();
    }

    for (int i = 0; i < objects.size(); i++)
    {
      if (objects.get(i).isInScene())
        objects.get(i).onResize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), oldWidth, oldHeight);
    }
  }

  /** Method that updates all objects in {@link #objects}. */
  private final void doUpdate()
  {

    if (objects == null || scene == null)
      return;

    // batch's scene is not the same as the current scene.
    if (DolphinOES.getScene() != null && !this.scene.equals(DolphinOES.getScene()))
    {
      scene = null;
      return;
    }
    if (objects.size() == 0)
      return;

    if (sort)
    {
      try
      {
        Collections.sort(objects, objectsComparator);
      } catch (Exception e)
      {
        DolphinOES.debug.log("Caught exception " + e.getMessage() + e.toString());
        e.printStackTrace();
      }
    }

    updateRenderingArea();

    if (shaderUniformValuesEvent != null && shaderType.equals(ShaderType.Update) && shaderProgram.isCompiled())
    {
      shaderProgram.begin();
      shaderUniformValuesEvent.run(shaderProgram);
      shaderProgram.end();
    }

    spriteBatch.setProjectionMatrix(camera.combined);
    shapeRenderer.setProjectionMatrix(camera.combined);
    spriteBatch.begin();
    shapeRenderer.begin();

    // update objects
    if (objects != null)
    {
      for (int i = 0; i < objects.size(); i++)
      {

        objects.get(i).updateInternal();
        if (objects == null)
          return;
      }
      if (DolphinOES.debug.isEnabled())
      {
        for (int i = 0; i < objects.size(); i++)
        {
          objects.get(i).updateDebug();
        }
      }

    }
    spriteBatch.end();
    shapeRenderer.end();

  }

  public void dispose()
  {

    spriteBatch.dispose();
  }

  /** Sets whether or not sorting should be enabled, and maybe the comparator used in sorting
   * <p>
   * If the <code>enabled</code> parameter is set to true, the <code>comparator</code> can be null only
   * if the value of the internal comparator has been set before, either in the {@link GameBatch} comparator or using
   * {@link #setSort(boolean, Comparator)}. Passing a null <code>comparator</code> parameter will imply that you don't want the
   * comparator to change
   * 
   * @param enabled Whether to enable sorting or not
   * @param comparator The Comparator to use, use null if already defined and you don't want to change it.
   */
  public void setSort(boolean enabled, Comparator<GameObject> comparator)
  {

    if (!enabled)
    {
      sort = false;
      if(comparator != null)
        objectsComparator = comparator;
      return;
    }
    
    if(comparator == null && objectsComparator == null)
      throw new NullPointerException("Gamebatch.setsort parameter comparator of type Comparator<GameObject> is null, and you are trying to enable"
        + "the sorting without a predefined comparator");
    
    sort = enabled;
    this.objectsComparator = comparator; 
  }
  
  // endregion
}




Java Source Code List

com.sidereal.dolphinoes.architecture.AbstractEvent.java
com.sidereal.dolphinoes.architecture.DebugHandler.java
com.sidereal.dolphinoes.architecture.DolphinOES.java
com.sidereal.dolphinoes.architecture.GameBatch.java
com.sidereal.dolphinoes.architecture.GameBehavior.java
com.sidereal.dolphinoes.architecture.GameObject.java
com.sidereal.dolphinoes.architecture.GameScene.java
com.sidereal.dolphinoes.architecture.Module.java
com.sidereal.dolphinoes.architecture.core.Assets.java
com.sidereal.dolphinoes.architecture.core.Configurable.java
com.sidereal.dolphinoes.architecture.core.Debug.java
com.sidereal.dolphinoes.architecture.core.DolphinOESConfiguration.java
com.sidereal.dolphinoes.architecture.core.GameData.java
com.sidereal.dolphinoes.architecture.core.MouseMovedEvent.java
com.sidereal.dolphinoes.architecture.core.Time.java
com.sidereal.dolphinoes.architecture.core.assetload.AssetLoadHandler.java
com.sidereal.dolphinoes.architecture.core.assetload.AssetLoader.java
com.sidereal.dolphinoes.architecture.core.assetload.ClassFileHandleResolver.java
com.sidereal.dolphinoes.architecture.core.assetload.LoadingPercentage.java
com.sidereal.dolphinoes.architecture.core.input.ActionData.java
com.sidereal.dolphinoes.architecture.core.input.ActionEventWrapper.java
com.sidereal.dolphinoes.architecture.core.input.ActionEvent.java
com.sidereal.dolphinoes.architecture.core.input.Input.java
com.sidereal.dolphinoes.architecture.core.input.KeyTypedEvent.java
com.sidereal.dolphinoes.architecture.core.input.ScrollEvent.java
com.sidereal.dolphinoes.architecture.core.input.TouchData.java
com.sidereal.dolphinoes.architecture.core.input.TouchEventWrapper.java
com.sidereal.dolphinoes.architecture.core.input.TouchEvent.java
com.sidereal.dolphinoes.architecture.pos.Position.java
com.sidereal.dolphinoes.architecture.pos.Positions.java
com.sidereal.dolphinoes.backend.ConcreteGametester.java
com.sidereal.dolphinoes.backend.GameTester.java
com.sidereal.dolphinoes.backend.SceneGameTester.java
com.sidereal.dolphinoes.behaviors.audio.AudioListener.java
com.sidereal.dolphinoes.behaviors.audio.AudioPlayer.java
com.sidereal.dolphinoes.behaviors.events.EventTimer.java
com.sidereal.dolphinoes.behaviors.events.RecurringEvent.java
com.sidereal.dolphinoes.behaviors.input.Clickable.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleEmitter.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleHandler.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleSpriteLayout.java
com.sidereal.dolphinoes.behaviors.particlesystem.ParticleSpriteObject.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingHandler.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingMap.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingNode.java
com.sidereal.dolphinoes.behaviors.pathfinding.PathfindingRoute.java
com.sidereal.dolphinoes.behaviors.renderer.DrawerBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.Drawer.java
com.sidereal.dolphinoes.behaviors.renderer.Renderer.java
com.sidereal.dolphinoes.behaviors.renderer.ninepatch.NinepatchBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.ninepatch.NinepatchDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.scml.SCMLBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.scml.SCMLDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.sprite.SpriteBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.sprite.SpriteDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.spritesequence.SpriteSequenceBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.spritesequence.SpriteSequenceDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.spritesequence.SpriteSequencePreference.java
com.sidereal.dolphinoes.behaviors.renderer.texture.TextureBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.texture.TextureDrawer.java
com.sidereal.dolphinoes.behaviors.renderer.tilemap.TileMapBuilder.java
com.sidereal.dolphinoes.behaviors.renderer.tilemap.TileMapDrawer.java
com.sidereal.dolphinoes.behaviors.triggers.Activatable.java
com.sidereal.dolphinoes.behaviors.triggers.Collider.java
com.sidereal.dolphinoes.behaviors.triggers.Hoverable.java
com.sidereal.dolphinoes.ui.MessageBubble.java
com.sidereal.dolphinoes.ui.TextBuilder.java
com.sidereal.dolphinoes.util.BooleanWrapper.java
com.sidereal.dolphinoes.util.DolphinOESException.java
com.sidereal.dolphinoes.util.FloatWrapper.java
com.sidereal.dolphinoes.util.IntWrapper.java
com.sidereal.dolphinoes.util.Utility.java