Commit bdc2023c by Patryk Czarnik

Przykłady Turtle

parent 80939e96
package turtle;
public class Poczatek {
public static void main(String[] args) {
Turtle turtle = new Turtle();
turtle.penColor("red");
turtle.forward(200);
turtle.left(90);
turtle.forward(200);
turtle.left(90);
turtle.penColor("blue");
turtle.forward(200);
turtle.left(90);
turtle.forward(200);
turtle.penColor("green");
turtle.left(135);
turtle.forward(200 * Math.sqrt(2));
// przeskok bez rysowania
turtle.up();
turtle.setPosition(-300, -200);
turtle.down();
turtle.dot();
}
}
package turtle;
/**AUTHOR: NICHOLAS SEWARD
* EMAIL: nicholas.seward@gmail.com
* LICENSE: MIT (USE THIS HOWEVER YOU SEE FIT.)
* DATE: 6/21/2012
* VERSION: 2 (THIS SHOULD BE VERSION 0.1 BUT THAT IS A SILLY NUMBERING SYSTEM.)
*
* https://github.com/NicholasSeward/Turtle
*
* THIS SOFTWARE HAS NO WARRANTY. IF IT WORKS, SUPER. IF IT DOESN'T, LET ME
* KNOW AND I MIGHT OR MIGHT NOT DO SOMETHING ABOUT IT.
*
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.lang.reflect.Method;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.filechooser.FileNameExtensionFilter;
/**
* Turtle is a selfcontained class that will allow students to make
* beautiful turtle graphics with ease.
*
* @author Nicholas Seward
*/
@SuppressWarnings("unchecked")
public class Turtle implements Runnable, ActionListener, MouseListener, MouseMotionListener, KeyListener, ComponentListener, MouseWheelListener
{
private static ArrayList<Turtle> turtles;
private static TreeMap<Long,ArrayList> turtleStates;
private static TreeMap<Long,ArrayList> redoStates;
private static JFrame window;
private static JApplet applet;
private static JLabel draw;
private static int width, height;
private static BufferedImage offscreenImage, midscreenImage, onscreenImage;
private static Graphics2D offscreen, midscreen, onscreen;
private static BufferedImage backgroundImage;
private static Color backgroundColor;
private static ImageIcon icon;
private static Turtle turtle;
private static HashMap<String,Polygon> shapes; //You can only add. Never remove.
private static HashMap<String, Color> colors;
private static HashMap<String,ArrayList<ArrayList>> keyBindings;
private static HashMap<Turtle,ArrayList<ArrayList>> mouseBindings;
private static double centerX, centerY;
private static double scale;
private static TreeSet<String> keysDown;
private static TreeSet<String> processedKeys;
private static TreeSet<String> unprocessedKeys;
private static long lastUpdate;
private static long fps;
private static final Object turtleLock=new Object();
private static int dragx=0,dragy=0,x=0,y=0,modifiers=0;
private static final Object keyLock = new Object();
private static final int REFRESH_MODE_ANIMATED=0;
private static final int REFRESH_MODE_STATE_CHANGE=1;
private static final int REFRESH_MODE_ON_DEMAND=2;
private static int refreshMode;
private static final int BACKGROUND_MODE_STRETCH=0;
private static final int BACKGROUND_MODE_CENTER=1;
private static final int BACKGROUND_MODE_TILE=2;
private static final int BACKGROUND_MODE_CENTER_RELATIVE=3;
private static final int BACKGROUND_MODE_TILE_RELATIVE=4;
private static int backgroundMode;
private static Turtle selectedTurtle;
private static boolean running;
static { init(); }
/**
* This is an internal method that should never be called.
*/
public void run()
{
if(Thread.currentThread().getName().equals("render")) renderLoop();
else if(Thread.currentThread().getName().equals("listen")) eventLoop();
}
private void eventLoop()
{
//System.out.println("EVENT LOOP STARTED");
long time=0;
while(running)
{
time=System.nanoTime();
processKeys();
waitUntil(time+1000000000/fps);
}
}
private void renderLoop()
{
//System.out.println("RENDER LOOP STARTED");
long time=0;
while(running)
{
time=System.nanoTime();
//System.out.println(time);
if(refreshMode==REFRESH_MODE_ANIMATED) draw();
if (!waitUntil(time+1000000000/fps)) fps--;
else if (fps<30) fps++;
}
}
private static boolean waitUntil(Long time)
{
long now=System.nanoTime();
if (now<time)
{
try {Thread.sleep((time - now) / 1000000);}
catch(Exception e) {}
return true;
}
else return false;
}
private static void init()
{
//mouseBindings.put(null, new ArrayList<ArrayList>());
turtles=new ArrayList<Turtle>();
turtleStates=new TreeMap<Long,ArrayList>();
redoStates=new TreeMap<Long,ArrayList>();
width=500;
height=500;
backgroundColor=Color.WHITE;
keyBindings=new HashMap<String,ArrayList<ArrayList>>();
mouseBindings=new HashMap<Turtle,ArrayList<ArrayList>>();
centerX=0;
centerY=0;
scale=1;
keysDown=new TreeSet<String>();
processedKeys=new TreeSet<String>();
unprocessedKeys=new TreeSet<String>();
lastUpdate=0;
fps=30;
dragx=0;
dragy=0;
x=0;
y=0;
modifiers=0;
refreshMode=REFRESH_MODE_ANIMATED;
backgroundMode=BACKGROUND_MODE_TILE_RELATIVE;
selectedTurtle=null;
running=true;
window = new JFrame("Turtle");
icon = new ImageIcon();
setupBuffering();
draw = new JLabel(icon);
window.setContentPane(draw);
//window.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
try{window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
catch(Exception e){}
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("File");
menuBar.add(menu);
JMenuItem menuItem1 = new JMenuItem("Save...");
menuItem1.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
menu.add(menuItem1);
window.setJMenuBar(menuBar);
window.pack();
window.requestFocusInWindow();
drawTurtleIcon();
window.setVisible(true);
makeShapes();
turtle=new Turtle(0);
draw.setFocusable(true);
menuItem1.addActionListener(turtle);
window.addComponentListener(turtle);
draw.addComponentListener(turtle);
draw.addMouseListener(turtle);
draw.addMouseMotionListener(turtle);
draw.addMouseWheelListener(turtle);
window.addKeyListener(turtle);
draw.addKeyListener(turtle);
draw.requestFocus();
initColors();
// GraphicsEnvironment ge;
// ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
// String[] fontNames = ge.getAvailableFontFamilyNames();
// System.out.println(Arrays.toString(fontNames));
(new Thread(turtle,"render")).start();
(new Thread(turtle,"listen")).start();
}
public static void exit()
{
running=false;
window.setVisible(false);
window.dispose();
}
/**
* This is an experimental method that should allow you to make turtle
* applets in the future. For now, it doesn't work because the key and
* mouse bindings require reflection and applets think that allowing
* reflection would open a security hole. Theoretically in the init method
* of the applet you need to place <code>Turtle.startApplet(this);</code>.
* <b>This is not currently working.</b>
*
* @param applet
*/
public static void startApplet(JApplet applet)
{
//turtleStates.clear();
//turtles.clear();
//init();
Turtle.applet=applet;
applet.setContentPane(window.getContentPane());
window.setVisible(false);
try{(new Thread((Runnable)applet,"turtle")).start();}
catch(Exception e)
{
e.printStackTrace();
}
}
private static void initColors()
{
colors = new HashMap<String, Color>();
colors.put("aliceblue", new Color(0xf0f8ff));
colors.put("antiquewhite", new Color(0xfaebd7));
colors.put("aqua", new Color(0x00ffff));
colors.put("aquamarine", new Color(0x7fffd4));
colors.put("azure", new Color(0xf0ffff));
colors.put("beige", new Color(0xf5f5dc));
colors.put("bisque", new Color(0xffe4c4));
colors.put("black", new Color(0x000000));
colors.put("blanchedalmond", new Color(0xffebcd));
colors.put("blue", new Color(0x0000ff));
colors.put("blueviolet", new Color(0x8a2be2));
colors.put("brown", new Color(0xa52a2a));
colors.put("burlywood", new Color(0xdeb887));
colors.put("cadetblue", new Color(0x5f9ea0));
colors.put("chartreuse", new Color(0x7fff00));
colors.put("chocolate", new Color(0xd2691e));
colors.put("coral", new Color(0xff7f50));
colors.put("cornflowerblue", new Color(0x6495ed));
colors.put("cornsilk", new Color(0xfff8dc));
colors.put("crimson", new Color(0xdc143c));
colors.put("cyan", new Color(0x00ffff));
colors.put("darkblue", new Color(0x00008b));
colors.put("darkcyan", new Color(0x008b8b));
colors.put("darkgoldenrod", new Color(0xb8860b));
colors.put("darkgray", new Color(0xa9a9a9));
colors.put("darkgreen", new Color(0x006400));
colors.put("darkkhaki", new Color(0xbdb76b));
colors.put("darkmagenta", new Color(0x8b008b));
colors.put("darkolivegreen", new Color(0x556b2f));
colors.put("darkorange", new Color(0xff8c00));
colors.put("darkorchid", new Color(0x9932cc));
colors.put("darkred", new Color(0x8b0000));
colors.put("darksalmon", new Color(0xe9967a));
colors.put("darkseagreen", new Color(0x8fbc8f));
colors.put("darkslateblue", new Color(0x483d8b));
colors.put("darkslategray", new Color(0x2f4f4f));
colors.put("darkturquoise", new Color(0x00ced1));
colors.put("darkviolet", new Color(0x9400d3));
colors.put("deeppink", new Color(0xff1493));
colors.put("deepskyblue", new Color(0x00bfff));
colors.put("dimgray", new Color(0x696969));
colors.put("dodgerblue", new Color(0x1e90ff));
colors.put("firebrick", new Color(0xb22222));
colors.put("floralwhite", new Color(0xfffaf0));
colors.put("forestgreen", new Color(0x228b22));
colors.put("fuchsia", new Color(0xff00ff));
colors.put("gainsboro", new Color(0xdcdcdc));
colors.put("ghostwhite", new Color(0xf8f8ff));
colors.put("gold", new Color(0xffd700));
colors.put("goldenrod", new Color(0xdaa520));
colors.put("gray", new Color(0x808080));
colors.put("green", new Color(0x008000));
colors.put("greenyellow", new Color(0xadff2f));
colors.put("honeydew", new Color(0xf0fff0));
colors.put("hotpink", new Color(0xff69b4));
colors.put("indianred", new Color(0xcd5c5c));
colors.put("indigo", new Color(0x4b0082));
colors.put("ivory", new Color(0xfffff0));
colors.put("khaki", new Color(0xf0e68c));
colors.put("lavender", new Color(0xe6e6fa));
colors.put("lavenderblush", new Color(0xfff0f5));
colors.put("lawngreen", new Color(0x7cfc00));
colors.put("lemonchiffon", new Color(0xfffacd));
colors.put("lightblue", new Color(0xadd8e6));
colors.put("lightcoral", new Color(0xf08080));
colors.put("lightcyan", new Color(0xe0ffff));
colors.put("lightgoldenrodyellow", new Color(0xfafad2));
colors.put("lightgreen", new Color(0x90ee90));
colors.put("lightgrey", new Color(0xd3d3d3));
colors.put("lightpink", new Color(0xffb6c1));
colors.put("lightsalmon", new Color(0xffa07a));
colors.put("lightseagreen", new Color(0x20b2aa));
colors.put("lightskyblue", new Color(0x87cefa));
colors.put("lightslategray", new Color(0x778899));
colors.put("lightsteelblue", new Color(0xb0c4de));
colors.put("lightyellow", new Color(0xffffe0));
colors.put("lime", new Color(0x00ff00));
colors.put("limegreen", new Color(0x32cd32));
colors.put("linen", new Color(0xfaf0e6));
colors.put("magenta", new Color(0xff00ff));
colors.put("maroon", new Color(0x800000));
colors.put("mediumaquamarine", new Color(0x66cdaa));
colors.put("mediumblue", new Color(0x0000cd));
colors.put("mediumorchid", new Color(0xba55d3));
colors.put("mediumpurple", new Color(0x9370db));
colors.put("mediumseagreen", new Color(0x3cb371));
colors.put("mediumslateblue", new Color(0x7b68ee));
colors.put("mediumspringgreen", new Color(0x00fa9a));
colors.put("mediumturquoise", new Color(0x48d1cc));
colors.put("mediumvioletred", new Color(0xc71585));
colors.put("midnightblue", new Color(0x191970));
colors.put("mintcream", new Color(0xf5fffa));
colors.put("mistyrose", new Color(0xffe4e1));
colors.put("moccasin", new Color(0xffe4b5));
colors.put("navajowhite", new Color(0xffdead));
colors.put("navy", new Color(0x000080));
colors.put("oldlace", new Color(0xfdf5e6));
colors.put("olive", new Color(0x808000));
colors.put("olivedrab", new Color(0x6b8e23));
colors.put("orange", new Color(0xffa500));
colors.put("orangered", new Color(0xff4500));
colors.put("orchid", new Color(0xda70d6));
colors.put("palegoldenrod", new Color(0xeee8aa));
colors.put("palegreen", new Color(0x98fb98));
colors.put("paleturquoise", new Color(0xafeeee));
colors.put("palevioletred", new Color(0xdb7093));
colors.put("papayawhip", new Color(0xffefd5));
colors.put("peachpuff", new Color(0xffdab9));
colors.put("peru", new Color(0xcd853f));
colors.put("pink", new Color(0xffc0cb));
colors.put("plum", new Color(0xdda0dd));
colors.put("powderblue", new Color(0xb0e0e6));
colors.put("purple", new Color(0x800080));
colors.put("red", new Color(0xff0000));
colors.put("rosybrown", new Color(0xbc8f8f));
colors.put("royalblue", new Color(0x4169e1));
colors.put("saddlebrown", new Color(0x8b4513));
colors.put("salmon", new Color(0xfa8072));
colors.put("sandybrown", new Color(0xf4a460));
colors.put("seagreen", new Color(0x2e8b57));
colors.put("seashell", new Color(0xfff5ee));
colors.put("sienna", new Color(0xa0522d));
colors.put("silver", new Color(0xc0c0c0));
colors.put("skyblue", new Color(0x87ceeb));
colors.put("slateblue", new Color(0x6a5acd));
colors.put("slategray", new Color(0x708090));
colors.put("snow", new Color(0xfffafa));
colors.put("springgreen", new Color(0x00ff7f));
colors.put("steelblue", new Color(0x4682b4));
colors.put("tan", new Color(0xd2b48c));
colors.put("teal", new Color(0x008080));
colors.put("thistle", new Color(0xd8bfd8));
colors.put("tomato", new Color(0xff6347));
colors.put("turquoise", new Color(0x40e0d0));
colors.put("violet", new Color(0xee82ee));
colors.put("wheat", new Color(0xf5deb3));
colors.put("white", new Color(0xffffff));
colors.put("whitesmoke", new Color(0xf5f5f5));
colors.put("yellow", new Color(0xffff00));
colors.put("yellowgreen", new Color(0x9acd32));
}
private static Color getColor(String color)
{
String origColor=color;
color = color.toLowerCase().replaceAll("[^a-z]", "");
if (colors.containsKey(color))
{
return colors.get(color);
}
else
{
return null;
}
}
private static void setupBuffering()
{
synchronized(turtleLock)
{
lastUpdate=0;
offscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
midscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
onscreenImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
offscreen = offscreenImage.createGraphics();
midscreen = midscreenImage.createGraphics();
onscreen = onscreenImage.createGraphics();
//offscreen.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
//offscreen.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
offscreen.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
midscreen.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
onscreen.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
drawBackground(offscreen);
drawBackground(onscreen);
icon.setImage(onscreenImage);
}
}
private static void drawTurtleIcon()
{
byte[] imageData= new byte[]{71,73,70,56,57,97,16,0,16,0,-95,2,0,0,-103,
0,0,-1,0,-1,-1,-1,-1,-1,-1,33,-7,4,1,10,0,2,0,44,0,0,0,0,16,0,16,0,
0,2,44,-108,-113,-87,-53,-19,-33,-128,4,104,74,35,67,-72,34,-21,11,
124,27,-90,-107,-109,72,117,-91,-71,110,103,-37,90,-31,-10,-55,-87,
122,-34,74,72,-15,17,-56,-127,8,33,5,0,59};
try
{
BufferedImage tmpicon = ImageIO.read(new ByteArrayInputStream(imageData));
window.setIconImage(tmpicon);
}
catch (Exception e) {}
}
private static void makeShapes()
{
shapes=new HashMap<String,Polygon>();
int[] xs=new int[]{66, 65, 63, 61, 53, 44, 33, 24, 23, 19, 17, 14, 9, 8, 8, 10, 13, 11, 10, 2, 9, 11, 15, 11, 11, 10, 12, 18, 20, 22, 23, 26, 35, 44, 53, 61, 62, 64, 66, 71, 77, 78, 77, 76, 72, 77, 81, 86, 91, 94, 97, 98, 97, 95, 92, 87, 82, 77, 72, 74, 77, 78, 76, 70};
int[] ys=new int[]{18, 19, 21, 25, 23, 22, 23, 27, 25, 21, 20, 21, 27, 30, 32, 34, 37, 42, 47, 50, 53, 59, 65, 68, 69, 71, 74, 79, 80, 80, 78, 74, 77, 78, 77, 75, 79, 81, 82, 81, 76, 73, 71, 69, 66, 59, 60, 61, 60, 58, 54, 50, 46, 42, 40, 39, 40, 41, 34, 32, 28, 27, 24, 19};
Polygon p = new Polygon(xs,ys,xs.length);
shapes.put("turtle", p);
xs=new int[]{0,100,0,20};
ys=new int[]{0,50,100,50};
p = new Polygon(xs,ys,xs.length);
shapes.put("arrow", p);
xs=new int[]{0,100,100,0};
ys=new int[]{0,0,100,100};
p = new Polygon(xs,ys,xs.length);
shapes.put("rectangle", p);
shapes.put("square", p);
xs=new int[]{0,100,0};
ys=new int[]{0,50,100};
p = new Polygon(xs,ys,xs.length);
shapes.put("triangle", p);
int divisions=24;
xs=new int[divisions];
ys=new int[divisions];
for(int i=0;i<divisions;i++)
{
double angle=Math.toRadians(i*360.0/divisions);
xs[i]=(int)Math.round(50+50*Math.cos(angle));
ys[i]=(int)Math.round(50+50*Math.sin(angle));
}
p = new Polygon(xs,ys,xs.length);
shapes.put("circle", p);
}
/* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ TURTLE CONSTRUCTION_/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
/**
* This is a internal constuctor that makes a singleton that does the
* listening but is not added to the stack of turtles to be rendered.
* You don't need to use this outside of the Turtle.java file.
*
* @param i Pass this any integer. It doesn't do anything.
*/
private Turtle(int i){}
private Point2D.Double location=new Point2D.Double(0,0);
private double direction=0; //degrees
private String shape="turtle"; //Stores a key to the shapes hashmap
private BufferedImage image=null;
private double shapeWidth=33;
private double shapeHeight=33;
private double tilt=0;
private double penWidth=2;
private Color penColor=Color.BLACK;
private double outlineWidth=2;
private Color outlineColor=Color.BLACK;
private Color fillColor=new Color(0,255,0,128);
private double speed=50; //milliseconds to execute a move
private boolean isPenDown=true;
private boolean isFilling=false;
private boolean isVisible=true;
private ArrayList<Point2D.Double> polygon=new ArrayList<Point2D.Double>();
//temporary storage
private Long _time;
private Point2D.Double _location;
private Double _direction;
private String _shape;
private BufferedImage _image;
private Double _shapeWidth;
private Double _shapeHeight;
private Double _tilt;
private Double _penWidth;
private Color _penColor;
private Double _outlineWidth;
private Color _outlineColor;
private Color _fillColor;
private Double _speed;
private Boolean _isPenDown;
private Boolean _isFilling;
private Boolean _isVisible;
private ArrayList<Point2D.Double> _polygon;
private Boolean _isFill;
private Boolean _isStamp;
private Double _dotSize;
private Color _dotColor;
private Font _font;
private String _text;
private Integer _justification;
private Point2D.Double _textOffset;
//secondary temporary storage
private Long __time;
private Point2D.Double __location;
private Double __direction;
private String __shape;
private BufferedImage __image;
private Double __shapeWidth;
private Double __shapeHeight;
private Double __tilt;
private Double __penWidth;
private Color __penColor;
private Double __outlineWidth;
private Color __outlineColor;
private Color __fillColor;
private Double __speed;
private Boolean __isPenDown;
private Boolean __isFilling;
private Boolean __isVisible;
private ArrayList<Point2D.Double> __polygon;
private Boolean __isFill;
private Boolean __isStamp;
private Double __dotSize;
private Color __dotColor;
private Font __font;
private String __text;
private Integer __justification;
private Point2D.Double __textOffset;
/**
* Makes a default turtle.
*/
public Turtle()
{
if(window==null)init();
synchronized(turtleLock){turtles.add(this);}
long time=storeCurrentState();
updateAll();
}
/**
* Makes a default turtle at the specified position.
*
* @param x x coordinate
* @param y y coordinate
*/
public Turtle(double x,double y)
{
if(window==null)init();
location=new Point2D.Double(x,y);
synchronized(turtleLock){turtles.add(this);}
long time=storeCurrentState();
updateAll();
}
/**
* This creates a cloned copy of a turtle.
*
* @return a cloned copy of a turtle
*/
public Turtle clone()
{
Turtle t=new Turtle(0);
t.location=(Point2D.Double)this.location.clone();
t.direction=this.direction;
t.shape=t.shape;
t.image=this.image;
t.shapeWidth=this.shapeWidth;
t.shapeHeight=this.shapeHeight;
t.tilt=this.tilt;
t.penWidth=this.penWidth;
t.penColor=this.penColor;
t.outlineWidth=this.outlineWidth;
t.outlineColor=this.outlineColor;
t.fillColor=this.fillColor;
t.speed=this.speed;
t.isPenDown=this.isPenDown;
t.isFilling=this.isFilling;
t.isVisible=this.isVisible;
if(window==null)init();
synchronized(turtleLock){turtles.add(t);}
long time=t.storeCurrentState();
return t;
}
/* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ STATE MANAGEMENT _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
private long storeCurrentState()
{
return storeCurrentState(false, false, 0,null,null,null,0,null);
}
private long storeAnimatedState()
{
return storeCurrentState(true, false, 0,null,null,null,0,null);
}
private long storeCurrentState(boolean animate, boolean isStamp,double dotSize,Color dotColor,Font font,String text,int justification,Point2D.Double textOffset)
{
ArrayList state = new ArrayList();
long time=System.nanoTime();
synchronized(turtleLock)
{
state.add(0); //0
state.add(this); //1
state.add(location.clone());//2
state.add(direction); //3
state.add(shape); //4
state.add(image); //5
state.add(shapeWidth); //6
state.add(shapeHeight); //7
state.add(tilt); //8
state.add(penWidth); //9
state.add(penColor); //10
state.add(outlineWidth); //11
state.add(outlineColor); //12
state.add(fillColor); //13
state.add(speed); //14
state.add(isPenDown); //15
state.add(isFilling); //16
state.add(isVisible); //17
state.add(isStamp); //18
state.add(dotSize); //19
state.add(dotColor); //20
state.add(font); //21
state.add(text); //22
state.add(justification); //23
state.add(textOffset); //24
if (!turtleStates.isEmpty() && turtleStates.lastKey()>time) time=turtleStates.lastKey()+1;
if (animate) time+=(long)(speed*1000000);
state.set(0, time);
turtleStates.put(time, state);
redoStates.clear();
}
if(refreshMode==REFRESH_MODE_STATE_CHANGE) draw();
if(refreshMode==REFRESH_MODE_ANIMATED)waitUntil(time);
return time;
}
private static void clearStorage()
{
synchronized(turtleLock)
{
for(Turtle t:turtles)
{
t.__time=null;
t.__location=null;
t.__direction=null;
t.__shape=null;
t.__image=null;
t.__shapeWidth=null;
t.__shapeHeight=null;
t.__tilt=null;
t.__penWidth=null;
t.__penColor=null;
t.__outlineWidth=null;
t.__outlineColor=null;
t.__fillColor=null;
t.__speed=null;
t.__isPenDown=null;
t.__isFilling=null;
t.__isVisible=null;
t.__isStamp=null;
t.__dotSize=null;
t.__dotColor=null;
t.__font=null;
t.__text=null;
t.__justification=null;
t.__textOffset=null;
t._time=null;
t._location=null;
t._direction=null;
t._shape=null;
t._shapeWidth=null;
t._shapeHeight=null;
t._image=null;
t._tilt=null;
t._penWidth=null;
t._penColor=null;
t._outlineWidth=null;
t._outlineColor=null;
t._fillColor=null;
t._speed=null;
t._isPenDown=null;
t._isFilling=null;
t._isVisible=null;
t._isStamp=null;
t._dotSize=null;
t._dotColor=null;
t._font=null;
t._text=null;
t._justification=null;
t._textOffset=null;
}
}
}
private static void retrieveState(long time)
{
synchronized(turtleLock)
{
Turtle t=getStateTurtle(turtleStates.get(time));
t.__time=t._time;
t.__location=t._location;
t.__direction=t._direction;
t.__shape=t._shape;
t.__image=t._image;
t.__shapeWidth=t._shapeWidth;
t.__shapeHeight=t._shapeHeight;
t.__tilt=t._tilt;
t.__penWidth=t._penWidth;
t.__penColor=t._penColor;
t.__outlineWidth=t._outlineWidth;
t.__outlineColor=t._outlineColor;
t.__fillColor=t._fillColor;
t.__speed=t._speed;
t.__isPenDown=t._isPenDown;
t.__isFilling=t._isFilling;
t.__isVisible=t._isVisible;
t.__isStamp=t._isStamp;
t.__dotSize=t._dotSize;
t.__dotColor=t._dotColor;
t.__font=t._font;
t.__text=t._text;
t.__justification=t._justification;
t.__textOffset=t._textOffset;
ArrayList state=turtleStates.get(time);
t._time=getStateTime(state);
t._location=getStateLocation(state);
t._direction=getStateDirection(state);
t._shape=getStateShape(state);
t._shapeWidth=getStateShapeWidth(state);
t._shapeHeight=getStateShapeHeight(state);
t._image=getStateImage(state);
t._tilt=getStateTilt(state);
t._penWidth=getStatePenWidth(state);
t._penColor=getStatePenColor(state);
t._outlineWidth=getStateOutlineWidth(state);
t._outlineColor=getStateOutlineColor(state);
t._fillColor=getStateFillColor(state);
t._speed=getStateSpeed(state);
t._isPenDown=getStateIsPenDown(state);
t._isFilling=getStateIsFilling(state);
t._isVisible=getStateIsVisible(state);
t._isStamp=getStateIsStamp(state);
t._dotSize=getStateDotSize(state);
t._dotColor=getStateDotColor(state);
t._font=getStateFont(state);
t._text=getStateText(state);
t._justification=getStateJustification(state);
t._textOffset=getStateTextOffset(state);
}
}
private static long getStateTime(ArrayList state){return (Long)state.get(0);}
private static Turtle getStateTurtle(ArrayList state){return (Turtle)state.get(1);}
private static Point2D.Double getStateLocation(ArrayList state){return (Point2D.Double)((Point2D.Double)state.get(2)).clone();}
private static double getStateDirection(ArrayList state){return (Double)state.get(3);}
private static String getStateShape(ArrayList state){return (String)state.get(4);}
private static BufferedImage getStateImage(ArrayList state){return (BufferedImage)state.get(5);}
private static double getStateShapeWidth(ArrayList state){return (Double)state.get(6);}
private static double getStateShapeHeight(ArrayList state){return (Double)state.get(7);}
private static double getStateTilt(ArrayList state){return (Double)state.get(8);}
private static double getStatePenWidth(ArrayList state){return (Double)state.get(9);}
private static Color getStatePenColor(ArrayList state){return (Color)state.get(10);}
private static double getStateOutlineWidth(ArrayList state){return (Double)state.get(11);}
private static Color getStateOutlineColor(ArrayList state){return (Color)state.get(12);}
private static Color getStateFillColor(ArrayList state){return (Color)state.get(13);}
private static double getStateSpeed(ArrayList state){return (Double)state.get(14);}
private static boolean getStateIsPenDown(ArrayList state){return (Boolean)state.get(15);}
private static boolean getStateIsFilling(ArrayList state){return (Boolean)state.get(16);}
private static boolean getStateIsVisible(ArrayList state){return (Boolean)state.get(17);}
private static boolean getStateIsStamp(ArrayList state){return (Boolean)state.get(18);}
private static double getStateDotSize(ArrayList state){return (Double)state.get(19);}
private static Color getStateDotColor(ArrayList state){return (Color)state.get(20);}
private static Font getStateFont(ArrayList state){return (Font)state.get(21);}
private static String getStateText(ArrayList state){return (String)state.get(22);}
private static int getStateJustification(ArrayList state){return (Integer)state.get(23);}
private static Point2D.Double getStateTextOffset(ArrayList state){return (Point2D.Double)state.get(24);}
private static void restoreState(long time)
{
ArrayList state=turtleStates.get(time);
Turtle t=getStateTurtle(turtleStates.get(time));
t.location=getStateLocation(state);
t.direction=getStateDirection(state);
t.shape=getStateShape(state);
t.shapeWidth=getStateShapeWidth(state);
t.shapeHeight=getStateShapeHeight(state);
t.image=getStateImage(state);
t.tilt=getStateTilt(state);
t.penWidth=getStatePenWidth(state);
t.penColor=getStatePenColor(state);
t.outlineWidth=getStateOutlineWidth(state);
t.outlineColor=getStateOutlineColor(state);
t.fillColor=getStateFillColor(state);
t.speed=getStateSpeed(state);
t.isPenDown=getStateIsPenDown(state);
t.isFilling=getStateIsFilling(state);
t.isVisible=getStateIsVisible(state);
if(refreshMode==REFRESH_MODE_STATE_CHANGE) draw();
}
private void select()
{
selectedTurtle=this;
}
private void unselect()
{
if (selectedTurtle==this) selectedTurtle=null;
}
/**
* Determines if a turtle is covering a screen position
*
* @param x x screen coordinate
* @param y y screen coordinate
* @return true if this turtle is at the indicated screen position.
*/
public boolean contains(int x, int y)
{
Point2D.Double point=new Point2D.Double(x,y);
if (_location==null)return false;
AffineTransform m = offscreen.getTransform();
double x1,y1,dir1;
x1=_location.x;
y1=_location.y;
dir1=_direction;
m.translate(((x1-centerX)*scale+width/2),((y1-centerY)*(-scale)+height/2));
m.scale(scale, scale);
if (image==null)
{
m.rotate(-Math.toRadians(dir1));
m.scale(shapeWidth/100.0, shapeHeight/100.0);
m.translate(-50,-50);
Polygon p =shapes.get(shape);
GeneralPath gp=new GeneralPath();
gp.append(p.getPathIterator(m),false);
return gp.contains(x, y);
}
else
{
int w=image.getWidth();
int h=image.getHeight();
m.rotate(-Math.toRadians(dir1));
m.scale(shapeWidth/1.0/w, shapeHeight/1.0/h);
m.translate(-w/2,-h/2);
try {m.inverseTransform(point, point);}
catch(Exception e){return false;}
x=(int)point.x;
y=(int)point.y;
try
{
//System.out.println((new Color(image.getRGB(x, y),true)).getAlpha());
return (new Color(image.getRGB(x, y),true)).getAlpha()>50;
}
catch(Exception e){return false;}
}
}
/* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ TURTLE METHODS _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U
* .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*) .-./*)
* _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/ _/___\/
* U U U U U U U U U U U U U U U U
*/
/**
* Gets the speed of the animation.
* @return milliseconds it takes to do one action
*/
public double getSpeed()
{
return speed;
}
/**
* Sets the speed of the animation.
* @param delay milliseconds it takes to do one action
* @return state change timestamp
*/
public long speed(double delay)
{
this.speed=delay;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Moves the turtle forward by the distance.
*
* @param distance distance to move forward
* @return state change timestamp
*/
public long forward(double distance)
{
double angle=Math.toRadians(direction);
Point2D.Double pastLocation=(Point2D.Double)location.clone();
location.x+=distance*Math.cos(angle);
location.y+=distance*Math.sin(angle);
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Moves the turtle backward by the distance.
*
* @param distance distance to move backward
* @return state change timestamp
*/
public long backward(double distance)
{
double angle=Math.toRadians(direction);
Point2D.Double pastLocation=(Point2D.Double)location.clone();
location.x-=distance*Math.cos(angle);
location.y-=distance*Math.sin(angle);
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Turns the turtle left by the number of indicated degrees.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public long left(double angle)
{
direction+=angle;
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Turns the turtle right by the number of indicated degrees.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public long right(double angle)
{
direction-=angle;
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Gets the direction the turtle is facing neglecting tilt.
*
* @return state change timestamp
*/
public double getDirection()
{
double a=direction;
while(a>=360)a-=360;
while(a<0)a+=360;
return a;
}
/**
* Sets the direction the turtle is facing neglecting tilt.
*
* @param direction angle counter-clockwise from east
* @return state change timestamp
*/
public long setDirection(double direction)
{
double a=direction;
while(this.direction-a>180)a+=360;
while(this.direction-a<-180)a-=360;
this.direction=a;
//this.direction=direction;
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Moves the turtle to (0,0) and facing east.
*
* @return state change timestamp
*/
public long home()
{
return setPosition(0,0,0);
}
/**
* Hides the turtle but it can still draw.
*
* @return state change timestamp
*/
public long hide()
{
isVisible=false;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Makes the turtle visible.
*
* @return state change timestamp
*/
public long show()
{
isVisible=true;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the direction in such a way that it faces (x,y)
*
* @param x x coordinate of target location
* @param y y coordinate of target location
* @return state change timestamp
*/
public long face(double x, double y)
{
return setDirection(towards(x,y));
}
/**
* Gets direction towards (x,y)
*
* @param x x coordinate of target location
* @param y y coordinate of target location
* @return angle in degrees where 0<=angle<360
*/
public double towards(double x, double y)
{
return Math.toDegrees(Math.atan2(y-location.y, x-location.x));
}
/**
* Gets the distance to another position.
*
* @param x x coordinate of target location
* @param y y coordinate of target location
* @return distance between turtle's current location and another position
*/
public double distance(double x, double y)
{
return Math.sqrt((y-location.y)*(y-location.y)+(x-location.x)*(x-location.x));
}
/**
* Gets the x coordinate of the turtle.
*
* @return x coordinate
*/
public double getX()
{
return location.x;
}
/**
* Gets the y coordinate of the turtle.
*
* @return y coordinate
*/
public double getY()
{
return location.y;
}
/**
* Sets the position and direction of a turtle.
*
* @param x x coordinate
* @param y y coordinate
* @param direction angle counter-clockwise from east in degrees
* @return state change timestamp
*/
public long setPosition(double x, double y, double direction)
{
location.x=x;
location.y=y;
double a=direction;
while(this.direction-a>180)a+=360;
while(this.direction-a<-180)a-=360;
this.direction=a;
this.direction=direction;
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Sets the position of a turtle.
*
* @param x x coordinate
* @param y y coordinate
* @return state change timestamp
*/
public long setPosition(double x, double y)
{
return setPosition(x, y, direction);
}
/**
* Adds an additional angle to rotation of the turtle's shape when rendering.
* This is useful when you need to face a different direction than the
* direction you are moving in.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public long tilt(double angle)
{
tilt+=angle;
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Sets the angle to rotate the turtle's shape when rendering.
* This is useful when you need to face a different direction than the
* direction you are moving in.
*
* @param angle angle in degrees
* @return state change timestamp
*/
public long setTilt(double angle)
{
//double a=angle;
//while(tilt-a>180)a+=360;
//while(tilt-a<-180)a-=360;
//tilt=a;
tilt=angle;
long timeStamp=storeAnimatedState();
return timeStamp;
}
/**
* Gets the rotation of the turtle's shape away from the turtle's direction.
*
* @return tilt in degrees (positive in counter-clockwise)
*/
public double getTilt()
{
return tilt;
}
/**
* Sets the width of the turtles path
*
* @param penWidth width of the turtles path
* @return state change timestamp
*/
public long width(double penWidth)
{
this.penWidth=penWidth;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the width of the turtle's outline.
*
* @param width width of the turtle's outline
* @return state change timestamp
*/
public long outlineWidth(double width)
{
this.outlineWidth=width;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Picks the turtle's tail up so it won't draw on the screen as it moves.
*
* @return state change timestamp
*/
public long up()
{
this.isPenDown=false;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Puts the turtle's tail down so it will draw on the screen as it moves.
*
* @return state change timestamp
*/
public long down()
{
this.isPenDown=true;
long timeStamp=storeCurrentState();
return timeStamp;
}
public long stab()
{
Color c=Turtle.getColor("red");
if(c!=null)this.penColor=c;
this.isPenDown=true;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the turtle's path color.
*
* @param penColor Color of the turtle's path.
* @return state change timestamp
*/
public long penColor(String penColor)
{
Color c=Turtle.getColor(penColor);
if(c!=null)this.penColor=c;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the turtle's path color.
*
* @param penColor Color of the turtle's path.
* @return state change timestamp
*/
public long penColor(Color penColor)
{
this.penColor=penColor;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the turtle's outlineColor color.
*
* @param outlineColor Color of the turtle's outlineColor.
* @return state change timestamp
*/
public long outlineColor(String outlineColor)
{
Color c=Turtle.getColor(outlineColor);
if(c!=null)this.outlineColor=c;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the turtle's outlineColor color.
*
* @param outlineColor Color of the turtle's outlineColor.
* @return state change timestamp
*/
public long outlineColor(Color outlineColor)
{
this.outlineColor=outlineColor;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the turtle's fill color.
*
* @param fillColor Color of the turtle's fill.
* @return state change timestamp
*/
public long fillColor(String fillColor)
{
Color c=Turtle.getColor(fillColor);
if(c!=null)this.fillColor=c;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the turtle's fill color.
*
* @param fillColor Color of the turtle's fill.
* @return state change timestamp
*/
public long fillColor(Color fillColor)
{
this.fillColor=fillColor;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Sets the shape of the turtle using the built in shapes (turtle,square,
* rectangle,triangle,arrow,circle) or to a image.
*
* @param shape shapename or filename of image
* @return state change timestamp
*/
public long shape(String shape)
{
try
{
image=ImageIO.read(new File(shape));
this.shapeHeight=image.getHeight();
this.shapeWidth=image.getWidth();
}
catch(Exception e)
{
if(shapes.containsKey(shape))
{
this.shape=shape;
this.shapeHeight=33;
this.shapeWidth=33;
image=null;
}
else {System.out.println("Unrecognized filename or shape name.");}
}
//if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
long timeStamp=storeCurrentState();
return timeStamp;
}
public long shapeSize(int width, int height)
{
this.shapeHeight=height;
this.shapeWidth=width;
long timeStamp=storeCurrentState();
return timeStamp;
}
/**
* Put a copy of the current turtle shape on the canvas.
*
* @return state change timestamp
*/
public long stamp()
{
long timeStamp=storeCurrentState(true, true,0,null,null,null,0,null);
return timeStamp;
}
/**
* Put a dot 3 times the size of the penWidth on the canvas.
*
* @return state change timestamp
*/
public long dot()
{
long timeStamp=storeCurrentState(true, false,penWidth*3,penColor,null,null,0,null);
return timeStamp;
}
/**
* Put a dot 3 times the size of the penWidth on the canvas.
*
* @param color color of dot
* @return state change timestamp
*/
public long dot(String color)
{
Color c=Turtle.getColor(color);
if(c==null)c=penColor;
long timeStamp=storeCurrentState(true, false,penWidth*3,c,null,null,0,null);
return timeStamp;
}
/**
* Put a dot 3 times the size of the penWidth on the canvas.
*
* @param color color of dot
* @return state change timestamp
*/
public long dot(Color color)
{
long timeStamp=storeCurrentState(true, false,penWidth*3,color,null,null,0,null);
return timeStamp;
}
/**
* Put a dot on the canvas.
*
* @param color color of dot
* @param dotSize diameter of the dot
* @return state change timestamp
*/
public long dot(String color,double dotSize)
{
Color c=Turtle.getColor(color);
if(c==null)c=penColor;
long timeStamp=storeCurrentState(true, false,dotSize,c,null,null,0,null);
return timeStamp;
}
/**
* Put a dot on the canvas.
*
* @param color color of dot
* @param dotSize diameter of the dot
* @return state change timestamp
*/
public long dot(Color color,double dotSize)
{
long timeStamp=storeCurrentState(true, false,dotSize,color,null,null,0,null);
return timeStamp;
}
public long write(String text, String fontName, int fontSize, int justification, double xOffset, double yOffset)
{
return 0;
}
/**
* Undo turtle state changes.
*
* @param steps the number of state changes to remove
*/
public void undo(int steps)
{
for(int i=0;i<steps;i++) rollback();
lastUpdate=0;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
/**
* Undo the last turtle state change.
*/
public void undo()
{
rollback();
lastUpdate=0;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
/**
* Redo turtle state changes.
*
* @param steps the number of state changes to restore
*/
public void redo(int steps)
{
for(int i=0;i<steps;i++) rollforward();
lastUpdate=0;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
/**
* Redo turtle state changes.
*/
public void redo()
{
rollforward();
lastUpdate=0;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
/**
* Clears all the drawing that a turtle has done but all the turtle
* settings remain the same. (color, location, direction, shape)
*/
public void clear()
{
synchronized(turtleLock)
{
long removeKey=0;
TreeMap<Long, ArrayList> copy_turtleStates=(TreeMap<Long, ArrayList>)turtleStates.clone();
for (Map.Entry<Long, ArrayList> entry:copy_turtleStates.entrySet())
{
ArrayList state=entry.getValue();
long time=entry.getKey();
if(getStateTurtle(state)==this)
{
if(removeKey!=0)
{
turtleStates.remove(removeKey);
}
removeKey=time;
}
}
redoStates.clear();
restoreState(removeKey);
}
lastUpdate=0;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
private void rollback()
{
int steps=0;
synchronized(turtleLock)
{
long removeKey=0;
long restoreTime=0;
for (Map.Entry<Long, ArrayList> entry:turtleStates.descendingMap().entrySet())
{
ArrayList state=entry.getValue();
long time=entry.getKey();
if(getStateTurtle(state)==this)
{
if (steps==0)
{
removeKey=time;
steps+=1;
}
else
{
restoreTime=time;
break;
}
}
}
if (removeKey!=0 && restoreTime!=0)
{
restoreState(restoreTime);
redoStates.put(removeKey, turtleStates.remove(removeKey));
}
}
}
private void rollforward()
{
synchronized(turtleLock)
{
for (Map.Entry<Long, ArrayList> entry:redoStates.entrySet())
{
ArrayList state=entry.getValue();
long time=entry.getKey();
if(getStateTurtle(state)==this)
{
turtleStates.put(entry.getKey(), redoStates.remove(entry.getKey()));
restoreState(time);
return;
}
}
}
}
/**
* This specifies when the screen gets refreshed.
* 0(default)=Animated (The turtle will slide from one state to another without being jerky.)
* 1=State Change (The turtle will refresh immediately to the last state. Jerky motion.)
* 2=On Demand (The turtle will refresh only when you call update())
*
* @param mode refresh mode
*/
public static void refreshMode(int mode)
{
refreshMode=mode;
updateAll();
}
/**
* This specifies how the background is drawn.
* 0=The image if present is stretched to fill the screen.
* 1=The image is centered on the middle of the screen and will not scale/pan
* 2=The image is tiled and will not scale/pan
* 3=The image is centered on (0,0) and will scale/pan
* 4(default)=The image is tiled and will scale/pan
*
* @param mode background mode
*/
public static void backgroundMode(int mode)
{
backgroundMode=mode;
updateAll();
}
/**
* Sets the background color.
*
* @param color Color of the background.
*/
public static void bgcolor(String color)
{
Color c=Turtle.getColor(color);
if(c!=null)backgroundColor=c;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
/**
* Sets the background color.
*
* @param color Color of the background.
*/
public static void bgcolor(Color color)
{
backgroundColor=color;
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
/**
* Set the background image.
*
* @param filename filename for a background image
*/
public static void bgpic(String filename)
{
try{backgroundImage=ImageIO.read(new File(filename));}
catch(Exception e){e.printStackTrace();}
if(refreshMode!=REFRESH_MODE_ON_DEMAND)updateAll();
}
private static boolean addMouseBinding(String methodName,Turtle t,boolean append,boolean click, boolean repeat)
{
String className="";
try
{
throw new Exception("Who called me?");
}
catch( Exception e )
{
className=e.getStackTrace()[2].getClassName();
}
try
{
boolean works=false;
for(Method m : Class.forName(className).getDeclaredMethods())
{
if (m.getName().equals(methodName))
{
//System.out.println(m);
works=true;
for(Class paramType : m.getParameterTypes())
{
//System.out.println(paramType.getName());
if (!paramType.getName().equals("double") && !paramType.getName().equals("java.lang.Double") && !paramType.getName().equals("Turtle"))
{
works=false;
break;
}
}
if (works) break;
}
}
if(works)
{
//System.out.println("Method found!");
}
else
{
System.out.println("ERROR");
return false;
}
}
catch(Exception e)
{
System.out.println("Calling Class not found.");
return false;
}
if(!append || !mouseBindings.containsKey(t)) mouseBindings.put(t,new ArrayList<ArrayList>());
ArrayList binding=new ArrayList();
binding.add(t);
binding.add(className);
binding.add(methodName);
binding.add(click);
binding.add(repeat);
mouseBindings.get(t).add(binding);
return true;
}
private boolean addKeyBinding(String methodName,String keyText,boolean append,boolean repeat)
{
keyText=keyText.toLowerCase();
String className="";
try
{
throw new Exception("Who called me?");
}
catch( Exception e )
{
className=e.getStackTrace()[2].getClassName();
}
try
{
boolean works=false;
for(Method m : Class.forName(className).getDeclaredMethods())
{
if (m.getName().equals(methodName))
{
//System.out.println(m);
works=true;
for(Class paramType : m.getParameterTypes())
{
//System.out.println(paramType.getName());
if (!paramType.getName().equals("java.lang.String") && !paramType.getName().equals("Turtle"))
{
works=false;
break;
}
}
if (works) break;
}
}
if(works)
{
//System.out.println("Method found!");
}
else
{
System.out.println("ERROR");
return false;
}
}
catch(Exception e)
{
System.out.println("Calling Class not found.");
return false;
}
if(!append || !keyBindings.containsKey(keyText)) keyBindings.put(keyText,new ArrayList<ArrayList>());
ArrayList binding=new ArrayList();
binding.add(this);
binding.add(className);
binding.add(methodName);
binding.add(repeat);
keyBindings.get(keyText).add(binding);
return true;
}
/**
* Links a method to a key.
*
* @param methodName method to be executed when the key is pressed
* @param keyText key that triggers the method
* @return
*/
public boolean onKey(String methodName,String keyText)
{
return addKeyBinding(methodName,keyText,false,false);
}
/**
* Links a method to a key.
*
* @param methodName method to be executed when the key is pressed
* @param keyText key that triggers the method
* @param append true if you want to have multiple methods per key
* @return
*/
public boolean onKey(String methodName,String keyText,boolean append)
{
return addKeyBinding(methodName,keyText,append,false);
}
/**
* Links a method to a key.
*
* @param methodName method to be executed when the key is pressed
* @param keyText key that triggers the method
* @param append true if you want to have multiple methods per key
* @param repeat true if you want call the method every screen refresh
* @return
*/
public boolean onKey(String methodName,String keyText,boolean append,boolean repeat)
{
return addKeyBinding(methodName,keyText,append,repeat);
}
/**
*
* Fits the indicated box in the center of the screen as large as possible.
*
* @param minx left x coordinate of box
* @param miny bottom y coordinate of box
* @param maxx right x coordinate of box
* @param maxy top y coordinate of box
*/
public static void zoom(double minx, double miny, double maxx, double maxy)
{
synchronized(turtleLock)
{
centerX=(minx+maxx)/2;
centerY=(miny+maxy)/2;
if (width/(maxx-minx)>height/(maxy-miny)) scale=height/(maxy-miny);
else scale=width/(maxx-minx);
updateAll();
}
}
/**
* Fits everything on the screen.
*/
public static void zoomFit()
{
synchronized(turtleLock)
{
Point2D.Double loc;
if (turtleStates.isEmpty())return;
else loc=getStateLocation(turtleStates.firstEntry().getValue());
double minx=loc.x, miny=loc.y;
double maxx=minx, maxy=miny;
double shapeWidth=0;
double shapeHeight=0;
long time=System.nanoTime();
if(refreshMode!=REFRESH_MODE_ANIMATED)time=turtleStates.lastKey()+1;
for (Map.Entry<Long, ArrayList> entry : turtleStates.headMap(time).entrySet())
{
ArrayList state=entry.getValue();
if(!getStateIsPenDown(state))continue;
Point2D.Double location =getStateLocation(state);
if (location.x<minx) minx=location.x;
if (location.x>maxx) maxx=location.x;
if (location.y<miny) miny=location.y;
if (location.y>maxy) maxy=location.y;
shapeWidth=getStateShapeWidth(state);
shapeHeight=getStateShapeHeight(state);
}
if(turtleStates.lastKey()>time && getStateSpeed(turtleStates.lastEntry().getValue())>0)
{
double percent = 1 - (turtleStates.lastKey() - time) / getStateSpeed(turtleStates.lastEntry().getValue()) / 1000000.0;
//System.out.println("trying");
Turtle t=getStateTurtle(turtleStates.lastEntry().getValue());
double x1=t._location.x,y1=t._location.y,x2=t.__location.x,y2=t.__location.y;
x1=(x2-x1)*percent+x1;
y1=(y2-y1)*percent+y1;
if (x1<minx) minx=x1;
if (x1>maxx) maxx=x1;
if (y1<miny) miny=y1;
if (y1>maxy) maxy=y1;
}
double shapeMax=Math.max(shapeWidth, shapeHeight);
zoom(minx-shapeMax/2, miny-shapeMax/2, maxx+shapeMax/2, maxy+shapeMax/2);
}
}
private static void updateAll()
{
lastUpdate=0;
draw();
}
/**
* Force redraw when the refreshMode is set to on demand.
*/
public static void update()
{
if(refreshMode==REFRESH_MODE_ON_DEMAND) draw();
}
private static void draw()
{
synchronized(turtleLock)
{
long renderTime=System.nanoTime();
if (turtleStates.isEmpty() || lastUpdate==0)
{
clearStorage();
drawBackground(offscreen);
}
if(turtleStates.isEmpty())
{
onscreen.drawImage(offscreenImage,0,0, null);
window.repaint();
if(applet!=null)applet.repaint();
return;
}
if(refreshMode!=REFRESH_MODE_ANIMATED)renderTime=turtleStates.lastKey()+1;
if (lastUpdate>turtleStates.lastKey())
{
midscreen.drawImage(offscreenImage,0,0, null);
for(Turtle t:turtles)
{
if(t.isVisible) t.drawStamp(1, midscreen);
//if(t==selectedTurtle)t.drawCrossHairs(1,midscreen);
}
onscreen.drawImage(midscreenImage,0,0, null);
window.repaint();
if(applet!=null)applet.repaint();
return;
}
for (Map.Entry<Long, ArrayList> entry : turtleStates.tailMap(lastUpdate).headMap(renderTime).entrySet())
{
retrieveState(entry.getKey());
Turtle t=getStateTurtle(entry.getValue());
t.drawLine(1,offscreen);
if(t._isStamp)t.drawStamp(1, offscreen);
t.drawDot(1, offscreen);
}
midscreen.drawImage(offscreenImage,0,0, null);
Turtle animatedTurtle=null;
double percent=1;
Long t2;
t2=new Long(0);
if (renderTime<turtleStates.lastKey())
{
animatedTurtle=getStateTurtle(turtleStates.ceilingEntry(renderTime).getValue());
t2=animatedTurtle._time;
retrieveState(turtleStates.ceilingKey(renderTime));
if(animatedTurtle._speed>0)
{
percent = 1 - (turtleStates.ceilingKey(renderTime) - renderTime) / animatedTurtle._speed / 1000000.0;
}
else percent=1;
if (percent<0)percent=0;
}
for(Turtle t:turtles)
{
if(t==animatedTurtle)
{
//System.out.println(percent);
t.drawLine(percent, midscreen);
if(t._dotSize>0)t.drawDot(percent, midscreen);
if(t.isVisible)t.drawStamp(percent, midscreen,false);
if(t._isStamp)t.drawStamp(percent, midscreen,true);
//if(t==selectedTurtle)t.drawCrossHairs(percent,midscreen);
try{retrieveState(t2);}
catch(Exception e){}
}
else
{
if(t.isVisible)t.drawStamp(1, midscreen);
//if(t==selectedTurtle)t.drawCrossHairs(1,midscreen);
}
}
lastUpdate=renderTime;
//zoomFit();
onscreen.drawImage(midscreenImage,0,0, null);
window.repaint();
if(applet!=null)applet.repaint();
}
}
private void drawLine(double percent,Graphics2D g)
{
if(!_isPenDown) return;
g.setColor(_penColor);
g.setStroke(new BasicStroke((float)(scale*_penWidth),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
if(__location!=null && !__location.equals(_location))
{
double x1=_location.x,y1=_location.y,x2=__location.x,y2=__location.y;
if(percent<1 && percent>=0)
{
x1=(x1-x2)*percent+x2;
y1=(y1-y2)*percent+y2;
}
//g.draw(new Line2D.Double((x1-centerX)*scale+width/2, (y1-centerY)*(-scale)+height/2, (x2-centerX)*scale+width/2, (y2-centerY)*(-scale)+height/2));
g.drawLine((int)((x1-centerX)*scale+width/2), (int)((y1-centerY)*(-scale)+height/2), (int)((x2-centerX)*scale+width/2), (int)((y2-centerY)*(-scale)+height/2));
}
}
private void drawStamp(double percent,Graphics2D g)
{
drawStamp(percent,g,false);
}
private void drawStamp(double percent,Graphics2D g,boolean isStamp)
{
if (_location==null)return;
AffineTransform originalTransform=(AffineTransform)g.getTransform().clone();
AffineTransform m = g.getTransform();
double x1,x2,y1,y2,dir1,dir2,tilt1,tilt2;
x1=_location.x;
y1=_location.y;
dir1=_direction;
tilt1=_tilt;
if(__location==null)
{
x2=x1;
y2=y1;
dir2=dir1;
tilt2=tilt1;
}
else
{
x2=__location.x;
y2=__location.y;
dir2=__direction;
tilt2=__tilt;
}
if(percent<1 && percent>=0)
{
x1=(x1-x2)*percent+x2;
y1=(y1-y2)*percent+y2;
dir1=(dir1-dir2)*percent+dir2;
tilt1=(tilt1-tilt2)*percent+tilt2;
}
m.translate(((x1-centerX)*scale+width/2),((y1-centerY)*(-scale)+height/2));
if(isStamp)m.scale(scale*percent, scale*percent);
else m.scale(scale, scale);
if (_image==null)
{
//_outlineWidth=0.0;
m.rotate(-Math.toRadians(dir1+tilt1));
m.scale(_shapeWidth/100.0, _shapeHeight/100.0);
m.translate(-50,-50);
g.setTransform(m);
Polygon p =shapes.get(_shape);
g.setColor(_fillColor);
g.fillPolygon(p);
g.setColor(_outlineColor);
if(_outlineWidth>0)
{
g.setStroke(new BasicStroke((float)(_outlineWidth*scale),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
g.setTransform(originalTransform);
GeneralPath gp=new GeneralPath();
gp.append(p.getPathIterator(m),false);
g.draw(gp);
}
}
else
{
int w=_image.getWidth();
int h=_image.getHeight();
m.rotate(-Math.toRadians(dir1+tilt1));
m.scale(_shapeWidth/1.0/w, _shapeHeight/1.0/h);
m.translate(-w/2,-h/2);
g.setTransform(m);
g.drawImage(_image,0,0,null);
}
g.setTransform(originalTransform);
}
private void drawDot(double percent,Graphics2D g)
{
AffineTransform originalTransform=(AffineTransform)g.getTransform().clone();
AffineTransform m = g.getTransform();
m.translate(((_location.x-centerX)*scale+width/2),((_location.y-centerY)*(-scale)+height/2));
m.scale(scale*percent/2, scale*percent/2);
g.setTransform(m);
g.setColor(_dotColor);
int r=(int)(_dotSize*1.0);
g.fillOval(-r, -r, 2*r, 2*r);
g.setTransform(originalTransform);
}
private static void drawBackground(Graphics2D g)
{
g.setColor(backgroundColor);
g.fillRect(0, 0, width, height);
if(backgroundImage==null) return;
int w=backgroundImage.getWidth();
int h=backgroundImage.getHeight();
if(backgroundMode==BACKGROUND_MODE_CENTER)
{
offscreen.drawImage(backgroundImage, (width-w)/2, (height-h)/2, w, h, null);
}
else if(backgroundMode==BACKGROUND_MODE_STRETCH)
{
offscreen.drawImage(backgroundImage, 0, 0, width, height, null);
}
else if(backgroundMode==BACKGROUND_MODE_CENTER_RELATIVE)
{
offscreen.drawImage(backgroundImage, (int)((-w/2-centerX)*scale+width/2),(int)((h/2-centerY)*(-scale)+height/2), (int)(w*scale), (int)(h*scale), null);
}
else if(backgroundMode==BACKGROUND_MODE_TILE)
{
for(int i=0;i<width;i+=w) for(int j=0;j<height;j+=h) offscreen.drawImage(backgroundImage, i,j, w, h, null);
}
else if(backgroundMode==BACKGROUND_MODE_TILE_RELATIVE)
{
double left=centerX-width/2/scale;
double top=centerY+height/2/scale;
double right=centerX+width/2/scale;
double bottom=centerY-height/2/scale;
for(double x=((int)(left/w)-1)*w;x<=right;x+=w) for(double y=((int)(bottom/h))*h;y<=top+h;y+=h) offscreen.drawImage(backgroundImage, (int)((x-centerX)*scale+width/2),(int)((y-centerY)*(-scale)+height/2), (int)Math.ceil(w*scale), (int)Math.ceil(h*scale), null);
}
}
private void drawCrossHairs(double percent, Graphics2D g)
{
if(_location==null)return;
double time=(System.nanoTime()/100000000)/10.0;
AffineTransform originalTransform=(AffineTransform)g.getTransform().clone();
AffineTransform m = g.getTransform();
double x1,x2,y1,y2,dir1,dir2;
x1=_location.x;
y1=_location.y;
if(__location==null)
{
x2=x1;
y2=y1;
}
else
{
x2=__location.x;
y2=__location.y;
}
if(percent<1 && percent>=0)
{
x1=(x1-x2)*percent+x2;
y1=(y1-y2)*percent+y2;
}
m.translate(((x1-centerX)*scale+width/2),((y1-centerY)*(-scale)+height/2));
int f=10;
m.scale(scale/f, scale/f);
g.setTransform(m);
int period=50;
int r=(int)(Math.sqrt(shapeWidth*shapeWidth+shapeHeight*shapeHeight)*f/2);
g.setColor(new Color(255,255,255));
g.setStroke(new BasicStroke((float)(6*f),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
g.drawOval(-r, -r, 2*r, 2*r);
r+=f;
for(int i=0;i<4;i++) g.drawLine((int)(r*Math.cos(Math.PI/2*i+2*Math.PI*time/period)),(int)(r*Math.sin(Math.PI/2*i+2*Math.PI*time/period)),
(int)((r+r/5)*Math.cos(Math.PI/2*i+2*Math.PI*time/period)),(int)((r+r/5)*Math.sin(Math.PI/2*i+2*Math.PI*time/period)));
r-=f;
g.setColor(new Color(0,0,0));
g.setStroke(new BasicStroke((float)(3*f),BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
g.drawOval(-r, -r, 2*r, 2*r);
r+=f;
for(int i=0;i<4;i++) g.drawLine((int)(r*Math.cos(Math.PI/2*i+2*Math.PI*time/period)),(int)(r*Math.sin(Math.PI/2*i+2*Math.PI*time/period)),
(int)((r+r/5)*Math.cos(Math.PI/2*i+2*Math.PI*time/period)),(int)((r+r/5)*Math.sin(Math.PI/2*i+2*Math.PI*time/period)));
g.setTransform(originalTransform);
}
/**
* Changes the size of the canvas effectively changing the size of the window.
*
* @param width width of the canvas
* @param height height of the canvas
*/
public static void setCanvasSize(int width,int height)
{
Turtle.width=width;
Turtle.height=height;
Turtle.setupBuffering();
window.pack();
updateAll();
}
/**
* Saves the visible canvas to an image.
*
* @param filename image filename
*/
public static void save(String filename)
{
save(new File(filename));
}
private static void save(File file)
{
WritableRaster raster = onscreenImage.getRaster();
WritableRaster newRaster;
newRaster = raster.createWritableChild(0, 0, width, height, 0, 0, new int[] {0, 1, 2});
DirectColorModel cm = (DirectColorModel) onscreenImage.getColorModel();
DirectColorModel newCM = new DirectColorModel(cm.getPixelSize(),
cm.getRedMask(),
cm.getGreenMask(),
cm.getBlueMask());
BufferedImage rgbBuffer = new BufferedImage(newCM, newRaster, false, null);
try
{
String suffix = file.getName().substring(file.getName().lastIndexOf('.') + 1);
if (!ImageIO.write(rgbBuffer, suffix,file)) throw new Exception("Didn't save file.");
}
catch(Exception e)
{
file.delete();
JOptionPane.showMessageDialog(window,
"Sorry! We can not process your request at this time.",
"Image Save Failed",
JOptionPane.ERROR_MESSAGE);
}
}
/**
* Demo program
*
* @param a commandline args
*/
public static void main(String[] a)
{
//Turtle bob = new Turtle();
/*for(int i=0;i<360;i++)
{
bob.forward(i*1.25);
bob.left(90.25);
}
*/
/*If you don't know what a for loop is yet this is equivalent to repeating the middle 4 lines 5 times in a row.*/
Turtle bob = new Turtle();
bgcolor("lightblue");
bob.penColor("red");
bob.width(10);
for(int i=0;i<200;i++)
{
bob.forward(i/10.);
bob.left(5);
if(i%10==0)bob.dot("orange");//Draws dots when i is a multiple of 10.
}
bob.saveGCODE("test.gcode");
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void actionPerformed(ActionEvent e)
{
if(((JMenuItem)e.getSource()).getText().equals("Save..."))
{
JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
chooser.setFileFilter(new FileNameExtensionFilter("Image (*.jpg, *.jpeg, *.gif, *.bmp, *.png)", "jpg", "png", "jpeg", "bmp", "gif"));
int option = chooser.showSaveDialog(window);
if(option == JFileChooser.APPROVE_OPTION)
{
if(chooser.getSelectedFile()!=null)
{
File file = chooser.getSelectedFile();
save(file);
}
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseClicked(MouseEvent e)
{
if(e.getModifiers()==8 && e.getClickCount()==2)
{
centerX=0;
centerY=0;
scale=1;
updateAll();
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseEntered(MouseEvent e) {}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseExited(MouseEvent e) {}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mousePressed(MouseEvent e)
{
dragx=e.getX();
dragy=e.getY();
modifiers+=e.getModifiers();
synchronized (turtleLock)
{
for(Turtle t:turtles)
{
if(t.contains(dragx,dragy))t.select();
else t.unselect();
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseReleased(MouseEvent e)
{
modifiers-=e.getModifiers();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseDragged(MouseEvent e)
{
modifiers=e.getModifiers();
int dx,dy;
if (e.getModifiers()==8)
{
x=e.getX();
dx=x-dragx;
y=e.getY();
dy=y-dragy;
dragx=x;
dragy=y;
synchronized(turtleLock)
{
centerX-=dx*1.0/scale;
centerY+=dy*1.0/scale;
}
updateAll();
}
this.x=e.getX();
this.y=e.getY();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseMoved(MouseEvent e)
{
modifiers=e.getModifiers();
x=e.getX();
y=e.getY();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void keyTyped(KeyEvent e) {}
/**
* Internal mehod for handling events.
* @param e event
*/
public void keyPressed(KeyEvent e)
{
String keyText=KeyEvent.getKeyText(e.getKeyCode()).toLowerCase();
synchronized (keyLock)
{
keysDown.add(keyText);
if (keyBindings.containsKey(keyText))
{
unprocessedKeys.add(keyText);
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void keyReleased(KeyEvent e)
{
String keyText=KeyEvent.getKeyText(e.getKeyCode()).toLowerCase();
synchronized (keyLock) {keysDown.remove(keyText);processedKeys.remove(keyText);}
}
private void processKeys()
{
//System.out.println(keysDown);
TreeSet<String> keysDownCopy=new TreeSet<String>();
synchronized (keyLock) {keysDownCopy=(TreeSet<String>)keysDown.clone();}
keysDownCopy.addAll(unprocessedKeys);
for(String keyText:keysDownCopy)
{
if (keyBindings.containsKey(keyText))
{
for(ArrayList binding:keyBindings.get(keyText))
{
Turtle t=(Turtle)binding.get(0);
String className=(String)binding.get(1);
String methodName=(String)binding.get(2);
Boolean repeat=(Boolean)binding.get(3);
if(!repeat && processedKeys.contains(keyText)) break;
unprocessedKeys.remove(keyText);
processedKeys.add(keyText);
try
{
Class cls = Class.forName(className);
Object clsInstance = (Object) cls.newInstance();
Method m = clsInstance.getClass().getMethod(methodName, t.getClass());
m.invoke(clsInstance, t);
}
catch(Exception e1)
{
try
{
Class cls = Class.forName(className);
Object clsInstance = (Object) cls.newInstance();
Method m = clsInstance.getClass().getMethod(methodName, t.getClass(), keyText.getClass());
m.invoke(clsInstance, t, keyText);
}
catch(Exception e2)
{
try
{
Class cls = Class.forName(className);
Object clsInstance = (Object) cls.newInstance();
Method m = clsInstance.getClass().getMethod(methodName);
m.invoke(clsInstance);
}
catch(Exception e3)
{
System.out.println("KeyBinding for "+keyText+" has failed.");
e1.printStackTrace();
e2.printStackTrace();
e3.printStackTrace();
}
}
}
}
}
}
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void componentHidden(ComponentEvent e) {}
/**
* Internal mehod for handling events.
* @param e event
*/
public void componentMoved(ComponentEvent e) {}
/**
* Internal mehod for handling events.
* @param e event
*/
public void componentResized(ComponentEvent e)
{
width=(int)draw.getBounds().getWidth();
height=(int)draw.getBounds().getHeight();
setupBuffering();
updateAll();
}
/**
* Internal mehod for handling events.
* @param e event
*/
public void componentShown(ComponentEvent e) {}
/**
* Internal mehod for handling events.
* @param e event
*/
public void mouseWheelMoved(MouseWheelEvent e)
{
int notches = e.getWheelRotation();
double ds=Math.pow(1.1,notches);
x=e.getX();
y=e.getY();
double dx=width/2-x;
double dy=height/2-y;
synchronized(turtleLock)
{
centerX-=(dx*ds-dx)/scale/ds;
centerY+=(dy*ds-dy)/scale/ds;
scale*=ds;
}
updateAll();
}
/**
* Get the pressed keys.
*
* @return a list of pressed keys
*/
public static String[] keysDown()
{
return keysDown.toArray(new String[]{});
}
/**
* Test if a key is pressed or not.
*
* @param key key you are testing
* @return true if the key is pressed
*/
public static boolean isKeyDown(String key)
{
return keysDown.contains(key);
}
/**
* Get the mouse x coordinate using the screens coordinate system.
*
* @return x coordinate
*/
public static int mouseX()
{
return turtle.x;
}
/**
* Get the mouse y coordinate using the screens coordinate system.
*
* @return y coordinate
*/
public static int mouseY()
{
return turtle.y;
}
/**
* Check to see if a mouse button is down.
*
* @return true if a button is down
*/
public static boolean mouseButton()
{
return mouseButton1() || mouseButton2() || mouseButton3();
}
/**
* Check to see if the first mouse button is down.
*
* @return true if button 1 is down
*/
public static boolean mouseButton1()
{
return (turtle.modifiers&16)==16;
}
/**
* Check to see if the second mouse button is down.
*
* @return true if button 2 is down
*/
public static boolean mouseButton2()
{
return (turtle.modifiers&8)==8;
}
/**
* Check to see if the third mouse button is down.
*
* @return true if button 3 is down
*/
public static boolean mouseButton3()
{
return (turtle.modifiers&4)==4;
}
/**
* Converts screen coordinates to canvas coordinates.
*
* @param screenX screen x coordinate
* @return canvas x coordinate
*/
public static double canvasX(double screenX)
{
return (screenX-width/2.0)/scale+centerX;
}
/**
* Converts screen coordinates to canvas coordinates.
*
* @param screenY screen y coordinate
* @return canvas y coordinate
*/
public static double canvasY(double screenY)
{
return (-screenY+height/2.0)/scale+centerY;
}
public static double screenX(double canvasX)
{
return (canvasX-centerX)*scale+width/2.0;
}
public static double screenY(double canvasY)
{
return (canvasY-centerY)*scale+height/2.0;
}
private static void saveGCODE(String filename)
{
PrintWriter out=new PrintWriter(System.out);
try
{
out=new PrintWriter(filename);
}
catch(Exception e)
{
}
out.println("M104 S200");
out.println("M109 S200");
out.println("G21");
out.println("G90");
out.println("M82");
out.println("M106");
out.println("G28 X0 Y0");
out.println("G28 Z0");
out.println("G29");
out.println("G1 Z15.0 F9000");
out.println("G92 E0");
out.println("G1 F200 E5");
out.println("G92 E0");
out.println("G1 X50 Y50 F1800");
double e=0;
synchronized(turtleLock)
{
int i=0;
for (Map.Entry<Long, ArrayList> entry : turtleStates.entrySet())
{
retrieveState(entry.getKey());
Turtle t=getStateTurtle(entry.getValue());
i++;
if(i==1)continue;
if(t.__location!=null && !t.__location.equals(t._location))
{
double x1=t._location.x,y1=t._location.y,x2=t.__location.x,y2=t.__location.y;
double d=Math.hypot(x1-x2,y1-y2);
e+=d*0.05;
//System.out.printf("%f %f %f %f",x1,y1,x2,y2);
if(t._isPenDown)
{
out.printf("G1 X%.4f Y%.4f E%.4f\n",screenX(x1)*1.0/width*100,screenY(y1)*1.0/height*100,e);
}
else
{
}
}
}
out.println("G1 Z15");
out.println("M104 S0");
out.println("M140 S0");
out.close();
}
}
}
package turtle;
import java.awt.Color;
import javax.swing.JOptionPane;
// Narysuj wielokąt foremny o podanej liczbie boków
public class Wielokat {
public static void main(String[] args) {
final int obwod = 1500;
int ileBokow = Integer.parseInt(JOptionPane.showInputDialog("Podaj liczbę boków"));
Turtle turtle = new Turtle();
Turtle.setCanvasSize(obwod/2, obwod/2);
double kat = 360.0 / ileBokow;
double bok = 1.0 * obwod / ileBokow;
turtle.up();
turtle.setPosition(-bok/2, -obwod/(2*Math.PI));
turtle.down();
turtle.penColor(Color.RED);
turtle.width(4);
for(int i = 0; i < ileBokow; i++) {
turtle.forward(bok);
turtle.left(kat);
}
}
}
package turtle;
import javax.swing.JOptionPane;
// Narysuj wielokąt foremny o podanej liczbie boków
public class Wielokat_v1 {
public static void main(String[] args) {
int ileBokow = Integer.parseInt(JOptionPane.showInputDialog("Podaj liczbę boków"));
Turtle turtle = new Turtle();
Turtle.setCanvasSize(1600, 900);
double kat = 360.0 / ileBokow;
for(int i = 0; i < ileBokow; i++) {
turtle.forward(100);
turtle.left(kat);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment