Test.java :  » Physics » dyn4j » org » dyn4j » game2d » testbed » Java Open Source

Java Open Source » Physics » dyn4j 
dyn4j » org » dyn4j » game2d » testbed » Test.java
/*
 * Copyright (c) 2011 William Bittle  http://www.dyn4j.org/
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, are permitted 
 * provided that the following conditions are met:
 * 
 *   * Redistributions of source code must retain the above copyright notice, this list of conditions 
 *     and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions 
 *     and the following disclaimer in the documentation and/or other materials provided with the 
 *     distribution.
 *   * Neither the name of dyn4j nor the names of its contributors may be used to endorse or 
 *     promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.dyn4j.game2d.testbed;

import java.awt.Dimension;
import java.util.List;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;

import org.dyn4j.game2d.collision.Bounds;
import org.dyn4j.game2d.collision.RectangularBounds;
import org.dyn4j.game2d.dynamics.Body;
import org.dyn4j.game2d.dynamics.Step;
import org.dyn4j.game2d.dynamics.World;
import org.dyn4j.game2d.dynamics.contact.ContactPoint;
import org.dyn4j.game2d.dynamics.contact.SolvedContactPoint;
import org.dyn4j.game2d.dynamics.joint.DistanceJoint;
import org.dyn4j.game2d.dynamics.joint.Joint;
import org.dyn4j.game2d.dynamics.joint.LineJoint;
import org.dyn4j.game2d.dynamics.joint.MouseJoint;
import org.dyn4j.game2d.dynamics.joint.PrismaticJoint;
import org.dyn4j.game2d.dynamics.joint.PulleyJoint;
import org.dyn4j.game2d.dynamics.joint.RevoluteJoint;
import org.dyn4j.game2d.dynamics.joint.RopeJoint;
import org.dyn4j.game2d.dynamics.joint.WeldJoint;
import org.dyn4j.game2d.geometry.Interval;
import org.dyn4j.game2d.geometry.Rectangle;
import org.dyn4j.game2d.geometry.Transform;
import org.dyn4j.game2d.geometry.Vector2;
import org.dyn4j.game2d.testbed.input.Keyboard;
import org.dyn4j.game2d.testbed.input.Mouse;

/**
 * Represents a test.
 * <p>
 * Using the {@link TestBed} class one can switch test without stopping
 * and starting the driver again.
 * @author William Bittle
 * @version 2.2.3
 * @since 1.0.0
 */
public abstract class Test implements Comparable<Test> {
  /** The test key */
  protected String key;
  
  /** A scaling factor from world space to device/screen space */
  protected double scale;
  
  /** The view port offset (x, y) */
  protected Vector2 offset;
  
  /** The physics world */
  protected World world;
  
  /** The current display area */
  protected Dimension size;

  /**
   * Returns the test name.
   * @return String the test name
   */
  public abstract String getName();
  
  /**
   * Returns the description of the test
   * @return String the description of the test
   */
  public abstract String getDescription();
  
