"sunlight leakage" fix was proven to be bogus, need proper fix, new JsonWriter and RasterWriter, auto toggle vsync, Doc: new attack momentum calc

Former-commit-id: b94cf67de8be29525c1760abb15e64a8f233028d
Former-commit-id: aef20331d16857d78066564f0c2e4c2cacbe4128
This commit is contained in:
Song Minjae
2016-03-05 14:13:53 +09:00
parent dc788aa515
commit b53af23577
22 changed files with 211 additions and 91 deletions

View File

@@ -0,0 +1,22 @@
package com.Torvald;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import java.io.FileWriter;
import java.io.IOException;
/**
* Created by minjaesong on 16-03-04.
*/
public class JsonWriter {
public static void writeFile(Object c, String path) throws IOException {
JsonElement classElem = new Gson().toJsonTree(c);
String jsonString = classElem.toString();
FileWriter writer = new FileWriter(path);
writer.write(jsonString);
writer.close();
}
}

View File

@@ -0,0 +1,55 @@
package com.Torvald;
import com.Torvald.Terrarum.Terrarum;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
/**
* Created by minjaesong on 16-03-04.
*/
public class RasterWriter {
public static final int[] BANDOFFSET_RGB = {0, 1, 2};
public static final int[] BANDOFFSET_RGBA = {0, 1, 2, 3};
public static final int[] BANDOFFSET_ARGB = {3, 0, 1, 2};
public static final int[] BANDOFFSET_MONO = {0};
public static final int COLORSPACE_SRGB = ColorSpace.CS_sRGB;
public static final int COLORSPACE_GRAY = ColorSpace.CS_GRAY;
public static final int COLORSPACE_GREY = COLORSPACE_GRAY;
public static final int COLORSPACE_CIEXYZ = ColorSpace.CS_CIEXYZ;
public static final int COLORSPACE_RGB_LINEAR_GAMMA = ColorSpace.CS_LINEAR_RGB;
public static void writePNG_RGB(int w, int h, byte[] rasterData, String path) throws IOException {
writePNG(w, h, rasterData, BANDOFFSET_RGB, COLORSPACE_SRGB, path);
}
public static void writePNG_Mono(int w, int h, byte[] rasterData, String path) throws IOException {
writePNG(w, h, rasterData, BANDOFFSET_MONO, COLORSPACE_GREY, path);
}
public static void writePNG(int w, int h, byte[] rasterData, int[] bandOffsets, int awt_colorspace, String path) throws IOException {
DataBuffer buffer = new DataBufferByte(rasterData, rasterData.length);
WritableRaster raster = Raster.createInterleavedRaster(
buffer
, w
, h
, bandOffsets.length * w
, bandOffsets.length
, bandOffsets
, null
);
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(awt_colorspace), false, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
ImageIO.write(image, "PNG", new File(path));
}
}

View File

