Fixed merge conflicts

This commit is contained in:
Kristian Knarvik 2018-03-08 01:02:22 +01:00
commit 2e50452a22
10 changed files with 240 additions and 36 deletions

View File

@ -98,6 +98,12 @@ Vi har også et par andre mer abstrakte ting vi bør tenke på f.eks. koordi
* [IArea](src/inf101/v18/grid/IArea.java) et rektangulært sett med ILocations. Brukes f.eks. av spillkartet for å lettvint gå gjennom alle cellene/rutene i kartet. * [IArea](src/inf101/v18/grid/IArea.java) et rektangulært sett med ILocations. Brukes f.eks. av spillkartet for å lettvint gå gjennom alle cellene/rutene i kartet.
* ([IGrid<T>](src/inf101/v18/grid/IGrid.java) og [IMultiGrid<T>](src/inf101/v18/grid/IMultiGrid.java) IGrid<T> er tilsvarende til den du har brukt i labbene tidligere; IMultiGrid<T> er et grid der hver celle er en liste av T-er. Den blir brukt av spillkartet, men du trenger neppe bruke den selv.) * ([IGrid<T>](src/inf101/v18/grid/IGrid.java) og [IMultiGrid<T>](src/inf101/v18/grid/IMultiGrid.java) IGrid<T> er tilsvarende til den du har brukt i labbene tidligere; IMultiGrid<T> er et grid der hver celle er en liste av T-er. Den blir brukt av spillkartet, men du trenger neppe bruke den selv.)
UML:
<a href="https://retting.ii.uib.no/inf101/inf101.v18/wikis/img/RogueInterface.png">
<img src="https://retting.ii.uib.no/inf101/inf101.v18/wikis/img/RogueInterface.png" width="200">
</a>
### *(4%)* Deloppgave A1: Tilstand, oppførsel og grensesnitt for objektene ### *(4%)* Deloppgave A1: Tilstand, oppførsel og grensesnitt for objektene
*Du vil sikkert finne på lurere svar på spørsmålene etterhvert som du jobber med oppgaven. Det er fint om du lar de opprinnelige svarene stå (det er helt OK om de er totalt feil eller helt på jordet) og heller gjør tilføyelser. Du kan evt. bruke ~~overstryking~~ (putt dobbel tilde rundt teksten, `~~Rabbit.java funker fordi det bor en liten kanin inni datamaskinen~~`) for å markere det du ikke lenger synes er like lurt.* *Du vil sikkert finne på lurere svar på spørsmålene etterhvert som du jobber med oppgaven. Det er fint om du lar de opprinnelige svarene stå (det er helt OK om de er totalt feil eller helt på jordet) og heller gjør tilføyelser. Du kan evt. bruke ~~overstryking~~ (putt dobbel tilde rundt teksten, `~~Rabbit.java funker fordi det bor en liten kanin inni datamaskinen~~`) for å markere det du ikke lenger synes er like lurt.*
@ -153,7 +159,7 @@ Prøv også å justere gulrøttene litt ([Carrot](src/inf101/v18/rogue101/exampl
* **a)** Gulrøttene får helsen satt til -1 når de blir spist etter helsereglene våre vil de derfor bli fjernet fra kartet. Prøv å sette helsen til 0 i stedet. Hvorfor går det ikke bedre med kaninene selv om gulrøttene nå blir værende på kartet? * **a)** Gulrøttene får helsen satt til -1 når de blir spist etter helsereglene våre vil de derfor bli fjernet fra kartet. Prøv å sette helsen til 0 i stedet. Hvorfor går det ikke bedre med kaninene selv om gulrøttene nå blir værende på kartet?
* **b)** Det hadde kanskje vært praktisk (ihvertfall for kaninene) om gulrøttene vokste seg store og fine igjen etter en stund; for eksempel ved at de “helbreder” ett helsepoeng for hver runde som går men `Carrot` har ingen `doTurn()` metode slik `Rabbit` har, så den får ikke med seg at rundene går eller at kaninene hopper rundt (rent bortsett fra at det går an å “jukse” ved å regne med / håpe på at `draw()` blir kalt en gang per runde). * **b)** Det hadde kanskje vært praktisk (ihvertfall for kaninene) om gulrøttene vokste seg store og fine igjen etter en stund; for eksempel ved at de “helbreder” ett helsepoeng for hver runde som går men `Carrot` har ingen `doTurn()` metode slik `Rabbit` har, så den får ikke med seg at rundene går eller at kaninene hopper rundt (rent bortsett fra at det går an å “jukse” ved å regne med / håpe på at `draw()` blir kalt en gang per runde).
* Lag en `doTurn()`-metode i `Carrot` som øker `hp` med 1 for hver runde (opp til `getMaxHealth()`). * ~~Lag en `doTurn()`-metode i `Carrot` som øker `hp` med 1 for hver runde (opp til `getMaxHealth()`).~~ (Denne fulgte med fra før.)
* Hva skjer, ser det ut til å virke? * Hva skjer, ser det ut til å virke?
* Hvis det ikke virker, hva må du eventuelt gjøre for å få `Carrot` til å gjøre noe hver runde? * Hvis det ikke virker, hva må du eventuelt gjøre for å få `Carrot` til å gjøre noe hver runde?
* **c)** Du kan også prøve å la `Game` legge til nye, tilfeldig plasserte gulrøtter av og til: * **c)** Du kan også prøve å la `Game` legge til nye, tilfeldig plasserte gulrøtter av og til:

