/************************************************************************* * Compilation: javac Turtle.java * Execution: java Turtle * * Singleton Turtle graphics. * *************************************************************************/ import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import javax.swing.*; // for images and audio import java.net.URLConnection; import java.net.URL; // for audio files only import java.applet.Applet; import java.applet.AudioClip; // Support for saving the canvas to a file import java.awt.image.*; import java.io.File; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; public class Turtle extends JFrame { static private Turtle turtle; static private Image offscreenImage; // double buffered image static private Graphics2D offscreen; static private double x = 0.0, y = 0.0; // turtle is at coordinate (x, y) static private double orientation = 0.0; // facing this many degrees counterclockwise static private Insets insets; // border around JFrame that we shouldn't use static private int width, height; // size of drawing area in pixels static private Color bg; // background color // singleton class - user is not allowed to create new ones private Turtle() { } // create a canvas with drawing area width-by-height static public void create(int width, int height) { // If we don't already have a JFrame, open up a new one if (turtle == null) { turtle = new Turtle(); Turtle.width = width; Turtle.height = height; turtle.setSize(new Dimension(width, height)); turtle.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); turtle.setTitle("Turtle Graphics"); turtle.setResizable(false); turtle.setVisible(true); // let us see the frame // re-adjust the size of the frame so that we don't lose space for insets insets = turtle.getInsets(); turtle.setSize(new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom)); System.out.println(width + " x " + height); // Initialize the picture init(); } } static private void init() { // create double buffered image and graphics handle offscreenImage = turtle.createImage(width, height); offscreen = (Graphics2D) offscreenImage.getGraphics(); // rescale and translate so that (0, 0) is lower left offscreen.translate(0, height); offscreen.scale(1.0, -1.0); // clear the screen clear(Color.white); } // close the window public static void done() { turtle.dispose(); turtle = null; } // clear the background public static void clear() { Color fg = offscreen.getColor(); offscreen.setColor(bg); offscreen.fillRect(0, 0, width, height); // should this be width - 1, height - 1 ? offscreen.setColor(fg); } // clear the background with a new color public static void clear(Color bg) { Turtle.bg = bg; clear(); } // wait for a short while public static void pause(int delay) { try { Thread.currentThread().sleep(delay); } catch (InterruptedException e) { } } // change the color of the paint public static void setColor(Color color) { offscreen.setColor(color); } public static void fly(double x, double y) { Turtle.x = x; Turtle.y = y; } public static void go(double x, double y) { offscreen.draw(new Line2D.Double(Turtle.x, Turtle.y, x, y)); Turtle.x = x; Turtle.y = y; } public static void spot(double size) { offscreen.fill(new Rectangle2D.Double(x - size/2, y - size/2, size, size)); } // circle of radius = size // public static void spot(double size) { // offscreen.fill(new Ellipse2D.Double(x - size, y - size, 2*size, 2*size)); // } // draw spot using gif - fix to be centered at (x, y) public static void spot(String s) { // needed to load from jar URL url = Turtle.class.getResource(s); Image image = Toolkit.getDefaultToolkit().getImage(url); // Image image = Toolkit.getDefaultToolkit().getImage(s); offscreen.scale(1.0, -1.0); offscreen.translate(0, -height); offscreen.drawImage(image, (int) x - image.getWidth(null) / 2, (int) y - image.getHeight(null) / 2, null); offscreen.translate(0, height); offscreen.scale(1.0, -1.0); /* offscreen.drawImage(image, (int) x, (int) y , (int) x + image.getWidth(null), (int) y -image.getHeight(null), 0, 0, image.getWidth(null), image.getHeight(null), null); */ } public static void pixel(int x, int y) { offscreen.drawRect(x, y, 1, 1); } // rotate counterclockwise in degrees public static void rotate(double angle) { orientation += angle; } public static void forward(double d) { double oldx = x; double oldy = y; x += d * Math.cos(Math.toRadians(orientation)); y += d * Math.sin(Math.toRadians(orientation)); offscreen.draw(new Line2D.Double(x, y, oldx, oldy)); } public static void grunt(String s) { URL url = Turtle.class.getResource(s); AudioClip clip = Applet.newAudioClip(url); clip.play(); } public void paint(Graphics g) { if (g != null && offscreenImage != null) g.drawImage(offscreenImage, insets.left, insets.top, this); } public static void render() { turtle.repaint(); } public static void save(String s) { BufferedImage bi = (BufferedImage) offscreenImage; System.out.println("Saving to " + s); try { File f = new File(s); ImageIO.write(bi, "png", f); } catch (IOException e) { System.out.println("Unable to write to file " + s); e.printStackTrace(); } } }