/Users/petercappello/NetBeansProjects/56-2014/56-2014-4-AdaptableZapem/src/Critter.java
import java.awt.Color;
import java.awt.Graphics;
import static java.lang.Math.random;
import static java.lang.Math.sqrt;

/**
 *
 * @author Peter Cappello
 */
abstract class Critter
{
    static Critter makeCritter() 
    {    
        switch ( (int) ( N_CRITTERS * random() ) )
        {
            case 0: return new SquareCritter();
            case 1: return new RoundCritter();
            case 2: return new WowCritter();
            case 3: return new PacManCritter();
            case 4: return new StarCritter();
            default: assert false;
        }
        return null;
    }
    
    private static final int N_CRITTERS = 5;
    static final int EDGE_LENGTH = 60;
    private static final int IMAGE_SIZE = 600;
    private static final int MAX_DELTA = (int) sqrt( IMAGE_SIZE );
    private static final int MIN_DELTA = (int) sqrt( sqrt( IMAGE_SIZE ) );
    private static final int MAX_DELTA_SIZE = MAX_DELTA - MIN_DELTA;
    
    protected int deltaX;
    protected int deltaY;
    protected Color color;        
    protected int x;
    protected int y;

    Critter()
    {
        x = (int) ( IMAGE_SIZE * random() );
        y = (int) ( IMAGE_SIZE * random() );
        deltaX = getDelta();
        deltaY = getDelta();
        color = getRandomColor();
    }

    protected final Color getRandomColor() 
    { 
        return new Color( (float) random(), (float) random(), (float) random() );
    }

    private int getDelta()   
    {
        int delta = (int) ( random() * MAX_DELTA_SIZE ) + MIN_DELTA;
        return random() < 0.5 ? delta : -delta;
    }

    abstract void draw( Graphics graphics );

    void move()
    {
        int xNew =  x + deltaX;
        x = xNew > 0 ? xNew % IMAGE_SIZE : IMAGE_SIZE - xNew;
        int yNew =  y + deltaY;
        y = yNew > 0 ? yNew % IMAGE_SIZE : IMAGE_SIZE - yNew;
    }

    /**
     * Is the mouse (x, y) within this Critter's (x, y)?
     * @param x horizontal mouse coordinate
     * @param y vertical mouse coordinate
     * @return true if and only if 
     *         x is in [this.x, this.x + EDGE_LENGTH]
     * &amp; 
     *         y is in [this.y, this.y + EDGE_LENGTH]
     */
    boolean isIn( int x, int y )
    {
        return this.x <= x && x <= this.x + EDGE_LENGTH
            && this.y <= y && y <= this.y + EDGE_LENGTH;
    }
}