Rogue101/src/inf101/v18/gfx/gfxmode/TurtlePainter.java

298 lines
6.2 KiB
Java
Raw Normal View History

2018-02-28 10:22:33 +01:00
package inf101.v18.gfx.gfxmode;
import java.util.ArrayList;
import java.util.List;
import inf101.v18.gfx.IPaintLayer;
import inf101.v18.gfx.Screen;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
public class TurtlePainter implements IPaintLayer, ITurtle {
static class TurtleState {
protected Point pos;
protected Direction dir;
protected Direction inDir;
protected double penSize = 1.0;
protected Paint ink = Color.BLACK;
public TurtleState() {
}
public TurtleState(TurtleState s) {
pos = s.pos;
dir = s.dir;
inDir = s.inDir;
penSize = s.penSize;
ink = s.ink;
}
}
private final Screen screen;
2018-02-28 23:51:40 +01:00
private final double width;
private final double height;
2018-02-28 10:22:33 +01:00
private final GraphicsContext context;
private final List<TurtleState> stateStack = new ArrayList<>();
private TurtleState state = new TurtleState();
private final Canvas canvas;
private boolean path = false;
2018-02-28 23:51:40 +01:00
public TurtlePainter(double width, double height, Canvas canvas) {
screen = null;
if (canvas == null)
canvas = new Canvas(width, height);
this.canvas = canvas;
this.context = canvas.getGraphicsContext2D();
this.width = width;
this.height = height;
stateStack.add(new TurtleState());
state.dir = new Direction(1.0, 0.0);
state.pos = new Point(width / 2, height / 2);
}
2018-02-28 10:22:33 +01:00
public TurtlePainter(Screen screen, Canvas canvas) {
this.screen = screen;
this.canvas = canvas;
this.context = canvas.getGraphicsContext2D();
2018-02-28 23:51:40 +01:00
this.width = screen.getWidth();
this.height = screen.getHeight();
2018-02-28 10:22:33 +01:00
stateStack.add(new TurtleState());
state.dir = new Direction(1.0, 0.0);
state.pos = new Point(screen.getWidth() / 2, screen.getHeight() / 2);
}
2018-02-28 23:51:40 +01:00
@Override
@SuppressWarnings("unchecked")
public <T> T as(Class<T> clazz) {
if (clazz == GraphicsContext.class)
return (T) context;
else
return null;
}
2018-02-28 10:22:33 +01:00
@Override
public void clear() {
context.clearRect(0, 0, getWidth(), getHeight());
}
2018-02-28 23:51:40 +01:00
@Override
public ITurtle curveTo(Point to, double startControl, double endAngle, double endControl) {
Point c1 = state.pos.move(state.dir, startControl);
Point c2 = to.move(Direction.fromDegrees(endAngle + 180), endControl);
if (!path) {
// context.save();
context.setStroke(state.ink);
context.setLineWidth(state.penSize);
context.beginPath();
context.moveTo(state.pos.getX(), state.pos.getY());
}
context.bezierCurveTo(c1.getX(), c1.getY(), c2.getX(), c2.getY(), to.getX(), to.getY());
state.inDir = state.dir;
state.pos = to;
state.dir = Direction.fromDegrees(endAngle);
if (!path) {
context.stroke();
// context.restore();
}
return this;
}
2018-02-28 10:22:33 +01:00
@Override
public void debugTurtle() {
System.err.println("[" + state.pos + " " + state.dir + "]");
}
@Override
2018-02-28 23:51:40 +01:00
public ITurtle draw(double dist) {
Point to = state.pos.move(state.dir, dist);
return drawTo(to);
2018-02-28 10:22:33 +01:00
}
@Override
2018-02-28 23:51:40 +01:00
public ITurtle drawTo(double x, double y) {
Point to = new Point(x, y);
return drawTo(to);
}
@Override
public ITurtle drawTo(Point to) {
if (path) {
context.lineTo(to.getX(), to.getY());
} else {
line(to);
}
state.inDir = state.dir;
state.pos = to;
2018-02-28 10:22:33 +01:00
return this;
}
@Override
public double getAngle() {
return state.dir.toDegrees();
}
@Override
public Direction getDirection() {
return state.dir;
}
2018-02-28 23:51:40 +01:00
@Override
2018-02-28 10:22:33 +01:00
public double getHeight() {
2018-02-28 23:51:40 +01:00
return height;
2018-02-28 10:22:33 +01:00
}
@Override
public Point getPos() {
return state.pos;
}
2018-02-28 23:51:40 +01:00
public Screen getScreen() {
return screen;
2018-02-28 10:22:33 +01:00
}
2018-02-28 23:51:40 +01:00
@Override
public double getWidth() {
return width;
2018-02-28 10:22:33 +01:00
}
@Override
public ITurtle jump(double dist) {
state.inDir = state.dir;
state.pos = state.pos.move(state.dir, dist);
return this;
}
@Override
public ITurtle jumpTo(double x, double y) {
state.inDir = state.dir;
state.pos = new Point(x, y);
return this;
}
@Override
public ITurtle jumpTo(Point to) {
state.inDir = state.dir;
state.pos = to;
return this;
}
@Override
2018-02-28 23:51:40 +01:00
public void layerToBack() {
if (screen != null)
screen.moveToBack(this);
2018-02-28 10:22:33 +01:00
}
@Override
2018-02-28 23:51:40 +01:00
public void layerToFront() {
if (screen != null)
screen.moveToFront(this);
2018-02-28 10:22:33 +01:00
}
@Override
2018-02-28 23:51:40 +01:00
public ITurtle line(Point to) {
// context.save();
context.setStroke(state.ink);
context.setLineWidth(state.penSize);
context.strokeLine(state.pos.getX(), state.pos.getY(), to.getX(), to.getY());
// context.restore();
2018-02-28 10:22:33 +01:00
return this;
}
@Override
public IPainter restore() {
if (stateStack.size() > 0) {
state = stateStack.remove(stateStack.size() - 1);
}
return this;
}
@Override
public IPainter save() {
stateStack.add(new TurtleState(state));
return this;
}
@Override
public IPainter setInk(Paint ink) {
state.ink = ink;
return this;
}
@Override
public ITurtle setPenSize(double pixels) {
if (pixels < 0)
throw new IllegalArgumentException("Negative: " + pixels);
state.penSize = pixels;
return this;
}
2018-02-28 23:51:40 +01:00
@Override
public IShape shape() {
ShapePainter s = new ShapePainter(context);
return s.at(getPos()).rotation(getAngle()).strokePaint(state.ink);
}
2018-02-28 10:22:33 +01:00
@Override
public ITurtle turn(double degrees) {
state.dir = state.dir.turn(degrees);
return this;
}
@Override
public ITurtle turnAround() {
return turn(180);
}
@Override
public ITurtle turnLeft() {
return turn(90);
}
@Override
public ITurtle turnLeft(double degrees) {
if (degrees < 0)
throw new IllegalArgumentException("Negative: " + degrees + " (use turn())");
state.dir = state.dir.turn(degrees);
return this;
}
@Override
public ITurtle turnRight() {
return turn(-90);
}
@Override
public ITurtle turnRight(double degrees) {
if (degrees < 0)
throw new IllegalArgumentException("Negative: " + degrees + " (use turn())");
state.dir = state.dir.turn(-degrees);
return this;
}
@Override
public ITurtle turnTo(double degrees) {
state.dir = state.dir.turnTo(degrees);
return this;
}
@Override
public ITurtle turnTowards(double degrees, double percent) {
state.dir = state.dir.turnTowards(new Direction(degrees), percent);
return this;
}
@Override
public ITurtle turtle() {
2018-02-28 23:51:40 +01:00
TurtlePainter painter = screen != null ? new TurtlePainter(screen, canvas)
: new TurtlePainter(width, height, canvas);
2018-02-28 10:22:33 +01:00
painter.stateStack.set(0, new TurtleState(state));
return painter;
}
}