package org.erikaredmark.monkeyshines; import org.erikaredmark.monkeyshines.bounds.IPoint2D; /** * * Represents a single point on the 2D world. * <p/> * To prevent heavy amounts of object insantatiation, instances of this class are mutable. Every unique object in the world * must have its own reference to a unique Point2D copy. * <p/> * Point data is internally stored as a double-precision floating point to allow fluid physics calculations. * <p/> * Instances of this class inherit equals and hashcode from object due to floating point precision and lack of need. * * @author Erika Redmark * */ public class Point2D implements IPoint2D { private double x; private double y; private Point2D(final double x, final double y) { this.x = x; this.y = y; } public double precisionX() { return x; } public double precisionY() { return y; } public int x() { return (int) x; } public int y() { return (int) y; } public void setX(final double x) { this.x = x; } public void setY(final double y) { this.y = y; } /** Translates point one full unit to the left, regardless of precision. */ public void left() { this.x -= 1; } /** Translates point one full unit to the right, regardless of precision. */ public void right() { this.x += 1; } /** Translates point one full unit down, regardless of precision. */ public void down() { this.y -= 1; } /** Translates point one full unit up, regardless of precision. */ public void up() { this.y += 1; } /** * Translates the given point along the horizontal. * * @param amt positive values go right, negative values go left */ public void translateX(int amt) { this.x += amt; } /** * Translates the given point along the verticle. * * @param amt positive values go down, negative values go up. */ public void translateY(int amt) { this.y += amt; } /** * Translates with extra precision; the translation may not affect the actual location returned by {@link #x() } * * @param amt positive values go right, negative values go left */ public void translateXFine(double amt) { this.x -= amt; } /** * Translates with extra precision; the translation may not affect the actual location returned by {@link #y() } * * @param amt positive values go down, negative values go up */ public void translateYFine(double amt) { this.y -= amt; } /** Reverses the sign of the x-cordinate, effectively flipping it to the other side of however the y-axis is defined*/ public void reverseX() {this.x = -x; } /** Reverses the sign of the y-cordinate, effectively flipping it to the other side of however the x-axis is defined*/ public void reverseY() {this.y = -y; } /** * * Returns a new copy of a Point2D with the same logical position as the passed one. The returned object is completely * distinct from the original. * * @param other * the original point 2d to copy from * * @return * a unqiue copy * */ public static Point2D of(Point2D other) { return new Point2D(other.precisionX(), other.precisionY() ); } public static Point2D of(final int x, final int y) { return new Point2D((double)x, (double)y); } public static Point2D of(final double x, final double y) { return new Point2D(x, y); } /** * * Copies the values of a valid point object to create a new instance of this object (a mutable point). The resulting * object can not be used to modify the immutable object. * <p/> * Due to the immutable point storing values as integers, a point transformed into an immutable point, and then back * again, will lose precision. * * @param point * the other point, possibly an immutable point * * @return * a new, unique instance of this object initialised to the values in the corresponding other point. * */ public static Point2D from(final IPoint2D point) { return of(point.x(), point.y() ); } /** * * Adds to this point another point, where the second point's x and y values represent a velocity. This point * instance is mutated by this function. The second instance is not mutated. * <p/> * The x component represented by velocity is added to the point, and the y component is subtracted from this point. * This is because positive velocities intuitively should go up, and negative ones should go down. * * @param velocity * the 'velocity' to add to this point. * */ public void applyVelocity(Point2D velocity) { this.translateXFine(velocity.precisionX() ); //using minus, because otherwise positive numbers go down and that makes no sense. this.translateYFine(-velocity.precisionY() ); } @Override public String toString() { return x + ", " + y; } }