Improvement to light blending (can mix sunlight to transparent and luminous tile), failed attempt to perturb terrain, need better algorithm

Former-commit-id: a8b456401859802fe5d19b7d12a41033f2ed3e44
Former-commit-id: 4f4a976e6f295f45519744216704c864afb6d621
This commit is contained in:
Song Minjae
2016-02-23 13:42:44 +09:00
parent 60fdff7528
commit 34a04943ab
25 changed files with 205 additions and 39 deletions

View File

@@ -31,3 +31,9 @@ Crafted tool/weapon size is dependent on the baseRaceMass.
* Gemstone tier
Topaz -> R·G·B -> Diamond·Amethyst
* Colouring
Natural: Use 4096
Magical/Surreal: Use 24 Bits

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

View File

@@ -2,7 +2,7 @@
"LANGUAGE_EN";"[LanguageName] in english";"English";"French";"Spanish";"German";"Italian ";"Portuguese (Brazil)";"Portuguese";"Russian";"Greek";"Turkish";"Danish";"Norwegian";"Swedish";"Dutch";"Polish";"Finnish";"Japanese";"Simplified Chinese";"Traditional Chinese";"Korean";"Czech";"Hungarian";"Romanian";"Thai";"Bulgarian";"Hebrew";"Japanese Kana";"Icelandic"
"LANGUAGE_ID";"IETF language tag(s) without dash";"enUS";"frFR";"esES";"deDE";"itIT";"ptBR";"ptPT";"ruRU";"elGR";"trTR";"daDK";"noNB";"svSE";"nlNL";"plPL";"fiFI";"jaJP";"zhCN";"zhTW";"koKR";"csCZ";"huHU";"roRO";"thTH";"bgBG";"heIL";"jakanaJP";"isIC"
"LANGUAGE_THIS";"MyLanguage'; in native text";"English";"Français";"Español";"Deutsch";"Italiano";"Português Brasileiro";"Português";"Pусский";"Ελληνικά";"Türkçe";"Dansk";"Norsk Bokmål";"Svenska";"Nederlands";"Polski";"Suomi";"日本語";"简体中文";"繁體中文";"한국어";"Čeština";"Magyar";"Română";"ภาษาไทย";"Български";"עברית";"にほんご";"íslenska"
"LANGUAGE_THIS";"MyLanguage'; in native text";"English";"Français";"Español";"Deutsch";"Italiano";"Português Brasileiro";"Português";"Pусский";"Ελληνικά";"Türkçe";"Dansk";"Norsk Bokmål";"Svenska";"Nederlands";"Polski";"Suomi";"日本語";"简体中文";"繁體中文";"한국어";"Čeština";"Magyar";"Română";"ภาษาไทย";"Български";"עברית";"にほんご";"Íslenska"
"LANGUAGE_DIRECTION";"ltr or rtl (text direction used by game code)";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"ltr";"rtl";"ltr";"ltr"
"CREDITS_POLYGLOT";"";"Translated by the Polyglot Project.";"Traduit par le Polyglot Projet.";"Traducido por el proyecto Polyglot.";"Übersetzt von Polyglot Project.";"Tradotto dal Polyglot Project.";"Traduzido pelo projeto Polyglot.";"Traduzido pelo projeto Polyglot.";"Перевод от проекта Polygon";"Μεταφράστηκε από το Polyglot Project.";"Polyglot Projesi ile çevrilmiştir.";"Oversat af Polyglot Projektet.";"Oversatt av Polyglot Prosjektet.";"Översättning av Polyglot-projektet.";"Vertaald door het Polyglot project.";"Przetłumaczono za pomocą Polyglot Project.";"Käännökset: Polyglot Project.";"翻訳提供Polyglotプロジェクト";"Polyglot 项目提供翻译";"翻譯由Polyglot Project 提供";"번역 제공: Polyglot Project.";"Překlad: Polyglot Projektu.";"Fordította a Polgylot Project.";"Tradus de către Polyglot Project.";"คำแปลโดย Polyglot Project";"Превод от проекта Polyglot.";"תורגם על-ידי פרויקט פוליגלוט.";"ほんやく ていきょうPolyglotプロジェクト";"Þýddur af verkefnið Polyglot"
1 STRING_ID IETF language tag(s) without dash enUS frFR esES deDE itIT ptBR ptPT ruRU elGR trTR daDK noNB svSE nlNL plPL fiFI jaJP zhCN zhTW koKR csCZ huHU roRO thTH bgBG heIL jakanaJP isIC
2 LANGUAGE_EN [LanguageName] in english English French Spanish German Italian Portuguese (Brazil) Portuguese Russian Greek Turkish Danish Norwegian Swedish Dutch Polish Finnish Japanese Simplified Chinese Traditional Chinese Korean Czech Hungarian Romanian Thai Bulgarian Hebrew Japanese Kana Icelandic
3 LANGUAGE_ID IETF language tag(s) without dash enUS frFR esES deDE itIT ptBR ptPT ruRU elGR trTR daDK noNB svSE nlNL plPL fiFI jaJP zhCN zhTW koKR csCZ huHU roRO thTH bgBG heIL jakanaJP isIC
4 LANGUAGE_THIS MyLanguage'; in native text English Français Español Deutsch Italiano Português Brasileiro Português Pусский Ελληνικά Türkçe Dansk Norsk Bokmål Svenska Nederlands Polski Suomi 日本語 简体中文 繁體中文 한국어 Čeština Magyar Română ภาษาไทย Български עברית にほんご íslenska Íslenska
5 LANGUAGE_DIRECTION ltr or rtl (text direction used by game code) ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr ltr rtl ltr ltr
6 CREDITS_POLYGLOT Translated by the Polyglot Project. Traduit par le Polyglot Projet. Traducido por el proyecto Polyglot. Übersetzt von Polyglot Project. Tradotto dal Polyglot Project. Traduzido pelo projeto Polyglot. Traduzido pelo projeto Polyglot. Перевод от проекта Polygon Μεταφράστηκε από το Polyglot Project. Polyglot Projesi ile çevrilmiştir. Oversat af Polyglot Projektet. Oversatt av Polyglot Prosjektet. Översättning av Polyglot-projektet. Vertaald door het Polyglot project. Przetłumaczono za pomocą Polyglot Project. Käännökset: Polyglot Project. 翻訳提供:Polyglotプロジェクト Polyglot 项目提供翻译 翻譯由Polyglot Project 提供 번역 제공: Polyglot Project. Překlad: Polyglot Projektu. Fordította a Polgylot Project. Tradus de către Polyglot Project. คำแปลโดย Polyglot Project Превод от проекта Polyglot. תורגם על-ידי פרויקט פוליגלוט. ほんやく ていきょう:Polyglotプロジェクト Þýddur af verkefnið Polyglot
7 CONTEXT_CHARACTER_DELETE Delete Character Supprimer personnage Eliminar personaje Character löschen Cancella personaggio Deletar Personagem Apagar personagem Удалить персонажа Διαγραφή Χαρακτήρα Karakteri Sil Slet karakter Slett karakter Radera karaktär Verwijder Personage Usuń Postać Poista hahmo キャラクター削除 删除角色 刪除角色 캐릭터 지우기 Smazat postavu Karakter törlése Șterge personaj ลบตัวละคร Изтрий персонаж למחוק דמות Eyða persónu
8 CONTEXT_CHARACTER_NEW Typically used in rpgs/mmorpgs New Character Nouveau personnage Nuevo personaje Neuer Charakter Nuovo personaggio Novo Personagem Nova personagem Новый персонаж Δημιουργία Χαρακτήρα Yeni Karakter Ny karakter Ny karakter Ny karaktär Nieuw Personage Nowa Postać Uusi hahmo 新規キャラクター 创新角色 創新角色 캐릭터 만들기 Nová postava Új karakter Personaj nou ตัวละครใหม่ Нов персонаж דמות חדשה Nýja persónu