View File

@ -25,4 +25,14 @@ public interface IPaintLayer {
*/ */
void layerToFront(); void layerToFront();
/**
* @return Width (in pixels) of graphics layer
*/
double getWidth();
/**
* @return Height (in pixels) of graphics layer
*/
double getHeight();
} }

View File

@ -5,13 +5,45 @@ import javafx.scene.paint.Paint;
public interface IPainter extends IPaintLayer { public interface IPainter extends IPaintLayer {
/**
* Restore graphics settings previously stored by {@link #save()}.
*
* @return {@code this}, for sending more draw commands
*/
IPainter restore(); IPainter restore();
/**
* Store graphics settings.
*
* @return {@code this}, for sending more draw commands
*/
IPainter save(); IPainter save();
/**
* Set colour used to drawing and filling.
*
* @param ink A colour or paint
* @return {@code this}, for sending more draw commands
*/
IPainter setInk(Paint ink); IPainter setInk(Paint ink);
/**
* Start drawing a shape.
*
* @return An IShape for sending shape drawing commands
*/
IShape shape(); IShape shape();
/**
* Start drawing with a turtle.
*
* @return An ITurtle for sending turtle drawing commands
*/
ITurtle turtle(); ITurtle turtle();
/**
* @return Current ink, as set by {@link #setInk(Paint)}
*/
Paint getInk();
} }

View File

@ -2,7 +2,18 @@ package inf101.v18.gfx.gfxmode;
public interface ITurtle extends IPainter { public interface ITurtle extends IPainter {
<T> T as(Class<T> class1); /**
* This method is used to convert the turtle to an other type, determined by the
* class object given as an argument.
* <p>
* This can be used to access extra functionality not provided by this
* interface, such as direct access to the underlying graphics context.
*
* @param clazz
* @return This object or an appropriate closely related object of the given
* time; or <code>null</code> if no appropriate object can be found
*/
<T> T as(Class<T> clazz);
/** /**
* Move to the given position while drawing a curve * Move to the given position while drawing a curve
@ -236,7 +247,24 @@ public interface ITurtle extends IPainter {
*/ */
ITurtle turnTowards(double degrees, double percent); ITurtle turnTowards(double degrees, double percent);
double getWidth(); /**
* Jump (without drawing) to the given relative position.
* <p>
* The new position will be equal to getPos().move(relPos).
*
* @param relPos
* A position, interpreted relative to current position
* @return {@code this}, for sending more draw commands
*/
ITurtle jump(Point relPos);
/**
* Move to the given relative position while drawing a line
* <p>
* The new position will be equal to getPos().move(relPos).
*
* @return {@code this}, for sending more draw commands
*/
ITurtle draw(Point relPos);
double getHeight();
} }

View File

@ -92,4 +92,25 @@ public class Point {
public String toString() { public String toString() {
return String.format("(%.2f,%.2f)", x, y); return String.format("(%.2f,%.2f)", x, y);
} }
/**
* Multiply this point by a scale factor.
*
* @param factor A scale factor
* @return A new Point, (getX()*factor, getY()*factor)
*/
public Point scale(double factor) {
return new Point(x*factor, y*factor);
}
/**
* Find difference between points.
* <p>
* The returned value will be such that <code>this.move(deltaTo(point)).equals(point)</code>.
* @param point Another point
* @return A new Point, (point.getX()-getX(), point.getY()-getY())
*/
public Point deltaTo(Point point) {
return new Point(point.x-x, point.y-y);
}
} }

View File

@ -222,7 +222,7 @@ public class ShapePainter implements IShape {
@Override @Override
public void draw(GraphicsContext context) { public void draw(GraphicsContext context) {
if (cmd != null) { if (cmd != null && context != null) {
if (fill != null) if (fill != null)
cmd.fill(context, this); cmd.fill(context, this);
if (stroke != null) if (stroke != null)
@ -238,7 +238,7 @@ public class ShapePainter implements IShape {
@Override @Override
public ShapePainter fill() { public ShapePainter fill() {
if (cmd != null) if (cmd != null && context != null)
cmd.fill(context, this); cmd.fill(context, this);
return this; return this;
} }
@ -288,7 +288,7 @@ public class ShapePainter implements IShape {
@Override @Override
public ShapePainter stroke() { public ShapePainter stroke() {
if (cmd != null) if (cmd != null && context != null)
cmd.stroke(context, this); cmd.stroke(context, this);
return this; return this;
} }

View File

@ -9,6 +9,8 @@ import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.paint.Paint; import javafx.scene.paint.Paint;
import javafx.scene.shape.StrokeLineCap;
import javafx.scene.shape.StrokeLineJoin;
public class TurtlePainter implements IPaintLayer, ITurtle { public class TurtlePainter implements IPaintLayer, ITurtle {
@ -41,12 +43,10 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
private final Canvas canvas; private final Canvas canvas;
private boolean path = false; private boolean path = false;
public TurtlePainter(double width, double height, Canvas canvas) { public TurtlePainter(double width, double height) {
screen = null; this.screen = null;
if (canvas == null) this.canvas = null;
canvas = new Canvas(width, height); this.context = null;
this.canvas = canvas;
this.context = canvas.getGraphicsContext2D();
this.width = width; this.width = width;
this.height = height; this.height = height;
stateStack.add(new TurtleState()); stateStack.add(new TurtleState());
@ -55,6 +55,8 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
} }
public TurtlePainter(Screen screen, Canvas canvas) { public TurtlePainter(Screen screen, Canvas canvas) {
if (screen == null || canvas == null)
throw new IllegalArgumentException();
this.screen = screen; this.screen = screen;
this.canvas = canvas; this.canvas = canvas;
this.context = canvas.getGraphicsContext2D(); this.context = canvas.getGraphicsContext2D();
@ -63,6 +65,8 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
stateStack.add(new TurtleState()); stateStack.add(new TurtleState());
state.dir = new Direction(1.0, 0.0); state.dir = new Direction(1.0, 0.0);
state.pos = new Point(screen.getWidth() / 2, screen.getHeight() / 2); state.pos = new Point(screen.getWidth() / 2, screen.getHeight() / 2);
context.setLineJoin(StrokeLineJoin.BEVEL);
context.setLineCap(StrokeLineCap.SQUARE);
} }
@Override @Override
@ -70,12 +74,15 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
public <T> T as(Class<T> clazz) { public <T> T as(Class<T> clazz) {
if (clazz == GraphicsContext.class) if (clazz == GraphicsContext.class)
return (T) context; return (T) context;
if (clazz == getClass())
return (T) this;
else else
return null; return null;
} }
@Override @Override
public void clear() { public void clear() {
if (context != null)
context.clearRect(0, 0, getWidth(), getHeight()); context.clearRect(0, 0, getWidth(), getHeight());
} }
@ -83,6 +90,7 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
public ITurtle curveTo(Point to, double startControl, double endAngle, double endControl) { public ITurtle curveTo(Point to, double startControl, double endAngle, double endControl) {
Point c1 = state.pos.move(state.dir, startControl); Point c1 = state.pos.move(state.dir, startControl);
Point c2 = to.move(Direction.fromDegrees(endAngle + 180), endControl); Point c2 = to.move(Direction.fromDegrees(endAngle + 180), endControl);
if (context != null) {
if (!path) { if (!path) {
// context.save(); // context.save();
context.setStroke(state.ink); context.setStroke(state.ink);
@ -91,11 +99,12 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
context.moveTo(state.pos.getX(), state.pos.getY()); context.moveTo(state.pos.getX(), state.pos.getY());
} }
context.bezierCurveTo(c1.getX(), c1.getY(), c2.getX(), c2.getY(), to.getX(), to.getY()); context.bezierCurveTo(c1.getX(), c1.getY(), c2.getX(), c2.getY(), to.getX(), to.getY());
}
state.inDir = state.dir; state.inDir = state.dir;
state.pos = to; state.pos = to;
state.dir = Direction.fromDegrees(endAngle); state.dir = Direction.fromDegrees(endAngle);
if (!path) { if (!path && context != null) {
context.stroke(); context.stroke();
// context.restore(); // context.restore();
} }
@ -113,6 +122,12 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
return drawTo(to); return drawTo(to);
} }
@Override
public ITurtle draw(Point relPos) {
Point to = state.pos.move(relPos);
return drawTo(to);
}
@Override @Override
public ITurtle drawTo(double x, double y) { public ITurtle drawTo(double x, double y) {
Point to = new Point(x, y); Point to = new Point(x, y);
@ -121,7 +136,9 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
@Override @Override
public ITurtle drawTo(Point to) { public ITurtle drawTo(Point to) {
if (path) { if (path && context != null) {
context.setStroke(state.ink);
context.setLineWidth(state.penSize);
context.lineTo(to.getX(), to.getY()); context.lineTo(to.getX(), to.getY());
} else { } else {
line(to); line(to);
@ -164,6 +181,18 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
public ITurtle jump(double dist) { public ITurtle jump(double dist) {
state.inDir = state.dir; state.inDir = state.dir;
state.pos = state.pos.move(state.dir, dist); state.pos = state.pos.move(state.dir, dist);
if (path && context != null)
context.moveTo(state.pos.getX(), state.pos.getY());
return this;
}
@Override
public ITurtle jump(Point relPos) {
// TODO: state.inDir = state.dir;
state.pos = state.pos.move(relPos);
if (path && context != null)
context.moveTo(state.pos.getX(), state.pos.getY());
return this; return this;
} }
@ -195,11 +224,13 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
@Override @Override
public ITurtle line(Point to) { public ITurtle line(Point to) {
if (context != null) {
// context.save(); // context.save();
context.setStroke(state.ink); context.setStroke(state.ink);
context.setLineWidth(state.penSize); context.setLineWidth(state.penSize);
context.strokeLine(state.pos.getX(), state.pos.getY(), to.getX(), to.getY()); context.strokeLine(state.pos.getX(), state.pos.getY(), to.getX(), to.getY());
// context.restore(); // context.restore();
}
return this; return this;
} }
@ -288,10 +319,55 @@ public class TurtlePainter implements IPaintLayer, ITurtle {
@Override @Override
public ITurtle turtle() { public ITurtle turtle() {
TurtlePainter painter = screen != null ? new TurtlePainter(screen, canvas) TurtlePainter painter = screen != null ? new TurtlePainter(screen, canvas) : new TurtlePainter(width, height);
: new TurtlePainter(width, height, canvas);
painter.stateStack.set(0, new TurtleState(state)); painter.stateStack.set(0, new TurtleState(state));
return painter; return painter;
} }
public ITurtle beginPath() {
if (path)
throw new IllegalStateException("beginPath() after beginPath()");
path = true;
if (context != null) {
context.setStroke(state.ink);
context.beginPath();
context.moveTo(state.pos.getX(), state.pos.getY());
}
return this;
}
public ITurtle closePath() {
if (!path)
throw new IllegalStateException("closePath() without beginPath()");
if (context != null)
context.closePath();
return this;
}
public ITurtle endPath() {
if (!path)
throw new IllegalStateException("endPath() without beginPath()");
path = false;
if (context != null)
context.stroke();
return this;
}
public ITurtle fillPath() {
if (!path)
throw new IllegalStateException("fillPath() without beginPath()");
path = false;
if (context != null) {
context.save();
context.setFill(state.ink);
context.fill();
context.restore();
}
return this;
}
@Override
public Paint getInk() {
return state.ink;
}
} }

View File

@ -14,6 +14,8 @@ import java.util.regex.Pattern;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
public class ControlSequences { public class ControlSequences {
private static final boolean DEBUG = false;
public static class CsiPattern { public static class CsiPattern {
public static CsiPattern compile0(String pat, String desc, Consumer<Printer> handler) { public static CsiPattern compile0(String pat, String desc, Consumer<Printer> handler) {
CsiPattern csiPattern = new CsiPattern(pat, 0, 0, desc, handler, null, null); CsiPattern csiPattern = new CsiPattern(pat, 0, 0, desc, handler, null, null);
@ -73,10 +75,12 @@ public class ControlSequences {
String argStr = matcher.groupCount() > 0 ? matcher.group(1) : ""; String argStr = matcher.groupCount() > 0 ? matcher.group(1) : "";
String[] args = argStr.split(";"); String[] args = argStr.split(";");
if (handler0 != null) { if (handler0 != null) {
if(DEBUG)
System.out.println("Handling " + getDescription() + "."); System.out.println("Handling " + getDescription() + ".");
handler0.accept(printer); handler0.accept(printer);
} else if (handler1 != null) { } else if (handler1 != null) {
int arg = args.length > 0 && !args[0].equals("") ? Integer.valueOf(args[0]) : defaultArg; int arg = args.length > 0 && !args[0].equals("") ? Integer.valueOf(args[0]) : defaultArg;
if(DEBUG)
System.out.println("Handling " + getDescription() + ": " + arg); System.out.println("Handling " + getDescription() + ": " + arg);
handler1.accept(printer, arg); handler1.accept(printer, arg);
} else if (handlerN != null) { } else if (handlerN != null) {
@ -90,6 +94,7 @@ public class ControlSequences {
while (argList.size() < numArgs) { while (argList.size() < numArgs) {
argList.add(defaultArg); argList.add(defaultArg);
} }
if(DEBUG)
System.out.println("Handling " + getDescription() + ": " + argList); System.out.println("Handling " + getDescription() + ": " + argList);
handlerN.accept(printer, argList); handlerN.accept(printer, argList);
} }

View File

@ -100,13 +100,25 @@ public class Printer implements IPaintLayer {
private int csiMode = 0; private int csiMode = 0;
private final double width;
private final double height;
public Printer(double width, double height) { public Printer(double width, double height) {
this(null, new Canvas(width, height)); this.screen = null;
this.textPage = null;
this.width = width;
this.height = height;
for (int i = 0; i < TextMode.PAGE_HEIGHT_MAX; i++) {
lineBuffer.add(new Char[TextMode.LINE_WIDTH_MAX]);
}
resetFull();
} }
public Printer(Screen screen, Canvas page) { public Printer(Screen screen, Canvas page) {
this.screen = screen; this.screen = screen;
this.textPage = page; this.textPage = page;
this.width = page.getWidth();
this.height = page.getHeight();
for (int i = 0; i < TextMode.PAGE_HEIGHT_MAX; i++) { for (int i = 0; i < TextMode.PAGE_HEIGHT_MAX; i++) {
lineBuffer.add(new Char[TextMode.LINE_WIDTH_MAX]); lineBuffer.add(new Char[TextMode.LINE_WIDTH_MAX]);
} }
@ -126,15 +138,17 @@ public class Printer implements IPaintLayer {
moveTo(leftMargin, y + 1); moveTo(leftMargin, y + 1);
break; break;
case "\f": case "\f":
GraphicsContext context = textPage.getGraphicsContext2D();
moveTo(leftMargin, topMargin); moveTo(leftMargin, topMargin);
for (Char[] line : lineBuffer) for (Char[] line : lineBuffer)
Arrays.fill(line, null); Arrays.fill(line, null);
if(textPage != null) {
GraphicsContext context = textPage.getGraphicsContext2D();
if (background != null && background != Color.TRANSPARENT) { if (background != null && background != Color.TRANSPARENT) {
context.setFill(background); context.setFill(background);
context.fillRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight()); context.fillRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight());
} else } else
context.clearRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight()); context.clearRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight());
}
break; break;
case "\b": case "\b":
moveHoriz(-1); moveHoriz(-1);
@ -286,7 +300,7 @@ public class Printer implements IPaintLayer {
} }
private void drawChar(int x, int y, Char c) { private void drawChar(int x, int y, Char c) {
if (c != null) { if (c != null && textPage != null) {
GraphicsContext context = textPage.getGraphicsContext2D(); GraphicsContext context = textPage.getGraphicsContext2D();
context.setFill(c.fill); context.setFill(c.fill);
@ -502,6 +516,8 @@ public class Printer implements IPaintLayer {
* "ms/char", "mode", "indir", "inv", "fake"); for (int m = -1; m < 8; m++) { * "ms/char", "mode", "indir", "inv", "fake"); for (int m = -1; m < 8; m++) {
* long t0 = System.currentTimeMillis(); int n = 0; * long t0 = System.currentTimeMillis(); int n = 0;
*/ */
if(textPage == null)
return;
GraphicsContext context = textPage.getGraphicsContext2D(); GraphicsContext context = textPage.getGraphicsContext2D();
if (background != null && background != Color.TRANSPARENT) { if (background != null && background != Color.TRANSPARENT) {
@ -718,4 +734,14 @@ public class Printer implements IPaintLayer {
plot(x, y, (a, b) -> a & ~b); plot(x, y, (a, b) -> a & ~b);
} }
@Override
public double getWidth() {
return width;
}
@Override
public double getHeight() {
return height;
}
} }

View File

@ -85,7 +85,7 @@ public class Game implements IGame {
public Game(String mapString) { public Game(String mapString) {
printer = new Printer(1280, 720); printer = new Printer(1280, 720);
painter = new TurtlePainter(1280, 720, null); painter = new TurtlePainter(1280, 720);
addFactory(); addFactory();