Package hermes

Source Code of hermes.HCamera

package hermes;

import hermes.hshape.HRectangle;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
import processing.core.*;

/**
* <code>HCamera</code> determines which <code>Being</code>s get drawn. You can think of it as a window into the <code>World</code>,
* and any <code>Being</code>s that are inside of its bounding box will have their <code>draw()</code> methods called automatically.
*
* <p>
* The <code>World</code> class needs to be passed an <code>HCamera</code> when constructed. 
* Any <code>Being</code>(s) registered with that <code>World</code> will automatically get drawn if they are
* spatially within that <code>HCamera</code>'s bounding box.
*
* <p>
* An <code>HCamera</code>'s bounding box is determined at construction - by default, it uses the pixel width and height of the PApplet that was passed to <code>Hermes</code>.
* Alternatively, <code>HCamera</code> has an alternate constructor that allows you to set your own custom screen to world coordinate ratio.
* If you wish to use a coordinate system other than pixels coordinates, simply set the width and height of the camera to the area of the world you want the camera to see at a time.
*
* <p>
* <code>HCamera</code> extends <code>Being</code>, which allows it to move around and interact with other entities in the game.
* This opens interesting possibilities, such as having a camera follow a character, having the camera move based on game events or other logic, etc.
*
*/
public class HCamera extends Being {

  //width & height of user's world coordinates
  private float _worldCoordinateWidth;
  private float _worldCoordinateHeight;
 
  @SuppressWarnings("unused")
  private float _zoomFactor;

  //contains all the Beings colliding with the Camera in a given timestep
  //repopulated each time step
  List<Being> _beingsPending;
  List<Being> _beingsDrawn;
  Boolean _switchToBeingsPending;

  //Camera's default constructor which uses
 
/**
  Default HCamera constructor.
  Passing no arguments gives HCamera a 1-to-1 world pixel ratio (the world coordinate units are the same size as the screen's pixel coordinates)
  
*/
  public HCamera() {
    this(0,0,Hermes.getPApplet().width,Hermes.getPApplet().height);
  }


  /**
   * Constructs an HCamera with a custom coordinate unit size.
   * @param x          the starting x coordinate of the camera
   * @param y          the starting y coordinate of the camera
   * @param cameraWidth    the width of the camera view, in world coordinate units. This determines how far the camera can see in the x direction.
   * @param cameraHeight    the height of the camera view. This determines how far the camera can see in the y direction.
   */
  public HCamera(float x, float y, float cameraWidth, float cameraHeight) {
    super(new HRectangle(new PVector(x,y), new PVector(0,0), new PVector(cameraWidth, cameraHeight)),
        HermesMath.zeroVector());
    _worldCoordinateWidth = cameraWidth;
    _worldCoordinateHeight = cameraHeight;
   
    _zoomFactor = 1.0f;

    _beingsPending = new LinkedList<Being>();
    _beingsDrawn = new LinkedList<Being>();
   
    _switchToBeingsPending = new Boolean(false);
  }

  public float getWorldCoordinateWidth() {
    return _worldCoordinateWidth;
  }

  public void setWorldCoordinateWidth(float worldCoordinateWidth) {
    _worldCoordinateWidth = worldCoordinateWidth;
  }

  public float getWorldCoordinateHeight() {
    return _worldCoordinateHeight;
  }

  public void setWorldCoordinateHeight(float worldCoordinateHeight) {
    _worldCoordinateHeight = worldCoordinateHeight;
  }
 
  //pixels/(worldmetric)
  public float getScreenToWorldRatioX() {
    return Hermes.getPApplet().width/_worldCoordinateWidth;
  }
 
  //pixels/(worldmetric)
  public float getScreenToWorldRatioY() {
    return Hermes.getPApplet().height/_worldCoordinateHeight;
  }
 