View File

@@ -67,8 +67,15 @@ public class ActorWithBody implements Actor, Visible, Glowing {
* meter to pixel : 24/FPS
*/
private final float METER = 24f;
private final float SI_TO_GAME_ACC = METER / (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS);
/**
* [m / s^2] * SI_TO_GAME_ACC -> [px / IFrame^2]
*/
private final float SI_TO_GAME_ACC = METER / FastMath.sqr(Terrarum.TARGET_FPS);
/**
* [m / s] * SI_TO_GAME_VEL -> [px / IFrame]
*/
private final float SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS;
private float gravitation;
private final float DRAG_COEFF = 1f;

View File

@@ -55,7 +55,7 @@ public class Player extends ActorWithBody implements Controllable, Pocketed, Fac
private final int TSIZE = MapDrawer.TILE_SIZE;
private char LUMINANCE_RGB = 1560;
private char LUMINANCE_RGB = 31960;
private HashSet<Faction> factionSet = new HashSet<>();

View File

@@ -157,6 +157,14 @@ public class GameMap {
else throw new IllegalArgumentException("illegal mode input: " + String.valueOf(mode));
}
public void overwriteLayerWall(MapLayer layerData) {
layerWall = layerData;
}
public void overwriteLayerTerrain(MapLayer layerData) {
layerTerrain = layerData;
}
private int uint8ToInt32(byte x) {
int ret;
if ((x & 0b1000_0000) != 0) {

View File

@@ -109,6 +109,10 @@ public class MapLayer implements Iterable<Byte> {
return uint8ToInt32(data[y][x]);
}
public void setTile(int x, int y, byte tile) {
data[y][x] = tile;
}
private int uint8ToInt32(byte x) {
int ret;
if ((x & 0b1000_0000) != 0) {

View File

@@ -31,3 +31,9 @@ Crafted tool/weapon size is dependent on the baseRaceMass.
* Gemstone tier
Topaz -> R·G·B -> Diamond·Amethyst
* Colouring
Natural: Use 4096
Magical/Surreal: Use 24 Bits

View File

@@ -114,9 +114,9 @@ public class LightmapRenderer {
}
}
// Round 2
for (int y = for_y_start; y < for_y_end; y++) {
for (int x = for_x_end - 1; x >= for_x_start; x--) {
// Round 4
for (int y = for_y_end - 1; y > for_y_start; y--) {
for (int x = for_x_start; x < for_x_end; x++) {
staticLightMap[y][x] = calculate(x, y);
}
}
@@ -128,12 +128,13 @@ public class LightmapRenderer {
}
}
// Round 4
for (int y = for_y_end - 1; y > for_y_start; y--) {
for (int x = for_x_start; x < for_x_end; x++) {
// Round 2
for (int y = for_y_start; y < for_y_end; y++) {
for (int x = for_x_end - 1; x >= for_x_start; x--) {
staticLightMap[y][x] = calculate(x, y);
}
}
}
public static void draw(Graphics g) {
@@ -178,23 +179,21 @@ public class LightmapRenderer {
* d
*/
char a = (y == 0) ? thisLightLevel
: (y == Terrarum.game.map.height - 1) ? thisLightLevel
: max(staticLightMap[y][x]
: (y == Terrarum.game.map.height - 1) ? thisLightLevel
: maximiseRGB(staticLightMap[y][x]
, staticLightMap[y - 1][x]);
char d = (y == 0) ? thisLightLevel
: (y == Terrarum.game.map.height - 1) ? thisLightLevel
: max(staticLightMap[y][x]
: (y == Terrarum.game.map.height - 1) ? thisLightLevel
: maximiseRGB(staticLightMap[y][x]
, staticLightMap[y + 1][x]);
char b = (x == 0) ? thisLightLevel
: (x == Terrarum.game.map.width - 1) ? thisLightLevel
: max(staticLightMap[y][x]
: (x == Terrarum.game.map.width - 1) ? thisLightLevel
: maximiseRGB(staticLightMap[y][x]
, staticLightMap[y][x - 1]);
char c = (x == 0) ? thisLightLevel
: (x == Terrarum.game.map.width - 1) ? thisLightLevel
: max(staticLightMap[y][x]
: (x == Terrarum.game.map.width - 1) ? thisLightLevel
: maximiseRGB(staticLightMap[y][x]
, staticLightMap[y][x + 1]);
char t = staticLightMap[y][x];
char[] colourMapItoL = new char[4];
colourMapItoL[0] = colourLinearMix(a, b);
colourMapItoL[1] = colourLinearMix(a, c);
@@ -252,15 +251,21 @@ public class LightmapRenderer {
int thisTerrain = Terrarum.game.map.getTileFromTerrain(x, y);
int thisWall = Terrarum.game.map.getTileFromWall(x, y);
char thisTileLuminosity = TilePropCodex.getProp(thisTerrain).getLuminosity();
char thisTileOpacity = TilePropCodex.getProp(thisTerrain).getOpacity();
char sunLight = Terrarum.game.map.getGlobalLight();
// open air
if (thisTerrain == AIR && thisWall == AIR) {
lightLevelThis = screenBlend(lightLevelThis, Terrarum.game.map.getGlobalLight());
lightLevelThis = sunLight;
}
// mix luminous tile
if (thisTileLuminosity > 0) {
lightLevelThis = screenBlend(lightLevelThis, thisTileLuminosity);
// luminous tile transparent (allows sunlight to pass)
else if (thisWall == AIR && thisTileLuminosity < COLOUR_DOMAIN_SIZE) {
char darkenSunlight = darkenColoured(sunLight, thisTileOpacity);
lightLevelThis = screenBlend(darkenSunlight, thisTileLuminosity);
}
// luminous tile (opaque)
else {
lightLevelThis = thisTileLuminosity;
}
// mix lantern
@@ -282,7 +287,7 @@ public class LightmapRenderer {
}
// calculate and mix ambient
// calculate ambient
char ambient = 0; char nearby = 0;
findNearbyBrightest:
for (int yoff = -1; yoff <= 1; yoff++) {
@@ -305,7 +310,7 @@ public class LightmapRenderer {
else if (xoff != 0 && yoff != 0) { // 'a' tiles
if (!outOfMapBounds(x + xoff, y + yoff)) {
nearby = darkenUniformInt(staticLightMap[y + yoff][x + xoff]
, 2);
, 2); //2
// mix some to have more 'spreading'
// so that light spreads in a shape of an octagon instead of a diamond
}
@@ -314,14 +319,14 @@ public class LightmapRenderer {
nearby = 0; // exclude 'me' tile
}
ambient = additiveBlend(ambient, nearby); // keep base value as brightest nearby
ambient = maximiseRGB(ambient, nearby); // keep base value as brightest nearby
}
}
char opacity = TilePropCodex.getProp(thisTerrain).getOpacity();
ambient = darkenColoured(ambient, opacity); // get real ambient by appling opacity value
ambient = darkenColoured(ambient, thisTileOpacity); // get real ambient by appling opacity value
return screenBlend(lightLevelThis, ambient);
// mix and return lightlevel and ambient
return maximiseRGB(lightLevelThis, ambient);
}
else {
throw new IllegalArgumentException("Out of bounds of lightMap");
@@ -329,6 +334,9 @@ public class LightmapRenderer {
}
/**
* Subtract each channel's RGB value.
* It works like:
* f(data, darken) = RGB(data.r - darken.r, data.g - darken.g, data.b - darken.b)
*
* @param data Raw channel value [0-39] per channel
* @param darken [0-39] per channel
@@ -347,6 +355,8 @@ public class LightmapRenderer {
/**
* Darken each channel by 'darken' argument
* It works like:
* f(data, darken) = RGB(data.r - darken, data.g - darken, data.b - darken)
* @param data [0-39] per channel
* @param darken [0-1]
* @return
@@ -364,6 +374,8 @@ public class LightmapRenderer {
/**
* Darken each channel by 'darken' argument
* It works like:
* f(data, darken) = RGB(data.r - darken, data.g - darken, data.b - darken)
* @param data [0-39] per channel
* @param darken [0-39]
* @return
@@ -381,7 +393,9 @@ public class LightmapRenderer {
/**
*
* Add each channel's RGB value.
* It works like:
* f(data, brighten) = RGB(data.r + darken.r, data.g + darken.g, data.b + darken.b)
* @param data Raw channel value [0-39] per channel
* @param brighten [0-39] per channel
* @return brightened data [0-39] per channel
@@ -397,13 +411,12 @@ public class LightmapRenderer {
return constructRGBFromFloat(r, g, b);
}
/**
*
/** Get each channel from two RGB values, return new RGB that has max value of each channel
* @param rgb
* @param rgb2
* @return
*/
private static char additiveBlend(char rgb, char rgb2) {
private static char maximiseRGB(char rgb, char rgb2) {
int r1 = getRawR(rgb); int r2 = getRawR(rgb2); int newR = (r1 > r2) ? r1 : r2;
int g1 = getRawG(rgb); int g2 = getRawG(rgb2); int newG = (g1 > g2) ? g1 : g2;
int b1 = getRawB(rgb); int b2 = getRawB(rgb2); int newB = (b1 > b2) ? b1 : b2;
@@ -505,12 +518,12 @@ public class LightmapRenderer {
return (x << 4);
}
private static char max(char... i) {
private static int max(int... i) {
Arrays.sort(i);
return i[i.length - 1];
}
private static char min(char... i) {
private static int min(int... i) {
Arrays.sort(i);
return i[0];
}

View File

@@ -2,6 +2,7 @@ package com.Torvald.Terrarum.MapGenerator;
import com.Torvald.Rand.HQRNG;
import com.Torvald.Terrarum.GameMap.GameMap;
import com.Torvald.Terrarum.GameMap.MapLayer;
import com.Torvald.Terrarum.TileProperties.TileNameCode;
import com.jme3.math.FastMath;
import com.sun.istack.internal.NotNull;
@@ -34,6 +35,10 @@ public class MapGenerator {
private static int SHORE_WIDTH = 120;
private static int MAX_OCEAN_DEPTH = 200;
private static final int TERRAIN_PERTURB_OFFSETMAX = 32; // [-val , val]
private static final int TERRAIN_PERTURB_LARGESTFEATURE = 256;
private static final float TERRAIN_PERTURB_RATE = 0.5f;
private static int GLACIER_MOUNTAIN_WIDTH = 900;
private static final int GLACIER_MOUNTAIN_HEIGHT = 300;
@@ -89,8 +94,10 @@ public class MapGenerator {
placeGlacierMount(heightMap);
heightMapToObjectMap(heightMap);
perturbTerrain();
carveCave(
caveGen(1, 1.2f)
caveGen(1.4f, 1.7f)
, TileNameCode.AIR
, "Carving out cave..."
);
@@ -518,6 +525,70 @@ public class MapGenerator {
}
}
}
private static void perturbTerrain() {
SimplexNoise perturbGen = new SimplexNoise(TERRAIN_PERTURB_LARGESTFEATURE
, TERRAIN_PERTURB_RATE, seed ^ random.nextLong());
float[][] perturbMap = new float[height][width];
byte[][] layerWall = map.getWallArray();
byte[][] layerTerrain = map.getTerrainArray();
MapLayer newLayerWall = new MapLayer(width, height);
MapLayer newLayerTerrain = new MapLayer(width, height);
float lowestNoiseVal = 10000f;
float highestNoiseVal = -10000f;
for (int y = 0; y < map.height; y++) {
for (int x = 0; x < map.width; x++) {
float noise = perturbGen.getNoise(x, y); // [-1, 1]
perturbMap[y][x] = noise;
if (noise < lowestNoiseVal) lowestNoiseVal = noise;
if (noise > highestNoiseVal) highestNoiseVal = noise;
}
}
// Auto-scale noise [-1, 1]
/**
* See ./work_files/Linear_autoscale.gcx
*/
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float noiseInit = perturbMap[y][x];
float noiseFin = (noiseInit - ((highestNoiseVal + lowestNoiseVal) / 2f))
* (2f / (highestNoiseVal - lowestNoiseVal));
perturbMap[y][x] = noiseFin;
}
}
// Perturb to x-axis, apply to newLayer
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float offsetOrigin = perturbMap[y][x] * 0.5f + 0.5f; // [0 , 1]
int offset = Math.round(offsetOrigin * TERRAIN_PERTURB_OFFSETMAX);
byte tileWall = layerWall[y][x];
byte tileTerrain = layerTerrain[y][x];
try {
//newLayerWall.setTile(x + offset, y, tileWall);
//newLayerTerrain.setTile(x + offset, y, tileTerrain);
//layerWall[y][x] = 0;
//layerTerrain[y][x] = 0;
layerWall[y - offset][x] = tileWall;
layerTerrain[y - offset][x] = tileTerrain;
}
catch (ArrayIndexOutOfBoundsException e) {
}
}
}
// set reference (pointer) of original map layer to new layers
//map.overwriteLayerWall(newLayerWall);
//map.overwriteLayerTerrain(newLayerTerrain);
}

Binary file not shown.

View File

@@ -0,0 +1,30 @@
MUL = 40
MUL_2 = MUL ** 2
MAX_STEP = MUL - 1
def getch(eightbit):
return int(round(eightbit / 255.0 * MAX_STEP))
def getR(rgb24):
return (rgb24 >> 16) & 0xFF
def getG(rgb24):
return (rgb24 >> 8) & 0xFF
def getB(rgb24):
return rgb24 & 0xFF
def getR40(raw):
return raw / MUL_2
def getG40(raw):
return (raw % MUL_2) / MUL
def getB40(raw):
return raw % MUL
def intFromCol(r, g, b):
return r * MUL_2 + g * MUL + b
def colFromNum(raw):
return getR40(raw), getG40(raw), getB40(raw)
print(intFromCol(19,39,0))

View File

@@ -0,0 +1,21 @@
# usage: pypy scriptname inputfile outputfile
import sys
def bandlimit(i):
key = (i & 0xF0) >> 4
return (key << 4) | key
outcontents = []
infile = open(sys.argv[1], "rb").read()
for i in infile:
#print(ord(i))
outcontents.append(bandlimit(ord(i)))
outfile = open(sys.argv[2], "wb")
outfile.write(bytearray(outcontents))
outfile.close()