Merge remote-tracking branch 'origin/master'

This commit is contained in:
Kristian Knarvik 2018-03-19 19:11:26 +01:00
commit 5ac42d8fcb
7 changed files with 176 additions and 20 deletions

View File

@ -11,7 +11,8 @@ Dette prosjektet inneholder [Semesteroppgave 1](SEM-1.md). Du kan også [lese op
**Innleveringsfrist:**
* Del A + minst to deloppgaver av Del B skal være ferdig til **fredag 9. mars kl. 2359**.
* Hele oppgaven skal være ferdig til **onsdag 14. mars kl. 2359**
* Hele oppgaven skal være ferdig til **fredag 16. mars kl. 2359** ([AoE](https://www.timeanddate.com/worldclock/fixedtime.html?msg=4&iso=20180316T2359&p1=3399))
* [Ekstra tips til innlevering](https://retting.ii.uib.no/inf101/inf101.v18/wikis/innlevering)
(Kryss av under her, i README.md, så kan vi følge med på om du anser deg som ferdig med ting eller ikke. Hvis du er helt ferdig til den første fristen, eller før den andre fristen, kan du si fra til gruppeleder slik at de kan begynne å rette.)

View File

@ -72,8 +72,8 @@ For å fikse dette vil vi at kartet skal ha tingene liggende i sortert rekkeføl
* Du må sette opp et test-scenario:
* du trenger et nytt GameMap (det trenger ikke være fylt med noe)
* du trenger også en ILocation, siden de fleste kart-metodene bruker det (kall `getLocation(x,y)` med en kjent, lovlig posisjon)
* så må du opprette noen IItems og legge dem til på kartposisjonen ved å kalle `GameMap.add()`
* Til slutt kan du teste at tingene ligger i den rekkefølgen du forventer (`GameMap.getAll()`, og sjekk listeelementene med `get()`)
* så må du opprette noen IItems og legge dem til på kartposisjonen ved å kalle `add()` på kartet
* Til slutt kan du teste at tingene ligger i den rekkefølgen du forventer (`getAll()`, og sjekk listeelementene med `get()`)
* *(Litt mer avansert:)* Hvis du vil teste med litt større mengder data er det gjerne upraktisk å sjekke nøyaktig hvordan elementene er plassert da kan du i stedet gå gjennom listen og sjekke at `list.get(i).compareTo(list.get(i+1)) >= 0` for `0 <= i < list.size()-1`. Et godt utvalg data kan du få ved å lage deg en metode som lager tilfeldige IItems den kan uansett være nyttig for å lage tilfeldige kart og slikt. (Du skal lære dette mer grundig i neste lab-oppgave.)
*(Avansert mulighet (ikke del av oppgaven): En mer generell løsning er å lage en sortert liste (kanskje helst `IList/MyList` fra Lab 2/3/4, men evt `List/ArrayList`) og så bruke den i stedet for vanlig liste i `IMultiGrid` og `MultiGrid`. Du trenger litt mer avansert Java-kunnskap for å få det til å funke, du må bla. si at elementtypen er sammenliknbar (f.eks. `ISortedList<T extends Comparable<T>>`) vi ser mer på dette senere i semesteret. )*

View File

@ -9,6 +9,7 @@ import java.util.function.Predicate;
import inf101.v18.gfx.gfxmode.TurtlePainter;
import inf101.v18.gfx.textmode.Printer;
import inf101.v18.rogue101.AppInfo;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Cursor;
@ -257,6 +258,7 @@ public class Screen {
Group root = new Group();
Scene scene = new Scene(root, winWidth, winHeight, Color.BLACK);
stage.setScene(scene);
stage.setTitle(AppInfo.APP_NAME);
if ((configFlags & CONFIG_FLAG_HIDE_MOUSE) != 0) {
scene.setCursor(Cursor.NONE);
}

View File

@ -61,6 +61,7 @@ public class Printer implements IPaintLayer {
1.0000, 1.0000, true);
private static final Paint DEFAULT_BACKGROUND = Color.TRANSPARENT;
private static final TextMode DEFAULT_MODE = TextMode.MODE_40X22;
private static final boolean DEBUG_REDRAW = false;
public static String center(String s, int width) {
for (; s.length() < width; s = " " + s + " ")
@ -103,6 +104,12 @@ public class Printer implements IPaintLayer {
private final double width;
private final double height;
private int dirtyX0 = Integer.MAX_VALUE;
private int dirtyX1 = Integer.MIN_VALUE;
private int dirtyY0 = Integer.MAX_VALUE;
private int dirtyY1 = Integer.MIN_VALUE;
private boolean useBuffer = true;
public Printer(double width, double height) {
this.screen = null;
this.textPage = null;
@ -239,7 +246,10 @@ public class Printer implements IPaintLayer {
y = constrainY(y);
if (y > 0 && y <= TextMode.PAGE_HEIGHT_MAX) {
Arrays.fill(lineBuffer.get(y - 1), null);
redrawTextPage();
dirty(1, y);
dirty(getLineWidth(), y);
if (!useBuffer)
redrawDirty();
}
}
@ -257,7 +267,10 @@ public class Printer implements IPaintLayer {
for (int i = y1; i <= y2; i++) {
Arrays.fill(lineBuffer.get(i - 1), x1 - 1, x2, null);
}
redrawTextPage();
dirty(x1, y1);
dirty(x2, y2);
if (!useBuffer)
redrawDirty();
}
private int constrainX(int x) {
@ -296,11 +309,16 @@ public class Printer implements IPaintLayer {
textMode = textMode.nextMode();
if (adjustDisplayAspect && screen != null)
screen.setAspect(textMode.getAspect());
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
private void drawChar(int x, int y, Char c) {
if (c != null && textPage != null) {
if (useBuffer) {
dirty(x, y);
} else if (c != null && textPage != null) {
GraphicsContext context = textPage.getGraphicsContext2D();
context.setFill(c.fill);
@ -510,6 +528,11 @@ public class Printer implements IPaintLayer {
}
public void redrawTextPage() {
redrawTextPage(1, 1, getLineWidth(), getPageHeight());
clean();
}
private void redrawTextPage(int x0, int y0, int x1, int y1) {
/*
* System.out.printf("redrawTextPage benchmark");
* System.out.printf(" %5s %5s %7s %4s %5s %5s %5s%n", "ms", "chars",
@ -520,21 +543,27 @@ public class Printer implements IPaintLayer {
return;
GraphicsContext context = textPage.getGraphicsContext2D();
double px0 = (x0 - 1) * getCharWidth(), py0 = (y0 - 1) * getCharHeight();
double px1 = x1 * getCharWidth(), py1 = y1 * getCharHeight();
if (DEBUG_REDRAW)
System.out.printf("redrawTextPage(): Area to clear: (%2f,%2f)(%2f,%2f)%n", px0, py0, px1, py1);
if (background != null && background != Color.TRANSPARENT) {
context.setFill(background);
context.fillRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight());
} else
context.clearRect(0.0, 0.0, textPage.getWidth(), textPage.getHeight());
for (int tmpY = 1; tmpY <= getPageHeight(); tmpY++) {
context.fillRect(px0, py0, px1 - px0, py1 - py0);
} else {
context.clearRect(px0, py0, px1 - px0, py1 - py0);
}
for (int tmpY = y0; tmpY <= y1; tmpY++) {
Char[] line = lineBuffer.get(tmpY - 1);
for (int tmpX = 1; tmpX <= getLineWidth(); tmpX++) {
for (int tmpX = x0; tmpX <= x1; tmpX++) {
Char c = line[tmpX - 1];
if (c != null) {
context.save();
context.setFill(c.fill);
context.setStroke(c.stroke);
font.drawTextAt(context, (tmpX - 1) * getCharWidth(), tmpY * getCharHeight(), c.s,
textMode.getCharWidth() / textMode.getCharBoxSize(), c.mode/* m */, c.bg);
Paint bg = c.bg == background ? null : c.bg;
font.drawTextNoClearAt(context, (tmpX - 1) * getCharWidth(), tmpY * getCharHeight(), c.s,
textMode.getCharWidth() / textMode.getCharBoxSize(), c.mode/* m */, bg);
context.restore();
// n++;
@ -590,14 +619,20 @@ public class Printer implements IPaintLayer {
Char[] remove = lineBuffer.remove(lineBuffer.size() - 1);
Arrays.fill(remove, null);
lineBuffer.add(0, remove);
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
public void scrollUp() {
Char[] remove = lineBuffer.remove(0);
Arrays.fill(remove, null);
lineBuffer.add(remove);
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
public boolean setAutoScroll(boolean autoScroll) {
@ -703,7 +738,10 @@ public class Printer implements IPaintLayer {
textMode = mode;
if (adjustDisplayAspect && screen != null)
screen.setAspect(textMode.getAspect());
redrawTextPage();
dirty(1, 1);
dirty(getLineWidth(), getPageHeight());
if (!useBuffer)
redrawDirty();
}
public void setTopMargin() {
@ -744,4 +782,63 @@ public class Printer implements IPaintLayer {
return height;
}
private boolean isDirty() {
return dirtyX0 <= dirtyX1 || dirtyY0 <= dirtyY1;
}
/**
* Expand the dirty region (area that should be redrawn) to include the given
* position
*
* @param x
* @param y
*/
private void dirty(int x, int y) {
dirtyX0 = Math.max(Math.min(x, dirtyX0), 1);
dirtyX1 = Math.min(Math.max(x, dirtyX1), getLineWidth());
dirtyY0 = Math.max(Math.min(y, dirtyY0), 1);
dirtyY1 = Math.min(Math.max(y, dirtyY1), getPageHeight());
}
/**
* Redraw the part of the page that has changed since last redraw.
*/
public void redrawDirty() {
if (isDirty()) {
if (DEBUG_REDRAW)
System.out.printf("redrawDirty(): Dirty region is (%d,%d)(%d,%d)%n", dirtyX0, dirtyY0, dirtyX1,
dirtyY1);
redrawTextPage(dirtyX0, dirtyY0, dirtyX1, dirtyY1);
clean();
}
}
/**
* Mark the entire page as clean
*/
private void clean() {
dirtyX0 = Integer.MAX_VALUE;
dirtyX1 = Integer.MIN_VALUE;
dirtyY0 = Integer.MAX_VALUE;
dirtyY1 = Integer.MIN_VALUE;
}
/**
* With buffered printing, nothing is actually drawn until
* {@link #redrawDirty()} or {@link #redrawTextPage()} is called.
*
* @param buffering
* Whether to use buffering
*/
public void setBuffering(boolean buffering) {
useBuffer = buffering;
}
/**
* @return True if buffering is enabled
* @see #setBuffering(boolean)
*/
public boolean getBuffering() {
return useBuffer;
}
}

View File

@ -514,13 +514,12 @@ public class TextFont {
/**
* Draw the given text at position (x, y), with horizontal scaling.
*
* Text will be clipped so each character fits its expected square-shaped area,
* and the area will be cleared to transparency before drwaing.
* The area will be cleared to transparency before drawing.
*
* The graphics context's current path will be overwritten.
*
* @param ctx
* a grapics context
* a graphics context
* @param x
* X-position of the lower left corner of the text
* @param y
@ -535,6 +534,29 @@ public class TextFont {
textAt(ctx, x, y, text, xScaleFactor, true, false, ctx.getFill(), null, mode, bg);
}
/**
* Draw the given text at position (x, y), with horizontal scaling.
*
* The area will not be cleared to transparency before drawing.
*
* The graphics context's current path will be overwritten.
*
* @param ctx
* a graphics context
* @param x
* X-position of the lower left corner of the text
* @param y
* Y-position of the lower left corner of the text
* @param text
* string to be printed
* @param xScaleFactor
* a horizontal scaling factor
*/
public void drawTextNoClearAt(GraphicsContext ctx, double x, double y, String text, double xScaleFactor, int mode,
Paint bg) {
textAt(ctx, x, y, text, xScaleFactor, false, false, ctx.getFill(), null, mode, bg);
}
private void fakeBlockElement(GraphicsContext ctx, String text, double xScaleFactor) {
text.codePoints().forEach((int c) -> {
// System.out.printf("%s %x%n", text, c);

View File

@ -0,0 +1,31 @@
package inf101.v18.rogue101;
import java.util.Arrays;
import java.util.List;
public class AppInfo {
/**
* Your application name.
*/
public static final String APP_NAME = "Rogue-101";
/**
* Your name.
*/
public static final String APP_DEVELOPER = "INF101-student";
/**
* A short description.
*/
public static final String APP_DESCRIPTION = "Implementasjon av inf101.v18.sem1";
/**
* List of extra credits (e.g. for media sources)
*/
public static final List<String> APP_EXTRA_CREDITS = Arrays.asList(//
/* "Graphics by Foo Bar" */
);
/**
* Help text. Could be used for an in-game help page, perhaps.
* <p>
* Use <code>\n</code> for new lines, <code>\f<code> between pages (if multi-page).
*/
public static final String APP_HELP = "";
}

View File

@ -103,6 +103,7 @@ public class Main extends Application {
if (grid)
printer.drawCharCells();
game.draw();
printer.redrawDirty();
return true;
} else if (code == KeyCode.A) {
screen.cycleAspect();
@ -153,6 +154,7 @@ public class Main extends Application {
game.displayDebug("Exception: " + e.getMessage());
}
}
printer.redrawDirty();
return true;
}
return false;
@ -175,6 +177,7 @@ public class Main extends Application {
System.out.println("doTurn() took " + (System.currentTimeMillis() - t) + "ms");
long t2 = System.currentTimeMillis();
game.draw();
printer.redrawDirty();
if (DEBUG_TIME) {
System.out.println("draw() took " + (System.currentTimeMillis() - t2) + "ms");
System.out.println("doTurn()+draw() took " + (System.currentTimeMillis() - t) + "ms");