@@ -106,7 +106,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
/** /**
* in milliseconds * in milliseconds
*/ */
public final int COOLTIME = 500; public final int INVINCIBILITY_TIME = 500;
/** /**
* Give new random ReferenceID and initialise ActorValue * Give new random ReferenceID and initialise ActorValue
@@ -180,7 +180,8 @@ public class ActorWithBody implements Actor, Visible, Glowing {
updateNextHitboxFromVelo(); updateNextHitboxFromVelo();
if (Math.abs(veloX) < 0.5) { // if not horizontally moving then ...
if (Math.abs(veloX) < 0.5) { // fix for special situations (see fig. 1 at the bottom of the source)
updateVerticalPos(); updateVerticalPos();
updateHorizontalPos(); updateHorizontalPos();
} }
@@ -227,7 +228,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
private void updateVerticalPos() { private void updateVerticalPos() {
if (!isPlayerNoClip()) { if (!isPlayerNoClip()) {
// check downward // check downward
if (veloY >= 0) { // use TERNARY for L/R! if (veloY >= 0) {
// order of the if-elseif chain is IMPORTANT // order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_BOTTOM)) { if (isColliding(CONTACT_AREA_BOTTOM)) {
adjustHitBottom(); adjustHitBottom();
@@ -273,7 +274,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
} while (colliding); } while (colliding);
float newY = nextHitbox.getPointedY() - newYOff; float newY = nextHitbox.getPointedY() - newYOff;
nextHitbox.setPositionFromPoint(newX - 1, newY); nextHitbox.setPositionFromPoint(newX, newY);
} }
private void adjustHitTop() { private void adjustHitTop() {
@@ -290,13 +291,13 @@ public class ActorWithBody implements Actor, Visible, Glowing {
} while (colliding); } while (colliding);
float newY = nextHitbox.getPosY() + newYOff; float newY = nextHitbox.getPosY() + newYOff;
nextHitbox.setPosition(newX + 1, newY); nextHitbox.setPosition(newX, newY);
} }
private void updateHorizontalPos() { private void updateHorizontalPos() {
if (!isPlayerNoClip()) { if (!isPlayerNoClip()) {
// check right // check right
if (veloX > 0) { // use TERNARY for L/R! if (veloX > 0) {
// order of the if-elseif chain is IMPORTANT // order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT)) { if (isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT)) {
adjustHitRight(); adjustHitRight();
@@ -309,8 +310,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
else { else {
} }
} }
else if (veloX < 0) { else { // fix for float-point rounding; veloX of zero should be treated as moving left
// order of the if-elseif chain is IMPORTANT // order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT)) { if (isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT)) {
adjustHitLeft(); adjustHitLeft();
@@ -323,9 +323,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
else { else {
} }
} }
else {
}
} }
} }
@@ -362,7 +360,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
} while (newXOff < TSIZE && colliding); } while (newXOff < TSIZE && colliding);
float newX = nextHitbox.getPosX() + newXOff; float newX = nextHitbox.getPosX() + newXOff;
nextHitbox.setPosition(newX + 1, newY); nextHitbox.setPosition(newX, newY); // + 1; float-point rounding compensation (i think...)
} }
private boolean isColliding(int side) { private boolean isColliding(int side) {
@@ -721,3 +719,16 @@ public class ActorWithBody implements Actor, Visible, Glowing {
return FastMath.floor(v / TSIZE) * TSIZE; return FastMath.floor(v / TSIZE) * TSIZE;
} }
} }
/**
= = ↑
=== ===@!
=↑ =↑
=↑ =
=↑ =
=@ (pressing R) =
================== ==================
Fig. 1: the fix was not applied
*/

View File

