"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
*/
public final int COOLTIME = 500;
public final int INVINCIBILITY_TIME = 500;
/**
* Give new random ReferenceID and initialise ActorValue
@@ -180,7 +180,8 @@ public class ActorWithBody implements Actor, Visible, Glowing {
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();
updateHorizontalPos();
}
@@ -227,7 +228,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
private void updateVerticalPos() {
if (!isPlayerNoClip()) {
// check downward
if (veloY >= 0) { // use TERNARY for L/R!
if (veloY >= 0) {
// order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_BOTTOM)) {
adjustHitBottom();
@@ -273,7 +274,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
} while (colliding);
float newY = nextHitbox.getPointedY() - newYOff;
nextHitbox.setPositionFromPoint(newX - 1, newY);
nextHitbox.setPositionFromPoint(newX, newY);
}
private void adjustHitTop() {
@@ -290,13 +291,13 @@ public class ActorWithBody implements Actor, Visible, Glowing {
} while (colliding);
float newY = nextHitbox.getPosY() + newYOff;
nextHitbox.setPosition(newX + 1, newY);
nextHitbox.setPosition(newX, newY);
}
private void updateHorizontalPos() {
if (!isPlayerNoClip()) {
// check right
if (veloX > 0) { // use TERNARY for L/R!
if (veloX > 0) {
// order of the if-elseif chain is IMPORTANT
if (isColliding(CONTACT_AREA_RIGHT) && !isColliding(CONTACT_AREA_LEFT)) {
adjustHitRight();
@@ -309,8 +310,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
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
if (isColliding(CONTACT_AREA_LEFT) && !isColliding(CONTACT_AREA_RIGHT)) {
adjustHitLeft();
@@ -323,9 +323,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
else {
}
}
else {
}
}
}
@@ -362,7 +360,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
} while (newXOff < TSIZE && colliding);
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) {
@@ -721,3 +719,16 @@ public class ActorWithBody implements Actor, Visible, Glowing {
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.
* 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("name", "Sigrid");

View File

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

View File

@@ -1,6 +1,7 @@
package com.Torvald.Terrarum.ConsoleCommand;
import com.Torvald.ColourUtil.Col4096;
import com.Torvald.RasterWriter;
import com.Torvald.Terrarum.Terrarum;
import javax.imageio.ImageIO;
@@ -76,23 +77,12 @@ public class ExportMap implements ConsoleCommand {
}
try {
int[] bandOffsets = {0, 1, 2}; // RGB
DataBuffer buffer = new DataBufferByte(mapData, mapData.length);
WritableRaster raster = Raster.createInterleavedRaster(
buffer
, Terrarum.game.map.width
RasterWriter.writePNG_RGB(
Terrarum.game.map.width
, Terrarum.game.map.height
, 3 * Terrarum.game.map.width
, 3
, 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"));
, mapData
, dir + args[1] + ".png"
);
new Echo().execute("ExportMap: exported to " + args[1] + ".png");
} catch (IOException e) {

View File

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

View File

@@ -87,11 +87,11 @@ public class LightmapRenderer {
}
int for_y_start = div16(MapCamera.getCameraY()) - 1;
int for_x_start = div16(MapCamera.getCameraX()) - 1;
int for_y_start = div16(MapCamera.getCameraY()) - 1; // fix for premature lightmap rendering
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_x_end = clampWTile(for_x_start + div16(MapCamera.getRenderWidth()) + 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;
/**
* Updating order:
@@ -104,7 +104,7 @@ public class LightmapRenderer {
* 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
// ("leakage" of non-updated sunlight)
@@ -269,11 +269,11 @@ public class LightmapRenderer {
catch (ArrayIndexOutOfBoundsException e) {}
}
private static Color toTargetColour(char raw) {
return new Col40().createSlickColor(raw);
private static char calculate(int x, int y) {
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;
int thisTerrain = Terrarum.game.map.getTileFromTerrain(x, y);
int thisWall = Terrarum.game.map.getTileFromWall(x, y);
@@ -316,46 +316,54 @@ public class LightmapRenderer {
}
// calculate ambient
char ambient = 0; char nearby = 0;
findNearbyBrightest:
for (int yoff = -1; yoff <= 1; yoff++) {
for (int xoff = -1; xoff <= 1; xoff++) {
/**
* filter for 'v's as:
* +-+-+-+
* |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 (!doNotCalculateAmbient) {
// calculate ambient
char ambient = 0;
char nearby = 0;
findNearbyBrightest:
for (int yoff = -1; yoff <= 1; yoff++) {
for (int xoff = -1; xoff <= 1; xoff++) {
/**
* filter for 'v's as:
* +-+-+-+
* |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];
}
}
}
else if (xoff != 0 && yoff != 0) { // 'a' tiles
if (!outOfMapBounds(x + xoff, y + yoff)) {
nearby = darkenUniformInt(staticLightMap[y + yoff][x + xoff]
, 2); //2
// mix some to have more 'spreading'
// so that light spreads in a shape of an octagon instead of a diamond
else if (xoff != 0 && yoff != 0) { // 'a' tiles
if (!outOfMapBounds(x + xoff, y + yoff)) {
nearby = darkenUniformInt(staticLightMap[y + yoff][x + xoff]
, 2); //2
// mix some to have more 'spreading'
// 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) {
for (int y = y1; y < y2; y++) {
for (int x = x1; x < x2; x++) {
if (!outOfMapBounds(x, y)) {
staticLightMap[y][x] = 0;
try {
for (int y = y1 - 1; y < y2 + 1; y++) {
for (int x = x1 - 1; x < x2 + 1; x++) {
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) {
@@ -622,6 +662,10 @@ public class LightmapRenderer {
}
return Math.round(sum / (float) i.length);
}
private static Color toTargetColour(char raw) {
return new Col40().createSlickColor(raw);
}
}
class LightmapLantern {

View File

@@ -31,7 +31,7 @@ public class Terrarum extends StateBasedGame {
*
* 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;
@@ -116,6 +116,7 @@ public class Terrarum extends StateBasedGame {
appgc.setTargetFrameRate(TARGET_INTERNAL_FPS);
appgc.setVSync(VSYNC);
appgc.setMaximumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS);
appgc.setMinimumLogicUpdateInterval(1000 / TARGET_INTERNAL_FPS - 1);
appgc.setShowFPS(false);
appgc.setUpdateOnlyWhenVisible(false);

View File

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