  /**
   * Resets internal state parameters, effectively clearing the cache of
   * collided Beings from the last time step
   */
  public void collisionsReset() {
    synchronized(_switchToBeingsPending) {
      _switchToBeingsPending = false;
    }
   
    synchronized(_beingsPending) {
      _beingsPending = Collections.synchronizedList(new LinkedList<Being>());
    }
  }
 
  /**
   * This method is a callback, letting the Camera know that the _beingsPending list
   * has been completed for this timestep, and that it can switch to make it the actively
   * drawn list of Beings on the next call to draw()
   */
  public void collisionsComplete() {
    synchronized(_switchToBeingsPending) {
      _switchToBeingsPending = true;
    }
  }

  /**
   * adds a Being to _beings. Every item in the list gets drawn.
   * @param being
   */
  public void addBeing(Being being) {
    synchronized(_beingsPending) {
      _beingsPending.add(being);
    }
  }
 
  //TODO: make sure these work and comment properly
 
  /**
   *
   * @param zoomFactor
   * @param worldZoomCenterX
   * @param worldZoomCenterY
   */
  public void zoomWithWorldCoordinates(float zoomFactor, float worldZoomCenterX, float worldZoomCenterY) {
    //change the World width and height of the Camera
    _worldCoordinateWidth = _worldCoordinateWidth/zoomFactor;
    _worldCoordinateHeight = _worldCoordinateHeight/zoomFactor;
   
    //find the new top-left point in World coordinates
    getPosition().x = worldZoomCenterX - _worldCoordinateWidth/2;
    getPosition().y = worldZoomCenterY - _worldCoordinateHeight/2;
   
    //set the _zoomFactor
    _zoomFactor = zoomFactor;
  }
 
  public void zoomWithScreenCoordinates(float zoomFactor, float screenZoomCenterX, float screenZoomCenterY) {
    //translate from screen coordinates to world coordinates
    //units of calculation: worldmetric = pixels * (worldmetric/pixel)
    float worldX = screenZoomCenterX * (_worldCoordinateWidth/Hermes.getPApplet().width);
    float worldY = screenZoomCenterY * (_worldCoordinateHeight/Hermes.getPApplet().height);
   
    //call other method that works with world coordinates
    this.zoomWithWorldCoordinates(zoomFactor, worldX, worldY);   
  }
 
 
 
 

  /**
   * This method gets called by Processing's draw thread. It handles drawing all of the Beings that
   * are colliding with the camera. It translates to each Being's position on screen and draws the
   * Being there.
   */
  @Override
  public void draw() {
    PApplet pApplet = Hermes.getPApplet();
   
    synchronized(_switchToBeingsPending) {
      if(_switchToBeingsPending) {
        synchronized(_beingsPending) {
          _beingsDrawn = _beingsPending;
        }
      }
    }
   
    pApplet.translate(-getPosition().x / (_worldCoordinateWidth/pApplet.width),
        -getPosition().y / (_worldCoordinateHeight/pApplet.height));
   
    // for each being in _beings do matrix manipulations and call the draw method of each being
    for(Iterator<Being> iter = _beingsDrawn.iterator(); iter.hasNext(); ) {


      Being being = iter.next();

      synchronized(being) {

        pApplet.pushMatrix();
       
        //translate to being's coordinates on the screen
        //units of calculation: pixels = (worldmetric)/(worldmetric/pixel)
        float beingXCoordinate = being.getPosition().x/(_worldCoordinateWidth/pApplet.width);
        float beingYCoordinate = being.getPosition().y/(_worldCoordinateHeight/pApplet.height);
        pApplet.translate(beingXCoordinate, beingYCoordinate);
        //pApplet.scale(_zoomFactor);
        //save this state
        pApplet.pushMatrix();
        //Push style
        pApplet.pushStyle();

        //draw being (will draw itself as though it were at (0,0))
        being.draw();

        //pop the two states and styles
        pApplet.popStyle();
        pApplet.popMatrix();
        pApplet.popMatrix();
     
      }
    }

  }

}
TOP

Related Classes of hermes.HCamera

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.