mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-14 23:56:07 +09:00
"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:
22
src/com/Torvald/JsonWriter.java
Normal file
22
src/com/Torvald/JsonWriter.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
55
src/com/Torvald/RasterWriter.java
Normal file
55
src/com/Torvald/RasterWriter.java
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user