  /* (non-Javadoc)
   * @see java.lang.Comparable#compareTo(java.lang.Object)
   */
  @Override
  public int compareTo(Test o) {
    // sort by name
    return this.getName().compareTo(o.getName());
  }
  
  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return this.getName();
  }
  
  /**
   * Initializes the {@link Test}.
   */
  public void initialize() {
    // initialize the scale
    this.scale = 0.0;
    // initialize the offset
    this.offset = new Vector2();
    // initialize the display size
    this.size = new Dimension();
  }
  
  /**
   * Sets up the test.
   * <p>
   * This method is called by {@link #initialize()} and {@link #reset()}.
   */
  protected abstract void setup();
  
  /**
   * Resets the test.
   */
  public void reset() {
    // clear all the bodies
    this.world.clear(false);
    // setup the test
    this.setup();
  }
  
  /**
   * Resets the camera to focus on the center of the world bounds
   * at the original zoom.
   */
  public abstract void home();
  
  /**
   * Releases the resources used by this test.
   */
  public void release() {
    this.world = null;
  }
  
  /**
   * Initializes any inputs specific to the test.
   * <p>
   * This method is called each time a test is selected and run
   * from the TestBed.
   * @param keyboard the keyboard to add inputs to listen for
   * @param mouse the mouse to add inputs to listen for
   */
  public void initializeInput(Keyboard keyboard, Mouse mouse) {}
  
  /**
   * Returns a string representation of any test specific controls.
   * @return String the test specific controls
   */
  public String[][] getControls() { return new String[][] {}; }

  /**
   * Returns true if this test has specific controls.
   * @return boolean
   */
  public boolean hasSpecificControls() {
    return this.getControls().length > 0;
  }
  
  /**
   * Performs any input polling required.
   * @param keyboard the keyboard input
   * @param mouse the mouse input
   */
  public void poll(Keyboard keyboard, Mouse mouse) {}
  
  /**
   * Performs the rendering for the {@link Test}.
   * @param gl the OpenGL graphics context
   * @param width the width of the rendering area
   * @param height the height of the rendering area
   */
  public void render(GL2 gl, double width, double height) {
    // immediately update the display size
    this.size.setSize(width, height);
    // get the draw flags singleton instance
    Draw draw = Draw.getInstance();
    
    // go from screen to world coordinates
    gl.glPushMatrix();
    gl.glScaled(this.scale, this.scale, this.scale);
    gl.glTranslated(this.offset.x, this.offset.y, 0.0);
    
    // draw any test specific stuff
    this.renderBefore(gl);
    
    // render all the bodies
    int size = this.world.getBodyCount();
    for (int i = 0; i < size; i++) {
      Entity obj = (Entity) this.world.getBody(i);
      obj.render(gl);
    }
    
    // see if the user wanted any contact information drawn
    if (draw.drawContacts() || draw.drawContactImpulses() 
     || draw.drawFrictionImpulses() || draw.drawContactPairs()) {
      // get the contact counter
      ContactCounter cc = (ContactCounter) this.world.getContactListener();
      // get the contacts from the counter
      List<ContactPoint> contacts = cc.getContacts();
      
      // loop over the contacts
      int cSize = contacts.size();
      for (int i = 0; i < cSize; i++) {
        // draw the contacts
        ContactPoint cp = contacts.get(i);
        // get the world space contact point
        Vector2 c = cp.getPoint();
        
        // draw the contact pairs
        if (draw.drawContactPairs()) {
          // set the color
          float[] color = draw.getContactPairsColor();
          gl.glColor4fv(color, 0);
          // get the world space points
          Vector2 p1 = cp.getBody1().getTransform().getTransformed(cp.getFixture1().getShape().getCenter());
          Vector2 p2 = cp.getBody2().getTransform().getTransformed(cp.getFixture2().getShape().getCenter());
          // draw line between the shapes
          gl.glBegin(GL.GL_LINES);
            gl.glVertex2d(p1.x, p1.y);
            gl.glVertex2d(p2.x, p2.y);
          gl.glEnd();
        }
        
        // draw the contact
        if (draw.drawContacts()) {
          // set the color
          float[] color = draw.getContactColor();
          gl.glColor4fv(color, 0);
          // draw the contact points
          GLHelper.fillRectangle(gl, c.x, c.y, 0.02, 0.02);
        }
        
        // check if the contact is a solved contact
        if (cp instanceof SolvedContactPoint) {
          // get the solved contact point to show the impulses applied
          SolvedContactPoint scp = (SolvedContactPoint) cp;
          Vector2 n = scp.getNormal();
          Vector2 t = n.cross(1.0);
          double j = scp.getNormalImpulse();
          double jt = scp.getTangentialImpulse();
          
          // draw the contact forces
          if (draw.drawContactImpulses()) {
            // set the color
            float[] color = draw.getContactImpulsesColor(); 
            gl.glColor4fv(color, 0);
            gl.glBegin(GL.GL_LINES);
              gl.glVertex2d(c.x, c.y);
              gl.glVertex2d(c.x + n.x * j, c.y + n.y * j);
            gl.glEnd();
          }
          
          // draw the friction forces
          if (draw.drawFrictionImpulses()) {
            // set the color
            float[] color = draw.getFrictionImpulsesColor();
            gl.glColor4fv(color, 0);
            gl.glBegin(GL.GL_LINES);
              gl.glVertex2d(c.x, c.y);
              gl.glVertex2d(c.x + t.x * jt, c.y + t.y * jt);
            gl.glEnd();
          }
        }
      }
    }
    
    // see if we should draw joints or not
    if (draw.drawJoints()) {
      size = this.world.getJointCount();
      // draw the joints
      for (int j = 0; j < size; j++) {
        Joint joint = this.world.getJoint(j);
        // check the joint type
        if (joint instanceof DistanceJoint) {
          this.render(gl, (DistanceJoint) joint);
        } else if (joint instanceof RevoluteJoint) {
          this.render(gl, (RevoluteJoint) joint);
        } else if (joint instanceof MouseJoint) {
          this.render(gl, (MouseJoint) joint);
        } else if (joint instanceof WeldJoint) {
          this.render(gl, (WeldJoint) joint);
        } else if (joint instanceof LineJoint) {
          this.render(gl, (LineJoint) joint);
        } else if (joint instanceof PrismaticJoint) {
          this.render(gl, (PrismaticJoint) joint);
        } else if (joint instanceof PulleyJoint) {
          this.render(gl, (PulleyJoint) joint);
        } else if (joint instanceof RopeJoint) {
          this.render(gl, (RopeJoint) joint);
        }
      }
    }
    
    // draw the bounds
    if (draw.drawBounds()) {
      // set the color
      float[] color = draw.getBoundsColor();
      gl.glColor4fv(color, 0);
      // get the bounds object
      Bounds bounds = this.world.getBounds();
      // check the type
      if (bounds instanceof RectangularBounds) {
        // cast to get access to the fields
        RectangularBounds rb = (RectangularBounds) bounds;
        
        // get the bounding rectangle
        Rectangle r = rb.getBounds();
        // get the transform
        Transform t = rb.getTransform();
        // get the rectangle's vertices
        Vector2[] vertices = r.getVertices();
        
        // save the current model-view matrix
        gl.glPushMatrix();
        // transform the model-view matrix
        gl.glTranslated(t.getTranslationX(), t.getTranslationY(), 0.0);
        gl.glRotated(Math.toDegrees(t.getRotation()), 0.0, 0.0, 1.0);
        
        // draw the box
        gl.glBegin(GL.GL_LINE_LOOP);
        // declare a vector for use
        Vector2 v;
        for (int i = 0; i < 4; i++) {
          // get the point
          v = vertices[i];
          // add the vertex
          gl.glVertex2d(v.x, v.y);
        }
        gl.glEnd();
        
        // throw away the current model-view matrix
        gl.glPopMatrix();
      }
    }
    
    // finally draw any test specific stuff
    this.renderAfter(gl);
    
    // restore the old model-view matrix
    gl.glPopMatrix();
  }
  
  /**
   * Renders a {@link DistanceJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link DistanceJoint} to render
   */
  private void render(GL2 gl, DistanceJoint joint) {
    // get the anchor points
    Vector2 v1 = joint.getAnchor1();
    Vector2 v2 = joint.getAnchor2();
    // set the color to be mostly transparent
    gl.glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
    // check for spring distance joint
    if (joint.isSpring()) {
      // draw a spring
      final double h = 0.03;
      final double w = 0.25;
      // compute the offset from the first joint point to the start
      // of the spring loops
      double offset = h * 0.5;
      // compute the number of spring loops
      // we have to use the joint's desired distance here so that the
      // number of loops in the spring doesnt change as the simulation
      // progresses
      int loops = (int) Math.ceil((joint.getDistance() - offset * 2.0) / h);
      // get the vector between the two points
      Vector2 n = v1.to(v2);
      // normalize it to get the current distance
      double x = n.normalize();
      // get the tangent to the normal
      Vector2 t = n.getRightHandOrthogonalVector();
      // compute the distance between each loop along the normal
      double d = (x - offset * 2.0) / (loops - 1);
      // draw a line straight down using the offset
      Vector2 d1 = n.product(offset).add(v1);
      gl.glBegin(GL.GL_LINES);
        gl.glVertex2d(v1.x, v1.y);
        gl.glVertex2d(d1.x, d1.y);
        // draw the first loop (half loop)
        Vector2 ct = t.product(w * 0.5);
        Vector2 cn = n.product(d * 0.5);
        Vector2 first = ct.sum(cn).add(d1);
        gl.glVertex2d(d1.x, d1.y);
        gl.glVertex2d(first.x, first.y);
        // draw the middle loops
        Vector2 prev = first;
        for (int i = 1; i < loops - 1; i++) {
          ct = t.product(w * 0.5 * ((i + 1) % 2 == 1 ? 1.0 : -1.0));
          cn = n.product(d * (i + 0.5) + offset);
          Vector2 p2 = ct.sum(cn).add(v1);
          // draw the line
          gl.glVertex2d(prev.x, prev.y);
          gl.glVertex2d(p2.x, p2.y);
          prev = p2;
        }
        // draw the final loop (half loop)
        Vector2 d2 = n.product(-offset).add(v2);
        gl.glVertex2d(prev.x, prev.y);
        gl.glVertex2d(d2.x, d2.y);
        // draw a line straight down using the offset
        gl.glVertex2d(d2.x, d2.y);
        gl.glVertex2d(v2.x, v2.y);
      gl.glEnd();
    } else {
      // emulate a line stroke of arbitrary width without cap/join
      
      // get the tangent vector
      Vector2 t = v1.to(v2);
      t.normalize();
      t.left();
      t.multiply(0.05);
      
      gl.glBegin(GL2.GL_QUADS);
        gl.glVertex2d(v1.x - t.x, v1.y - t.y);
        gl.glVertex2d(v1.x + t.x, v1.y + t.y);
        gl.glVertex2d(v2.x + t.x, v2.y + t.y);
        gl.glVertex2d(v2.x - t.x, v2.y - t.y);
      gl.glEnd();
    }
  }
  
  /**
   * Renders a {@link RevoluteJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link RevoluteJoint} to render
   */
  private void render(GL2 gl, RevoluteJoint joint) {
    Vector2 anchor = joint.getAnchor1();
    gl.glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
    GLHelper.fillCircle(gl, anchor.x, anchor.y, 0.025, 10);
    gl.glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
    GLHelper.renderCircle(gl, anchor.x, anchor.y, 0.025, 10);
  }
  
  /**
   * Renders a {@link MouseJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link MouseJoint} to render
   */
  private void render(GL2 gl, MouseJoint joint) {
    // set the color
    gl.glColor4f(0.0f, 0.0f, 0.0f, 0.8f);
    // draw the anchor point
    Vector2 anchor = joint.getAnchor2();
    GLHelper.fillRectangle(gl, anchor.x, anchor.y, 0.05, 0.05);
    // draw the target point
    Vector2 target = joint.getTarget();
    GLHelper.fillRectangle(gl, target.x, target.y, 0.05, 0.05);
    // draw a line connecting them
    // make the line color a function of stress (black to red)
    Step step = this.world.getStep();
    double invdt = step.getInverseDeltaTime();
    double maxForce = joint.getMaxForce();
    double force = joint.getReactionForce(invdt).getMagnitude();
    double red = force / maxForce;
    red *= 1.10;
    red = Interval.clamp(red, 0.0, 1.0);
    // set the color
    gl.glColor4f((float)red, 0.0f, 0.0f, 0.8f);
    gl.glBegin(GL.GL_LINES);
      gl.glVertex2d(anchor.x, anchor.y);
      gl.glVertex2d(target.x, target.y);
    gl.glEnd();
  }
  
  /**
   * Renders a {@link WeldJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link WeldJoint} to render
   */
  private void render(GL2 gl, WeldJoint joint) {
    // set the color
    gl.glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
    // draw an x at the anchor point
    Vector2 anchor = joint.getAnchor1();
    final double d = 0.025;
    gl.glBegin(GL.GL_LINES);
      gl.glVertex2d(anchor.x - d, anchor.y - d);
      gl.glVertex2d(anchor.x + d, anchor.y + d);
      gl.glVertex2d(anchor.x - d, anchor.y + d);
      gl.glVertex2d(anchor.x + d, anchor.y - d);
    gl.glEnd();
  }
  
  /**
   * Renders a {@link LineJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link LineJoint} to render
   */
  private void render(GL2 gl, LineJoint joint) {
    // draw an x at the anchor point
    Vector2 anchor = joint.getAnchor1();
    // draw a circle at the rotation anchor point
    gl.glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
    GLHelper.fillCircle(gl, anchor.x, anchor.y, 0.025, 10);
    gl.glColor4f(0.3f, 0.3f, 0.3f, 1.0f);
    GLHelper.renderCircle(gl, anchor.x, anchor.y, 0.025, 10);
    // draw a line to each center
    Body b1 = joint.getBody1();
    Body b2 = joint.getBody2();
    Vector2 c1 = b1.getWorldCenter();
    Vector2 c2 = b2.getWorldCenter();
    // draw a line from the anchor to each center
    gl.glBegin(GL.GL_LINES);
      gl.glVertex2d(anchor.x, anchor.y);
      gl.glVertex2d(c1.x, c1.y);
      gl.glVertex2d(anchor.x, anchor.y);
      gl.glVertex2d(c2.x, c2.y);
    gl.glEnd();
  }

  /**
   * Renders a {@link PrismaticJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link PrismaticJoint} to render
   */
  private void render(GL2 gl, PrismaticJoint joint) {
    // the length scale factor
    final double lf = 0.75;
    // the "piston" width
    final double w = 0.10;
    
    double hw = w * 0.5;
    Body b1 = joint.getBody1();
    Body b2 = joint.getBody2();
    Vector2 c1 = b1.getWorldCenter();
    Vector2 c2 = b2.getWorldCenter();
    Vector2 n = c1.to(c2);
    double l = n.normalize();
    
    // emulate a line stroke of arbitrary width without cap/join
    // get the tangent vector
    Vector2 t = n.product(w * 0.25).left();
    
    // set the color to be mostly transparent
    gl.glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
    // draw the inner piston
    gl.glBegin(GL2.GL_QUADS);
      gl.glVertex2d(c1.x - t.x, c1.y - t.y);
      gl.glVertex2d(c1.x + t.x, c1.y + t.y);
      gl.glVertex2d(c2.x + t.x, c2.y + t.y);
      gl.glVertex2d(c2.x - t.x, c2.y - t.y);
    gl.glEnd();
    
    // draw a line from body1's center to the anchor
    gl.glBegin(GL.GL_LINES);
      // draw two lines slightly offset from the center line
      t = n.cross(1.0);
      gl.glVertex2d(c2.x + t.x * hw, c2.y + t.y * hw);
      gl.glVertex2d(c2.x - n.x * l * lf + t.x * hw, c2.y - n.y * l * lf + t.y * hw);
      gl.glVertex2d(c2.x - t.x * hw, c2.y - t.y * hw);
      gl.glVertex2d(c2.x - n.x * l * lf - t.x * hw, c2.y - n.y * l * lf - t.y * hw);
    gl.glEnd();
  }
  
  /**
   * Renders a {@link PulleyJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link PulleyJoint} to render
   * @since 2.2.0
   */
  private void render(GL2 gl, PulleyJoint joint) {
    // set the color to be mostly transparent
    gl.glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
    
    Vector2 p1 = joint.getAnchor1();
    Vector2 p2 = joint.getPulleyAnchor1();
    Vector2 p3 = joint.getPulleyAnchor2();
    Vector2 p4 = joint.getAnchor2();
    
    gl.glBegin(GL.GL_LINE_STRIP);
      gl.glVertex2d(p1.x, p1.y);
      gl.glVertex2d(p2.x, p2.y);
      gl.glVertex2d(p3.x, p3.y);
      gl.glVertex2d(p4.x, p4.y);
    gl.glEnd();
  }
  
  /**
   * Renders a {@link RopeJoint} to the given graphics object.
   * @param gl the OpenGL graphics context
   * @param joint the {@link RopeJoint} to render
   */
  private void render(GL2 gl, RopeJoint joint) {
    Vector2 v1 = joint.getAnchor1();
    Vector2 v2 = joint.getAnchor2();
    // set the color to be mostly transparent
    gl.glColor4f(0.0f, 0.0f, 0.0f, 0.3f);
    
    // emulate a line stroke of arbitrary width without cap/join
    // get the tangent vector
    Vector2 t = v1.to(v2);
    t.normalize();
    t.left();
    t.multiply(0.05);
    
    // save the original stroke
    gl.glBegin(GL2.GL_QUADS);
      gl.glVertex2d(v1.x - t.x, v1.y - t.y);
      gl.glVertex2d(v1.x + t.x, v1.y + t.y);
      gl.glVertex2d(v2.x + t.x, v2.y + t.y);
      gl.glVertex2d(v2.x - t.x, v2.y - t.y);
    gl.glEnd();
  }
  
  /**
   * Performs rendering for a subclass of {@link Test} before the world,
   * contacts, and bounds are drawn.
   * <p>
   * Any graphics rendered in this method does not need to apply
   * a transformation for screen to world coordinates.
   * @param gl the OpenGL graphics context
   */
  protected void renderBefore(GL2 gl) {};
  
  /**
   * Performs rendering for a subclass of {@link Test} after the world,
   * contacts, and bounds are drawn.
   * <p>
   * Any graphics rendered in this method does not need to apply
   * a transformation for screen to world coordinates.
   * @param gl the OpenGL graphics context
   */
  protected void renderAfter(GL2 gl) {};
  
  /**
   * Updates the {@link Test} given the delta time
   * in seconds.
   * <p>
   * This method assumes the step mode is continuous and the TestBed is not paused.
   * @param dt the delta time in seconds
   */
  public void update(double dt) {}
  
  /**
   * Updates the {@link Test} given the number of steps to perform.
   * @param steps the number of steps to perform
   */
  public void update(int steps) {}
  
  /**
   * Converts the screen coordinate to world space.
   * @param x screen x
   * @param y screen y
   * @return {@link Vector2}
   */
  public Vector2 screenToWorld(double x, double y) {
    Vector2 v = new Vector2();
    v.x = (x - this.size.width * 0.5) / this.scale - this.offset.x;
    v.y = -((y - this.size.height * 0.5) / this.scale + this.offset.y);
    return v;
  }
  
  /**
   * Zooms the camera in by the given zoom factor.
   * @param zoom the zoom factor
   */
  public void zoom(double zoom) {
    this.scale *= zoom;
  }
  
  /**
   * Translates the camera by the given values.
   * @param dx the delta x translation
   * @param dy the delta y translation
   */
  public void translate(double dx, double dy) {
    this.offset.add(dx, dy);
  }

  /**
   * Returns the current zoom amount.
   * @return double the current zoom amount
   */
  public double getZoom() {
    return this.scale;
  }
  
  /**
   * Returns the world object.
   * @return {@link World} the world object
   */
  public World getWorld() {
    return this.world;
  }
  
  /**
   * Returns the current display size.
   * @return Dimension
   */
  public Dimension getSize() {
    return this.size;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.