import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Image; import java.awt.image.ImageProducer; import java.awt.image.MemoryImageSource; /** * This class provides support for the *Turtle* (the object displayed which * is the source of all graphics activity). It provides the actual image of * the turtle as well as support for all TurtleTalk commands and operators * which manipulate/query the turtle's state. ** @author Guy Haas */ public class Turtle extends Component { // // constants // public static final int NORTH = 0; public static final int EAST = 90; public static final int SOUTH = 180; public static final int WEST = 270; public static final int BLACK = 0; public static final int BLUE = 1; public static final int GREEN = 2; public static final int CYAN = 3; public static final int RED = 4; public static final int MAGENTA = 5; public static final int YELLOW = 6; public static final int WHITE = 7; public static final int BROWN = 8; public static final int TAN = 9; public static final int FOREST = 10; public static final int AQUA = 11; public static final int SALMON = 12; public static final int VIOLET = 13; public static final int ORANGE = 14; public static final int GRAY = 15; private static final Color COLORS[] = new Color[16]; static { COLORS[ BLACK ] = Color.black; COLORS[ BLUE ] = Color.blue; COLORS[ GREEN ] = Color.green; COLORS[ CYAN ] = Color.cyan; COLORS[ RED ] = Color.red; COLORS[ MAGENTA ] = Color.magenta; COLORS[ YELLOW ] = Color.yellow; COLORS[ WHITE ] = Color.white; COLORS[ BROWN ] = new Color(155, 96, 59); COLORS[ TAN ] = new Color(197, 136, 18); COLORS[ FOREST ] = new Color(100, 162, 64); COLORS[ AQUA ] = new Color(120, 187, 187); COLORS[ SALMON ] = new Color(255, 149, 119); COLORS[ VIOLET ] = new Color(144, 113, 208); COLORS[ ORANGE ] = Color.orange; COLORS[ GRAY ] = Color.lightGray; }; // height and width of the isosceles triangle that represents the // default turtle. initTurtlePixels() assumes that the height is // greater than or equal to the width. both the height and the // width should be odd numbers so that the image looks good when // rotated around its center bit private static final int TURTLE_HEIGHT = 21; private static final int TURTLE_WIDTH = 15; private static final int BLACK_OPAQUE_PIXEL = 0xff000000; private static final int PIXEL_OPACITY_BITS = 0xff000000; private static final int WHITE_OPAQUE_PIXEL = 0xffffffff; private static final int INITIAL_PEN_SIZE = 2; private static final int INITIAL_FONT_SIZE = 14; private static final int INITIAL_FONT_STYLE = Font.PLAIN; private static final String INITIAL_FONT_NAME = "Courier"; private static final Font INITIAL_FONT; static { INITIAL_FONT = new Font( INITIAL_FONT_NAME, INITIAL_FONT_STYLE, INITIAL_FONT_SIZE ); } private static final Color INITIAL_FOREGROUND = Color.black; // variables with class-wide scope // private boolean penDown; private boolean showTurtle; private boolean[] turtleFillMask; // used to determine which pixels in // baseTurtlePixels[] change when the // pen color changes private Color currentPenColor; private int currentPenSize; private int turtleSideSize; // this needs to be computed such // that it is larger than either // TURTLE_HEIGHT and TURTLE_WIDTH // so that the corners of the image // of the turtle are not clipped // when drawn at certain angles, // e.g., 45 degrees private int[] baseTurtlePixels; // pixel array for the turtle in an // eastern orientation, i.e. headed // along the positive X axis private int[] turtlePixels; // pixel array for current turtle's // image - if it's visible. it is // oriented toward current heading // and its body is current color private float currentHeading; // radians in conventional/AWT manner private Font currentFont = INITIAL_FONT; private Image turtleImage; private MemoryImageSource turtleImageProducer; private TGCanvas tgc; // where this turtle draws private TGPoint currentPoint; // current X,Y location of the turtle // // Turtle Constructors // public Turtle( TGCanvas tgc ) { this.tgc = tgc; currentFont = INITIAL_FONT; currentHeading = (float) (Math.PI / 2.0); currentPenColor = INITIAL_FOREGROUND; currentPenSize = INITIAL_PEN_SIZE; currentPoint = new TGPoint( 0, 0 ); penDown = true; showTurtle = true; initTurtlePixels(); tgc.addTurtle( this ); } // end Turtle() // build a mask of pixels that are to be changed when // the foreground color is changed. starting with // the center pixel of the turtle image, a flood-fill // algorithm is used to identify all pixels with the // same color value. these pixels are set to true in // a mask array. colorTurtle() uses this mask to change // the color of the turtle. // // although baseTurtlePixels is manipulated as an array // with a single index, it is really a two dimensional // array, a series of rows of pixels. each row is // turtleSideSize pixels in width. this explains why // pixelIndex = rowNumber * turtleSideSize + columnNumber // is used to calculate a pixel's index // private void buildTurtleFillMask() { int column = turtleSideSize / 2; int row = turtleSideSize / 2; int color = baseTurtlePixels[ row * turtleSideSize + column ]; turtleFillMask = new boolean[turtleSideSize * turtleSideSize]; floodFill( row, column, color ); } // end buildTurtleFillMask // clearToTurtleEdge - set all white pixels outside the // edge of the turtle to be transparent // private void clearToTurtleEdge() { for (int y=0; y < turtleSideSize; y++ ) for (int x=0; x < turtleSideSize; x++ ) { int i = y * turtleSideSize + x; if ( (baseTurtlePixels[i] & 0x00ffffff) == 0x00ffffff ) baseTurtlePixels[i] = 0; else break; } for (int y=0; y < turtleSideSize; y++ ) for (int x=turtleSideSize-1; x >= 0; x-- ) { int i = y * turtleSideSize + x; if ( (baseTurtlePixels[i] & 0x00ffffff) == 0x00ffffff ) baseTurtlePixels[i] = 0; else break; } for (int x=0; x < turtleSideSize; x++ ) for (int y=0; y < turtleSideSize; y++ ) { int i = y * turtleSideSize + x; if ( (baseTurtlePixels[i] & 0x00ffffff) == 0x00ffffff ) baseTurtlePixels[i] = 0; else break; } for (int x=0; x < turtleSideSize; x++ ) for (int y=turtleSideSize-1; y >= 0; y-- ) { int i = y * turtleSideSize + x; if ( (baseTurtlePixels[i] & 0x00ffffff) == 0x00ffffff ) baseTurtlePixels[i] = 0; else break; } } // end clearToTurtleEdge() // fill inner pixels of the turtle with the specified color. // private void colorTurtle( Color newColor ) { int heading = (int) Math.rint( currentHeading / (Math.PI/180.0) ); int rgbVals = newColor.getRGB(); for (int pixIdx=0; pixIdx < baseTurtlePixels.length; pixIdx++) if ( turtleFillMask[pixIdx] == true ) { int pixel = baseTurtlePixels[pixIdx] & PIXEL_OPACITY_BITS; pixel += rgbVals; baseTurtlePixels[pixIdx] = pixel; } updateTurtlePixels( heading ); } // end colorTurtle() // draw the turtle, an isosceles triangle, into baseTurtlePixels. // the turtle's image is on its side, pointing right so that it's // aligned with the positive X axis, a heading of mathematical 0 // degrees (not to be confused with TurtleSpace's coordinate system // where 0 degrees is the positive Y axis). // // first the base is drawn as a vertical line, from its top to // its bottom. then, the legs of the isosceles triangle are drawn. // The code that does this is an adaptation of the "midpoint" // technique for scanline creation (see van Aken, J., and Novak, // Mark. Curve Drawing Algorithms for Raster Displays. ACM // Transactions on Graphics. Apr 1985.) also available in the // classic book: Computer Graphics: Principles and Practice, by // Foley, van Dam, Feiner, Hughes // private void drawDefaultTurtle() { int center, x, y; center = turtleSideSize / 2; x = center - TURTLE_HEIGHT / 2; y = center - TURTLE_WIDTH / 2; while ( y <= center + TURTLE_WIDTH/2 ) { baseTurtlePixels[y*turtleSideSize + x] = BLACK_OPAQUE_PIXEL; y++; } int deltaX = TURTLE_HEIGHT; int deltaY = TURTLE_WIDTH/2; int incrE = 2 * deltaY; int incrNE = 2 * (deltaY - deltaX); int which = (2 * deltaY) - deltaX; int lowerY = center + TURTLE_WIDTH/2; int upperY = center - TURTLE_WIDTH/2; while ( x <= center + TURTLE_HEIGHT/2 ) { if ( which <= 0 ) { which += incrE; x++; } else { which += incrNE; x++; lowerY--; upperY++; } baseTurtlePixels[lowerY * turtleSideSize + x] = BLACK_OPAQUE_PIXEL; baseTurtlePixels[upperY * turtleSideSize + x] = BLACK_OPAQUE_PIXEL; } } // end drawDefaultTurtle() // floodFill // private void floodFill( int row, int column, int color ) { int pixIdx = row * turtleSideSize + column; if ( baseTurtlePixels[pixIdx] == color && !turtleFillMask[pixIdx] ) { turtleFillMask[pixIdx] = true; if ( row - 1 >= 0 ) floodFill( row - 1, column, color ); if ( row + 1 < turtleSideSize ) floodFill( row + 1, column, color ); if ( column - 1 >= 0 ) floodFill( row, column - 1, color ); if ( column + 1 < turtleSideSize ) floodFill( row, column + 1, color ); } } // end floodFill // initialize the turtle // private void initTurtlePixels() { turtleSideSize = TURTLE_HEIGHT + TURTLE_HEIGHT/4; if ( turtleSideSize % 2 == 0 ) turtleSideSize++; baseTurtlePixels = new int[turtleSideSize * turtleSideSize]; for (int pixIdx=0; pixIdx < baseTurtlePixels.length; pixIdx++) baseTurtlePixels[pixIdx] = WHITE_OPAQUE_PIXEL; drawDefaultTurtle(); clearToTurtleEdge(); buildTurtleFillMask(); for (int pixIdx=0; pixIdx < baseTurtlePixels.length; pixIdx++) if ( turtleFillMask[pixIdx] == true ) baseTurtlePixels[pixIdx] = BLACK_OPAQUE_PIXEL; updateTurtlePixels( 90 ); } // end initTurtlePixels() private void printPixels(String what, int[] pixels, int width, int height) { for ( int y=0; y < height; y++ ) { for ( int x=0; x < width; x++ ) { int i = y * width + x; int a = (pixels[i] >> 24) & 0xff; int r = (pixels[i] >> 16) & 0xff; int g = (pixels[i] >> 8) & 0xff; int b = pixels[i] & 0xff; System.out.println(what+"["+i+"] a="+a+", r="+r+", g="+g+", b="+b); } System.out.println( "----------" ); } } // end printPixels() private int rgbToPencolor( int rgbValue ) { rgbValue &= 0xFFFFFF; for (int i=0; i < COLORS.length; i++) if ( (COLORS[i].getRGB() & 0xFFFFFF) == rgbValue ) return( i ); return rgbValue; } // end rgbToPencolor() // update turtlePixels[] to reflect the specified heading (in degrees) // and return it. baseTurtlePixels[] is rotated to the new heading and // the results are stored in turtlePixels[]. // private void updateTurtlePixels( int heading ) { if ( turtlePixels == null ) turtlePixels = new int[turtleSideSize * turtleSideSize]; if ( heading == 0 ) // no translation if heading aligned with orig image for (int i=0; i < turtleSideSize * turtleSideSize; i++) turtlePixels[i] = baseTurtlePixels[i]; else { int center = turtleSideSize / 2; double theta = Math.PI/180.0 * (double) (360 - heading); double cosTheta = Math.cos( theta ); double sinTheta = Math.sin( theta ); double xOffset = -center * cosTheta - center * sinTheta + center; double yOffset = center * sinTheta - center * cosTheta + center; // first zap destination, make all pixels transparent for (int y=0; y < turtleSideSize; y++) for (int x=0; x < turtleSideSize; x++) turtlePixels[y * turtleSideSize + x] = 0; for (int row=0; row < turtleSideSize; row++) for (int col=0; col < turtleSideSize; col++) { int pixel, pixelIndex; int srcX, srcY; srcX = (int) Math.rint(col*cosTheta + row*sinTheta + xOffset); srcY = (int) Math.rint(-col*sinTheta + row*cosTheta + yOffset); if ( srcX < 0 || srcX >= turtleSideSize ) continue; if ( srcY < 0 || srcY >= turtleSideSize ) continue; pixelIndex = srcY * turtleSideSize + srcX; pixel = baseTurtlePixels[ pixelIndex ]; turtlePixels[row * turtleSideSize + col] = pixel; } } turtleImage = null; } //end updateTurtlePixels() // ------------------------------------------ // Methods available outside the Turtle class, sorted alphabetically // ------------------------------------------ /** * Move the turtle backwards along its current heading. If the * pen is currently in the DOWN position, a line is drawn. *
* Long name for bk(). Both spellings need to provided for * compatibility. *
* @param steps Number of pixels (in this implementation) to take. * @see #bk */ public void back( double steps ) { bk( steps ); } public void back( float steps ) { bk( (double) steps ); } public void back( int steps ) { bk( (double) steps ); } /** * Move the turtle backwards along its current heading. If the * pen is currently in the DOWN position, a line is drawn. *
* Abbreviation for back(). Both spellings need to * provided for compatibility. *
* @param steps Number of pixels (in this implementation) to take. * @see #back */ public void bk( float steps ) { bk( (double) steps ); } public void bk( int steps ) { bk( (double) steps ); } public void bk( double steps ) { if ( penDown ) currentPoint = tgc.drawLine( currentPoint, -steps, (double) currentHeading, currentPenSize, currentPenColor ); else currentPoint = currentPoint.otherEndPoint((double) currentHeading, -steps); if ( penDown || showTurtle ) tgc.tgDoRepaint(); } // end bk() /** * Return the color the Turtle is sitting on *
* @see #pencolor * @see #setpc * @see #setpencolor */ public int colorunder() { return rgbToPencolor( tgc.colorunder(currentPoint) ); } // end colorunder() /** * Fill a bounded area in the graphics image. *
* The current pixel, and any of its neighbors that are the * same color as it (and any of their neighbors that are the * same color as it, etc...) are changed to the current color. */ public void fill() { tgc.fill( currentPoint, currentPenColor ); tgc.tgDoRepaint(); } // end fill() /** * Move the turtle forward along its current heading. If the * pen is currently in the DOWN position, a line is drawn. *
* Abbreviation for forward(). Both spellings need to * provided for compatibility. *
* @param steps Distance in TurtleSpace to move. * @see #forward */ public void fd( float steps ) { fd( (double) steps ); } public void fd( int steps ) { fd( (double) steps ); } public void fd( double steps ) { if ( penDown ) currentPoint = tgc.drawLine( currentPoint, steps, (double) currentHeading, currentPenSize, currentPenColor ); else currentPoint = currentPoint.otherEndPoint((double) currentHeading, steps); if ( penDown || showTurtle ) tgc.tgDoRepaint(); } // end fd() /** * Move the turtle forward along its current heading. If the * pen is currently in the DOWN position, a line is drawn. *
* Long name for fd(). Both spellings need to provided for * compatibility. *
* @param steps Number of pixels (in this implementation) to take. * @see #fd */ public void forward( double steps ) { fd( steps ); } public void forward( float steps ) { fd( (double) steps ); } public void forward( int steps ) { fd( (double) steps ); } /** * Return the turtle's Image */ public Image getImage() { if ( turtleImage == null ) { // create turtleImage to match the array of pixels: turtlePixels // AWT Graphics only supports painting of Image objects, no kind // of BitBlt for arrays of pixel values (?who know's why?) if ( turtleImageProducer == null ) turtleImageProducer = new MemoryImageSource( turtleSideSize, turtleSideSize, turtlePixels, 0, turtleSideSize ); turtleImage = createImage( turtleImageProducer ); } return turtleImage; } // end getImage() /** * Return the size of a side of the turtle's Image *
* @see #getImage */ public int getImageSideSize() { return turtleSideSize; } /** * Return the width of the pen the turtle is currently * writing with *
* @see #setpensize */ public int pensize() { return( currentPenSize ); } /** * Return the Turtle's heading *
* @see #seth * @see #setheading */ // Logo's TurtleSpace doesn't match the mathematical // convention of measuring angles counter-clockwise from // the positive X axis. Logo defines North (+Y axis) as // 0 degrees and degrees increase in the clockwise // direction, so East is 90 degrees, South is 180 degrees // and West is 270 degrees. The module-wide variable // currentHeading contains the mathematically-correct // heading in radians, not Logo's point of view. So, we // must convert currentHeading to TurtleSpace's scheme. // public int heading() { int degrees = (int) Math.rint( currentHeading / (Math.PI/180.0) ); int turtleSpaceDegrees = 360 - degrees; turtleSpaceDegrees += 90; turtleSpaceDegrees %= 360; return( turtleSpaceDegrees ); } /** * Move the turtle to the center of the display. If the * pen is currently in the DOWN position, a line is drawn. *
* Home is equivilent to setxy( 0, 0 ) *
* @see #setxy */ public void home() { setxy( 0, 0 ); } /** * Hide the turtle; make it invisible. *
* Abbreviation for hideturtle(). Both spellings need to * provided for compatibility. *
* @see #hideturtle * @see #showturtle * @see #st */ public void ht() { if ( showTurtle ) { turtlePixels = null; turtleImage = null; turtleImageProducer = null; tgc.removeTurtle( this ); tgc.tgDoRepaint(); showTurtle = false; } } // end ht() /** * Hide the turtle; make it invisible. *
* Long name for ht(). Both spellings need to provided for * compatibility. *
* @see #ht * @see #showturtle * @see #st */ public void hideturtle() { ht(); } /** * Return the current status of the pen. *
* Return true if the turtle's pen is down or * false if it in the up position. *
* @see #pendown * @see #penup * @see #pd * @see #pu */ public boolean ispendown() { return penDown; } /** * Paints a String of characters on the display. * The text is painted in the current pen's color, * starting at the current position of the turtle. *
* The text is always painted in the standard * horizontal manner, i.e., the heading of the * turtle is ignored. *
* @param text Characters to be painted on the display. */ public void label( String text ) { if ( text != null ) { tgc.label( text, currentPoint, currentFont, currentPenColor ); tgc.tgDoRepaint(); } } // end label() /** * Rotate the turtle counterclockwise by the specified * angle, measured in degrees. *
* @param degrees Angle to change turtle's heading by. * @see #lt */ public void left( float degrees ) { lt( degrees ); } public void left( int degrees ) { lt( (float) degrees ); } /** * Rotate the turtle counterclockwise by the specified * angle, measured in degrees. *
* Abbreviation for left(). Both spellings need * to provided for compatibility. *
* @param degrees Angle to change turtle's heading by. * @see #left */ // Logo degrees increase in the clockwise direction. // Since this does not match the mathematical convention // of measuring angles counterclockwise, we must convert // the parameter. public void lt( float degrees ) { lt( (double) degrees ); } public void lt( int degrees ) { lt( (double) degrees ); } public void lt( double degrees ) { float radians = (float) (degrees * (Math.PI/180.0)); currentHeading += radians; if ( currentHeading > Math.PI * 2.0 ) currentHeading -= Math.PI * 2.0; if ( showTurtle ) { int newDegrees = (int) Math.rint( currentHeading / (Math.PI/180.0) ); updateTurtlePixels( newDegrees ); tgc.tgDoRepaint(); } } // end lt() /** * Put the turtle's pen in the down position. *
* When the turtle moves, it will leave a trace from its * current position to its destination (its new position). * @see #ispendown * @see #pendown * @see #pu * @see #penup */ public void pd() { penDown = true; } /** * Return the color the pen is currently writing in *
* @see #setpc * @see #setpencolor */ public int pencolor() { int rgbVal = currentPenColor.getRGB(); //System.out.print( "pencolor: R=" + ((rgbVal & 0xff0000) >> 16) ); //System.out.print( " G=" + ((rgbVal & 0xff00) >> 8) ); //System.out.println( " B=" + (rgbVal & 0xff) ); return rgbToPencolor( rgbVal ); } // end pencolor() /** * Put the turtle's pen in the down position. *
* When the turtle moves, it will leave a trace from its * current position to its destination (its new position). * @see #ispendown * @see #pd * @see #pu * @see #penup */ public void pendown() { pd(); } /** * Put the turtle's pen in the up position. *
* When the turtle moves, it will leave no trace. * @see #ispendown * @see #pd * @see #pendown * @see #penup */ public void pu() { penDown = false; } /** * Put the turtle's pen in the up position. *
* When the turtle moves, it will leave no trace. * @see #ispendown * @see #pd * @see #pendown * @see #pu */ public void penup() { pu(); } /** * Rotate the turtle clockwise by the specified angle, * measured in degrees. *
* @param degrees Angle to change turtle's heading by. * @see #rt */ public void right( double degrees ) { rt( degrees ); } public void right( float degrees ) { rt( (double) degrees ); } public void right( int degrees ) { rt( (double) degrees ); } /** * Rotate the turtle clockwise by the specified angle, * measured in degrees. *
* Abbreviation for right(). Both spellings need * to provided for compatibility. *
* @param degrees Angle to change turtle's heading by. * @see #right */ // Logo degrees increase in the clockwise direction. // Since this does not match the mathematical convention // of measuring angles counterclockwise, we must convert // the parameter. public void rt( float degrees ) { rt( (double) degrees ); } public void rt( int degrees ) { rt( (double) degrees ); } public void rt( double degrees ) { float radians = (float) (degrees * (Math.PI/180.0)); currentHeading -= radians; if ( currentHeading < 0.0F ) currentHeading += Math.PI * 2.0; if ( showTurtle ) { int newDegrees = (int) Math.rint( currentHeading / (Math.PI/180.0) ); updateTurtlePixels( newDegrees ); tgc.tgDoRepaint(); } } // end rt() /** * Set the size of the text displayed in the graphics area. * @see #label */ public void setlabelheight( int size ) { if ( currentFont.getSize() != size ) currentFont = new Font(INITIAL_FONT_NAME, INITIAL_FONT_STYLE, size); } // end setlabelheight() /** * Turns the turtle to the specified absolute heading. * The heading is specified in degrees (units of 1/360th * of a circle) with 0 being North (+Y axis), increasing * clockwise. So, East is 90 degrees, South is 180 degrees, * and West is 270 degrees. *
* Abbreviation for setheading(). Both spellings * need to provided for compatibility. *
* @param degrees number of 1/360ths increments clockwise * from the positive Y axis. * @see #setheading */ // Logo defines North (+Y axis) as 0 degrees and degrees // increase in the clockwise direction, so East is 90 // degrees, South is 180 degrees and West is 270 degrees. // Since this does not match the mathematical convention // of measuring angles counterclockwise from the positive // X axis, we must convert the parameter. The module-wide // variable (currentHeading) contains the mathematically- // correct heading, not Logo's point of view. // public void seth( int turtleSpaceDegrees ) { int degrees = (360 - (turtleSpaceDegrees % 360)); degrees += 90; degrees %= 360; currentHeading = (float) (degrees * (Math.PI/180.0)); if ( showTurtle ) { updateTurtlePixels(degrees); tgc.tgDoRepaint(); } } // end seth() /** * Turns the turtle to the specified absolute heading. * The heading is specified in degrees (units of 1/360th * of a circle) with 0 being North (+Y axis), increasing * clockwise. So, East is 90 degrees, South is 180 degrees, * and West is 270 degrees. * @param degrees number of 1/360ths increments clockwise * from the positive Y axis. * @see #seth */ public void setheading(int degrees) { seth(degrees); } /** * Sets the color of the turtle's pen to the supplied number. * @param colorNum numbers 0-15 are: *
*
* Number Color Number Color * ------ ------- ------ ------- * 0 black 8 brown * 1 blue 9 tan * 2 green 10 forest * 3 cyan 11 aqua * 4 red 12 salmon * 5 magenta 13 violet * 6 yellow 14 orange * 7 white 15 grey *** Color numbers greater than 15 will be assumed to be RGB * values with the red component in bits 16-23, the green * component in bits 8-15, and the blue component in bits * 0-7. The actual color used in rendering will depend on * finding the best match given the color space available * for a given display. * @see #getpencolor * @see #setpencolor */ public void setpc( int colorNum ) { Color color; if ( colorNum >= 0 && colorNum <= 15 ) color = COLORS[colorNum]; else { colorNum &= 0777777777; color = new Color( colorNum ); } if ( currentPenColor.getRGB() != color.getRGB() ) { currentPenColor = color; if ( showTurtle ) { colorTurtle( color); tgc.tgDoRepaint(); } } } // end setpc() /** * Sets the color of the turtle's pen to the supplied number. * @param colorNum numbers 0-15 are: *
*
* Number Color Number Color * ------ ------- ------ ------- * 0 black 8 brown * 1 blue 9 tan * 2 green 10 forest * 3 cyan 11 aqua * 4 red 12 salmon * 5 magenta 13 violet * 6 yellow 14 orange * 7 white 15 grey *** Color numbers greater than 15 will be assumed to be RGB * values with the red component in bits 16-23, the green * component in bits 8-15, and the blue component in bits * 0-7. The actual color used in rendering will depend on * finding the best match given the color space available * for a given display. * @see #getpencolor * @see #setpc */ public void setpencolor(int colorNum) { setpc(colorNum); } /** * Sets the width of the turtle's pen to the supplied number. * @param width small positive number; 1 (or less) results * in a single pixel line. */ public void setpensize( int width ) { if ( width == currentPenSize ) return; if ( width < 1 ) currentPenSize = 1; else currentPenSize = width; } // end setpensize() /** * Move the turtle to an absolute display position. *
* Move the turtle horizontally to a new location * specified as an X coordinate argument. * @param newX the X-coordinate of destination. * @see #home * @see #setxy * @see #sety */ public void setx( int newX ) { TGPoint p2 = new TGPoint( (float) newX, currentPoint.yFloatValue() ); if ( penDown ) tgc.drawLine( currentPoint, p2, currentPenSize, currentPenColor ); currentPoint = p2; if ( penDown || showTurtle ) tgc.tgDoRepaint(); } // end setx() /** * Move the turtle to an absolute display position. *
* Move the turtle to the x and y coordinates provided * as arguments. * @param newX the X-coordinate of destination. * @param newY the Y-coordinate of destination. * @see #home * @see #setx * @see #sety */ public void setxy( int newX, int newY ) { TGPoint p2 = new TGPoint( newX, newY ); if ( penDown ) tgc.drawLine( currentPoint, p2, currentPenSize, currentPenColor ); currentPoint = p2; if ( penDown || showTurtle ) tgc.tgDoRepaint(); } // end setxy() /** * Move the turtle to an absolute display position. *
* Move the turtle vertically to a new location * specified as an Y coordinate argument. * @param newY the Y-coordinate of destination. * @see #home * @see #setx * @see #setxy */ public void sety( int newY ) { TGPoint p2 = new TGPoint( currentPoint.xFloatValue(), (float) newY ); if ( penDown ) tgc.drawLine( currentPoint, p2, currentPenSize, currentPenColor ); currentPoint = p2; if ( penDown || showTurtle ) tgc.tgDoRepaint(); } // end sety() /** * Show the turtle; make it visible. *
* Long name for st(). Both spellings need to provided for * compatibility. *
* @see #hideturtle * @see #ht * @see #st */ public void showturtle() { st(); } /** * Show the turtle; make it visible. *
* Abbreviation for showturtle(). Both spellings need to * provided for compatibility. *
* @see #hideturtle * @see #ht * @see #showturtle */ public void st() { if ( ! showTurtle ) { colorTurtle( currentPenColor ); tgc.addTurtle( this ); tgc.tgDoRepaint(); showTurtle = true; } } // end st() /** * Return the Turtle's X-coordinate * @see #setxy * @see #setx * @see #sety * @see #ycor */ public int xcor() { return currentPoint.xIntValue(); } /** * Return the Turtle's Y-coordinate * @see #setxy * @see #setx * @see #sety * @see #xcor */ public int ycor() { return currentPoint.yIntValue(); } } // end class Turtle