@@ -53,7 +53,7 @@ public class PBFSigrid {
* fixed value, or 'base value', from creature strength of Dwarf Fortress. * fixed value, or 'base value', from creature strength of Dwarf Fortress.
* Human race uses 1000. (see CreatureHuman.json) * Human race uses 1000. (see CreatureHuman.json)
*/ */
p.actorValue.set("strength", 1250); p.actorValue.set("strength", 1414);
p.actorValue.set("encumbrance", 1000); p.actorValue.set("encumbrance", 1000);
p.actorValue.set("name", "Sigrid"); p.actorValue.set("name", "Sigrid");

View File

@@ -1,5 +1,6 @@
package com.Torvald.Terrarum.ConsoleCommand; package com.Torvald.Terrarum.ConsoleCommand;
import com.Torvald.JsonWriter;
import com.Torvald.Terrarum.Terrarum; import com.Torvald.Terrarum.Terrarum;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
@@ -16,14 +17,10 @@ public class ExportAV implements ConsoleCommand {
@Override @Override
public void execute(String[] args) { public void execute(String[] args) {
if (args.length == 2) { if (args.length == 2) {
JsonElement avelem = new Gson().toJsonTree(Terrarum.game.getPlayer().getActorValue());
String jsonString = avelem.toString();
FileWriter writer;
try { try {
writer = new FileWriter(Terrarum.defaultDir + "/Exports/" + args[1] + ".json"); JsonWriter.writeFile(Terrarum.game.getPlayer().getActorValue()
writer.write(jsonString); , Terrarum.defaultDir + "/Exports/" + args[1] + ".json"
writer.close(); );
new Echo().execute("ExportAV: exported to " + args[1] + ".json"); new Echo().execute("ExportAV: exported to " + args[1] + ".json");
} }

View File

@@ -1,6 +1,7 @@
package com.Torvald.Terrarum.ConsoleCommand; package com.Torvald.Terrarum.ConsoleCommand;
import com.Torvald.ColourUtil.Col4096; import com.Torvald.ColourUtil.Col4096;
import com.Torvald.RasterWriter;
import com.Torvald.Terrarum.Terrarum; import com.Torvald.Terrarum.Terrarum;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@@ -76,23 +77,12 @@ public class ExportMap implements ConsoleCommand {
} }
try { try {
int[] bandOffsets = {0, 1, 2}; // RGB RasterWriter.writePNG_RGB(
DataBuffer buffer = new DataBufferByte(mapData, mapData.length); Terrarum.game.map.width
WritableRaster raster = Raster.createInterleavedRaster(
buffer
, Terrarum.game.map.width
, Terrarum.game.map.height , Terrarum.game.map.height
, 3 * Terrarum.game.map.width , mapData
, 3 , dir + args[1] + ".png"
, bandOffsets );
, null);
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), false, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
ImageIO.write(image, "PNG", new File(dir + args[1] + ".png"));
new Echo().execute("ExportMap: exported to " + args[1] + ".png"); new Echo().execute("ExportMap: exported to " + args[1] + ".png");
} catch (IOException e) { } catch (IOException e) {

View File

@@ -145,6 +145,9 @@ public class Game extends BasicGameState {
TileStat.update(); TileStat.update();
MapDrawer.update(gc, delta_t);
MapCamera.update(gc, delta_t);
actorContainer.forEach(actor -> actor.update(gc, delta_t)); actorContainer.forEach(actor -> actor.update(gc, delta_t));
actorContainer.forEach( actorContainer.forEach(
actor -> { actor -> {
@@ -157,12 +160,11 @@ public class Game extends BasicGameState {
} }
); );
MapDrawer.update(gc, delta_t);
MapCamera.update(gc, delta_t);
uiContainer.forEach(ui -> ui.update(gc, delta_t)); uiContainer.forEach(ui -> ui.update(gc, delta_t));
//bulletin.update(gc, delta_t); //bulletin.update(gc, delta_t);
Terrarum.appgc.setVSync(Terrarum.appgc.getFPS() >= 59);
} }
private void setAppTitle() { private void setAppTitle() {
@@ -200,11 +202,11 @@ public class Game extends BasicGameState {
actor -> { if (actor instanceof Glowing) ((Glowing) actor).drawGlow(gc, g); } actor -> { if (actor instanceof Glowing) ((Glowing) actor).drawGlow(gc, g); }
); );
LightmapRenderer.renderLightMap();
MapCamera.renderFront(gc, g); MapCamera.renderFront(gc, g);
MapDrawer.render(gc, g); MapDrawer.render(gc, g);
LightmapRenderer.renderLightMap();
setBlendModeMul(); setBlendModeMul();
MapDrawer.drawEnvOverlay(g); MapDrawer.drawEnvOverlay(g);
LightmapRenderer.draw(g); LightmapRenderer.draw(g);

View File

@@ -87,11 +87,11 @@ public class LightmapRenderer {
} }
int for_y_start = div16(MapCamera.getCameraY()) - 1; int for_y_start = div16(MapCamera.getCameraY()) - 1; // fix for premature lightmap rendering
int for_x_start = div16(MapCamera.getCameraX()) - 1; int for_x_start = div16(MapCamera.getCameraX()) - 1; // on topmost/leftmost side
int for_y_end = clampHTile(for_y_start + div16(MapCamera.getRenderHeight()) + 2) + 1; int for_y_end = clampHTile(for_y_start + div16(MapCamera.getRenderHeight()) + 2) + 1; // same fix as above
int for_x_end = clampWTile(for_x_start + div16(MapCamera.getRenderWidth()) + 2) + 1; int for_x_end = clampWTile(for_x_start + div16(MapCamera.getRenderWidth()) + 2) + 1;
/** /**
* Updating order: * Updating order:
@@ -104,7 +104,7 @@ public class LightmapRenderer {
* for all staticLightMap[y][x] * for all staticLightMap[y][x]
*/ */
purgePartOfLightmap(for_x_start - 1, for_y_start - 1, for_x_end + 1, for_y_end + 1); purgePartOfLightmap(for_x_start, for_y_start, for_x_end, for_y_end);
// if wider purge were not applied, GL changing (sunset, sunrise) will behave incorrectly // if wider purge were not applied, GL changing (sunset, sunrise) will behave incorrectly
// ("leakage" of non-updated sunlight) // ("leakage" of non-updated sunlight)
@@ -269,11 +269,11 @@ public class LightmapRenderer {
catch (ArrayIndexOutOfBoundsException e) {} catch (ArrayIndexOutOfBoundsException e) {}
} }
private static Color toTargetColour(char raw) { private static char calculate(int x, int y) {
return new Col40().createSlickColor(raw); return calculate(x, y, false);
} }
private static char calculate(int x, int y){ private static char calculate(int x, int y, boolean doNotCalculateAmbient){
char lightLevelThis = 0; char lightLevelThis = 0;
int thisTerrain = Terrarum.game.map.getTileFromTerrain(x, y); int thisTerrain = Terrarum.game.map.getTileFromTerrain(x, y);
int thisWall = Terrarum.game.map.getTileFromWall(x, y); int thisWall = Terrarum.game.map.getTileFromWall(x, y);
@@ -316,46 +316,54 @@ public class LightmapRenderer {
} }
// calculate ambient if (!doNotCalculateAmbient) {
char ambient = 0; char nearby = 0; // calculate ambient
findNearbyBrightest: char ambient = 0;
for (int yoff = -1; yoff <= 1; yoff++) { char nearby = 0;
for (int xoff = -1; xoff <= 1; xoff++) { findNearbyBrightest:
/** for (int yoff = -1; yoff <= 1; yoff++) {
* filter for 'v's as: for (int xoff = -1; xoff <= 1; xoff++) {
* +-+-+-+ /**
* |a|v|a| * filter for 'v's as:
* +-+-+-+ * +-+-+-+
* |v| |v| * |a|v|a|
* +-+-+-+ * +-+-+-+
* |a|v|a| * |v| |v|
* +-+-+-+ * +-+-+-+
*/ * |a|v|a|
if (xoff != yoff && -xoff != yoff) { // 'v' tiles * +-+-+-+
if (!outOfMapBounds(x + xoff, y + yoff)) { */
nearby = staticLightMap[y + yoff][x + xoff]; if (xoff != yoff && -xoff != yoff) { // 'v' tiles
if (!outOfMapBounds(x + xoff, y + yoff)) {
nearby = staticLightMap[y + yoff][x + xoff];
}
} }
} else if (xoff != 0 && yoff != 0) { // 'a' tiles
else if (xoff != 0 && yoff != 0) { // 'a' tiles if (!outOfMapBounds(x + xoff, y + yoff)) {
if (!outOfMapBounds(x + xoff, y + yoff)) { nearby = darkenUniformInt(staticLightMap[y + yoff][x + xoff]
nearby = darkenUniformInt(staticLightMap[y + yoff][x + xoff] , 2); //2
, 2); //2 // mix some to have more 'spreading'
// mix some to have more 'spreading' // so that light spreads in a shape of an octagon instead of a diamond
// so that light spreads in a shape of an octagon instead of a diamond }
}
else {
nearby = 0; // exclude 'me' tile
} }
}
else {
nearby = 0; // exclude 'me' tile
}
ambient = maximiseRGB(ambient, nearby); // keep base value as brightest nearby ambient = maximiseRGB(ambient, nearby); // keep base value as brightest nearby
}
} }
ambient = darkenColoured(ambient,
thisTileOpacity
); // get real ambient by appling opacity value
// mix and return lightlevel and ambient
return maximiseRGB(lightLevelThis, ambient);
}
else {
return lightLevelThis;
} }
ambient = darkenColoured(ambient, thisTileOpacity); // get real ambient by appling opacity value
// mix and return lightlevel and ambient
return maximiseRGB(lightLevelThis, ambient);
} }
/** /**
@@ -582,13 +590,45 @@ public class LightmapRenderer {
} }
private static void purgePartOfLightmap(int x1, int y1, int x2, int y2) { private static void purgePartOfLightmap(int x1, int y1, int x2, int y2) {
for (int y = y1; y < y2; y++) { try {
for (int x = x1; x < x2; x++) { for (int y = y1 - 1; y < y2 + 1; y++) {
if (!outOfMapBounds(x, y)) { for (int x = x1 - 1; x < x2 + 1; x++) {
staticLightMap[y][x] = 0; if (y == y1 - 1 || y == y2 || x == x1 - 1 || x == x2) {
// fill the rim with (pre) calculation
staticLightMap[y][x] = preCalculateUpdateGLOnly(x, y);
}
else {
staticLightMap[y][x] = 0;
}
} }
} }
} }
catch (ArrayIndexOutOfBoundsException e) {}
}
private static char preCalculateUpdateGLOnly(int x, int y) {
int thisWall = Terrarum.game.map.getTileFromWall(x, y);
int thisTerrain = Terrarum.game.map.getTileFromTerrain(x, y);
char thisTileLuminosity = TilePropCodex.getProp(thisTerrain).getLuminosity();
char thisTileOpacity = TilePropCodex.getProp(thisTerrain).getOpacity();
char sunLight = Terrarum.game.map.getGlobalLight();
char lightLevelThis;
// MIX TILE
// open air
if (thisTerrain == AIR && thisWall == AIR) {
lightLevelThis = sunLight;
}
// luminous tile transparent (allows sunlight to pass)
else if (thisWall == AIR && thisTileLuminosity > 0) {
char darkenSunlight = darkenColoured(sunLight, thisTileOpacity);
lightLevelThis = screenBlend(darkenSunlight, thisTileLuminosity);
}
else {
lightLevelThis = getValueFromMap(x, y);
}
return lightLevelThis;
} }
private static int clampWTile(int x) { private static int clampWTile(int x) {
@@ -622,6 +662,10 @@ public class LightmapRenderer {
} }
return Math.round(sum / (float) i.length); return Math.round(sum / (float) i.length);
} }
private static Color toTargetColour(char raw) {
return new Col40().createSlickColor(raw);
}
} }
class LightmapLantern { class LightmapLantern {

View File

@@ -31,7 +31,7 @@ public class Terrarum extends StateBasedGame {
* *
* TARGET_INTERNAL_FPS > TARGET_FPS for smooth frame drawing * TARGET_INTERNAL_FPS > TARGET_FPS for smooth frame drawing
* *
* Must choose a value so that 1000 / VAL is still integer * Must choose a value so that (1000 / VAL) is still integer
*/ */
public static final int TARGET_INTERNAL_FPS = 100; public static final int TARGET_INTERNAL_FPS = 100;
@@ -116,6 +116,7 @@ public class Terrarum extends StateBasedGame {
appgc.setTargetFrameRate(TARGET_INTERNAL_FPS); appgc.setTargetFrameRate(TARGET_INTERNAL_FPS);
appgc.setVSync(VSYNC); appgc.setVSync(VSYNC);
appgc.setMaximumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS); appgc.setMaximumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS);
appgc.setMinimumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS - 1);
appgc.setShowFPS(false); appgc.setShowFPS(false);
appgc.setUpdateOnlyWhenVisible(false); appgc.setUpdateOnlyWhenVisible(false);

View File

@@ -103,10 +103,8 @@ public class BasicDebugInfoWindow implements UICanvas {
* Second column * Second column
*/ */
String[] collisionFlagKey = {"top", "right", "bottom", "left"};
int collisonFlag = playerDbg.eventMoving(); int collisonFlag = playerDbg.eventMoving();
printLineColumn(g, 2, 1, "CollisionFlag : " printLineColumn(g, 2, 1, "Vsync : " + Terrarum.appgc.isVSyncRequested());
+ ((collisonFlag == -1) ? "none" : collisionFlagKey[collisonFlag]));
printLineColumn(g, 2, 2, "Env colour temp : " + MapDrawer.getColTemp()); printLineColumn(g, 2, 2, "Env colour temp : " + MapDrawer.getColTemp());
/** /**