protected Shape getTail (int type, Rectangle r, Point speaker)
    {
        // emotes don't actually have tails
        if (ChatLogic.modeOf(type) == ChatLogic.EMOTE) {
            return new Area(); // empty shape
        }

        int midx = r.x + (r.width / 2);
        int midy = r.y + (r.height / 2);

        // we actually want to start about SPEAKER_DISTANCE away from the
        // speaker
        int xx = speaker.x - midx;
        int yy = speaker.y - midy;
        float dist = (float) Math.sqrt(xx * xx + yy * yy);
        float perc = (dist - SPEAKER_DISTANCE) / dist;

        if (ChatLogic.modeOf(type) == ChatLogic.THINK) {
            int steps = Math.max((int) (dist / SPEAKER_DISTANCE), 2);
            float step = perc / steps;
            Area a = new Area();
            for (int ii=0; ii < steps; ii++, perc -= step) {
                int radius = Math.min(SPEAKER_DISTANCE / 2 - 1, ii + 2);
                a.add(new Area(new Ellipse2D.Float(
                  (int) ((1 - perc) * midx + perc * speaker.x) + perc * radius,
                  (int) ((1 - perc) * midy + perc * speaker.y) + perc * radius,
                  radius * 2, radius * 2)));
            }

            return a;
        }

        // ELSE draw a triangular tail shape
        Polygon p = new Polygon();
        p.addPoint((int) ((1 - perc) * midx + perc * speaker.x),
                   (int) ((1 - perc) * midy + perc * speaker.y));

        if (Math.abs(speaker.x - midx) > Math.abs(speaker.y - midy)) {
            int x;
            if (midx > speaker.x) {
                x = r.x + PAD;
            } else {
                x = r.x + r.width - PAD;
            }
            p.addPoint(x, midy - (TAIL_WIDTH / 2));
            p.addPoint(x, midy + (TAIL_WIDTH / 2));

        } else {
            int y;
            if (midy > speaker.y) {
                y = r.y + PAD;
            } else {
                y = r.y + r.height - PAD;
            }
            p.addPoint(midx - (TAIL_WIDTH / 2), y);
            p.addPoint(midx + (TAIL_WIDTH / 2), y);
        }

        return p;
    }
protected Shape getTail ( int type , Rectangle r , Point speaker ) { if ( ChatLogic . modeOf ( type ) == ChatLogic . EMOTE ) { return new Area ( ) ; } int midx = r . x + ( r . width / 2 ) ; int midy = r . y + ( r . height / 2 ) ; int xx = speaker . x - midx ; int yy = speaker . y - midy ; float dist = ( float ) Math . sqrt ( xx * xx + yy * yy ) ; float perc = ( dist - SPEAKER_DISTANCE ) / dist ; if ( ChatLogic . modeOf ( type ) == ChatLogic . THINK ) { int steps = Math . max ( ( int ) ( dist / SPEAKER_DISTANCE ) , 2 ) ; float step = perc / steps ; Area a = new Area ( ) ; for ( int ii = 0 ; ii < steps ; ii ++ , perc -= step ) { int radius = Math . min ( SPEAKER_DISTANCE / 2 - 1 , ii + 2 ) ; a . add ( new Area ( new Ellipse2D . Float ( ( int ) ( ( 1 - perc ) * midx + perc * speaker . x ) + perc * radius , ( int ) ( ( 1 - perc ) * midy + perc * speaker . y ) + perc * radius , radius * 2 , radius * 2 ) ) ) ; } return a ; } Polygon p = new Polygon ( ) ; p . addPoint ( ( int ) ( ( 1 - perc ) * midx + perc * speaker . x ) , ( int ) ( ( 1 - perc ) * midy + perc * speaker . y ) ) ; if ( Math . abs ( speaker . x - midx ) > Math . abs ( speaker . y - midy ) ) { int x ; if ( midx > speaker . x ) { x = r . x + PAD ; } else { x = r . x + r . width - PAD ; } p . addPoint ( x , midy - ( TAIL_WIDTH / 2 ) ) ; p . addPoint ( x , midy + ( TAIL_WIDTH / 2 ) ) ; } else { int y ; if ( midy > speaker . y ) { y = r . y + PAD ; } else { y = r . y + r . height - PAD ; } p . addPoint ( midx - ( TAIL_WIDTH / 2 ) , y ) ; p . addPoint ( midx + ( TAIL_WIDTH / 2 ) , y ) ; } return p ; }
Create a tail to the specified rectangular area from the speaker point.