implemented tile connection draw, frosty area in map gen, fixed too less floating islands, ocean water now generates properly

Former-commit-id: d280e2f95c10f1060bfaa794b31d91965badc373
Former-commit-id: d0881343a802658b1fe0b2ad59561ca6ceb7a805
This commit is contained in:
Song Minjae
2016-02-06 00:48:25 +09:00
parent d5c99aad5e
commit 4ddd020d07
27 changed files with 490 additions and 286 deletions

View File

@@ -16,6 +16,10 @@ import org.newdawn.slick.Graphics;
*/
public class ActorWithBody implements Actor, Visible, Glowing {
ActorValue actorValue;
ActorInventory inventory;
private @NotNull float hitboxTranslateX; // relative to spritePosX
private @NotNull float hitboxTranslateY; // relative to spritePosY
private @NotNull int baseHitboxW;
@@ -29,8 +33,8 @@ public class ActorWithBody implements Actor, Visible, Glowing {
* veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*/
private @NotNull float veloX, veloY, veloMax;
private @NotNull float veloX, veloY;
private final float VELO_HARD_LIMIT = 10000;
private boolean grounded = false;
@@ -75,6 +79,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
public ActorWithBody() {
referenceID = new HighQualityRandom(0x7E22A211AAL).nextLong();
actorValue = new ActorValue();
}
public void setHitboxDimension(int w, int h, int tx, int ty) {
@@ -118,13 +123,21 @@ public class ActorWithBody implements Actor, Visible, Glowing {
baseSpriteWidth = sprite.getWidth();
gravitation = Game.map.getGravitation();
applyGravitation();
if (!playerNoClip()) {
applyGravitation();
}
//Set 'next' positions to fiddle with
// hard limit velocity
if (veloX > VELO_HARD_LIMIT) veloX = VELO_HARD_LIMIT;
if (veloY > VELO_HARD_LIMIT) veloY = VELO_HARD_LIMIT;
// Set 'next' positions to fiddle with
updateNextHitbox(delta_t);
updateVerticalPos();
updateHorizontalPos();
if (!playerNoClip()) {
updateVerticalPos();
updateHorizontalPos();
}
// Apply previous fiddling
updateHitbox();
@@ -204,26 +217,21 @@ public class ActorWithBody implements Actor, Visible, Glowing {
sprite.update(delta_t);
}
boolean collideBottomAndAdjust() {
boolean collideBottomAndAdjusted() {
// noclip off?
if (!(this instanceof Player && ((Player) this).isNoClip())) {
int feetTileX = clampWtile(Math.round((nextHitbox.getPointedX()) / TSIZE));
int feetTileY = clampHtile(FastMath.floor(nextHitbox.getPointedY() / TSIZE));
int feetTileX = clampWtile(Math.round((nextHitbox.getPointedX()) / TSIZE));
int feetTileY = clampHtile(FastMath.floor(nextHitbox.getPointedY() / TSIZE));
if (feetTileX < 0) feetTileX = 0;
if (feetTileY < 0) feetTileY = 0;
if (feetTileX < 0) feetTileX = 0;
if (feetTileY < 0) feetTileY = 0;
int feetTile = Game.map.getTileFromTerrain(feetTileX, feetTileY);
int feetTile = Game.map.getTileFromTerrain(feetTileX, feetTileY);
if (feetTile != 0) {
nextHitbox.setPositionYFromPoint(
feetTileY * TSIZE
);
return true;
}
else {
return false;
}
if (feetTile != 0) {
nextHitbox.setPositionYFromPoint(
feetTileY * TSIZE
);
return true;
}
else {
return false;
@@ -236,6 +244,8 @@ public class ActorWithBody implements Actor, Visible, Glowing {
* Apply only if not grounded; normal force is not implemented (and redundant)
* so we manually reset G to zero (not applying G. force) if grounded.
*/
// FIXME abnormal jump behaviour if mass == 1, same thing happens if mass == 0 but zero mass
// is invalid anyway.
private void applyGravitation() {
if (!isGrounded()) {
/**
@@ -250,22 +260,19 @@ public class ActorWithBody implements Actor, Visible, Glowing {
float A = scale * scale;
float D = DRAG_COEFF * 0.5f * 1.292f * veloY * veloY * A;
veloY += ((W - D) / mass) * SI_TO_GAME_ACC * G_MUL_PLAYABLE_CONST;
veloY += clampCeil(((W - D) / mass) * SI_TO_GAME_ACC * G_MUL_PLAYABLE_CONST
, VELO_HARD_LIMIT
);
}
}
private void updateVerticalPos() {
if (!playerNoClip()) {
if (collideBottomAndAdjust()) {
grounded = true;
veloY = 0;
}
else {
grounded = false;
}
if (collideBottomAndAdjusted()) {
grounded = true;
veloY = 0;
}
else {
grounded = true;
grounded = false;
}
}
@@ -363,6 +370,10 @@ public class ActorWithBody implements Actor, Visible, Glowing {
return x & 0b1111;
}
private static float clampCeil(float x, float ceil) {
return (Math.abs(x) > ceil ? ceil : x);
}
public void setVisible(boolean visible) {
this.visible = visible;
}
@@ -383,10 +394,6 @@ public class ActorWithBody implements Actor, Visible, Glowing {
this.veloY = veloY;
}
public void setVeloMax(float veloMax) {
this.veloMax = veloMax;
}
public void setGrounded(boolean grounded) {
this.grounded = grounded;
}
@@ -411,10 +418,6 @@ public class ActorWithBody implements Actor, Visible, Glowing {
return veloY;
}
public float getVeloMax() {
return veloMax;
}
public boolean isGrounded() {
return grounded;
}

View File

@@ -0,0 +1,122 @@
package com.Torvald.Terrarum.Actors;
import com.Torvald.Rand.Fudge3;
import com.Torvald.Rand.HighQualityRandom;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.newdawn.slick.SlickException;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
/**
* Created by minjaesong on 16-02-05.
*/
public class CreatureBuildFactory {
private static final String JSONPATH = "./res/raw/";
private static String jsonString = new String();
public ActorWithBody build(String jsonFileName) throws IOException, SlickException {
JsonObject jsonObj = readJson(jsonFileName);
ActorWithBody actor = new ActorWithBody();
String[] elementsString = {
"racename"
, "racenameplural"
};
String[] elementsFloat = {
"baseheight"
, "basemass"
, "toolsize"
, "encumbrance"
};
String[] elementsFloatVariable = {
"baseheight"
, "strength"
, "speed"
, "jumppower"
, "scale"
, "speed"
, "jump"
};
setAVStrings(actor, elementsString, jsonObj);
setAVFloats(actor, elementsFloat, jsonObj);
setAVFloatsVariable(actor, elementsFloatVariable, jsonObj);
actor.inventory = new ActorInventory((int) actor.actorValue.get("encumberance"), true);
return actor;
}
/**
* Fetch and set actor values that have 'variable' appended. E.g. strength
* @param p
* @param elemSet
* @param jsonObject
*/
private void setAVFloatsVariable(ActorWithBody p, String[] elemSet, JsonObject jsonObject) {
for (String s : elemSet) {
float baseValue = jsonObject.get(s).getAsFloat();
// roll fudge dice and get value [-3, 3] as [0, 6]
int varSelected = new Fudge3().create(new HighQualityRandom()).roll() + 3;
// get multiplier from json. Assuming percentile
int multiplier = jsonObject.get(s + "variable").getAsJsonArray().get(varSelected).getAsInt();
float realValue = baseValue * multiplier / 100f;
p.actorValue.set(s, realValue);
}
}
/**
* Fetch and set string actor values
* @param p
* @param elemSet
* @param jsonObject
*/
private void setAVStrings(ActorWithBody p, String[] elemSet, JsonObject jsonObject) {
for (String s : elemSet) {
p.actorValue.set(s, jsonObject.get(s).getAsString());
}
}
/**
* Fetch and set float actor values
* @param p
* @param elemSet
* @param jsonObject
*/
private void setAVFloats(ActorWithBody p, String[] elemSet, JsonObject jsonObject) {
for (String s : elemSet) {
p.actorValue.set(s, jsonObject.get(s).getAsFloat());
}
}
private JsonObject readJson(String jsonFileName) throws IOException {
readJsonFileAsString(jsonFileName);
JsonParser jsonParser = new JsonParser();
JsonObject jsonObj = jsonParser.parse(jsonString).getAsJsonObject();
return jsonObj;
}
private void readJsonFileAsString(String filename) throws IOException {
Files.lines(
FileSystems.getDefault().getPath(JSONPATH + filename)
).forEach(this::strAppend);
}
private void strAppend( String s) {
jsonString += s;
}
}

View File

@@ -12,10 +12,6 @@ public class PBFSigrid {
public Player build() throws SlickException {
Player p = new Player();
p.referenceID = Game.PLAYER_REF_ID;
p.setVisible(true);
p.sprite = new SpriteAnimation();
p.sprite.setDimension(28, 50);
p.sprite.setSpriteImage("res/graphics/sprites/test_player.png");
@@ -35,12 +31,12 @@ public class PBFSigrid {
p.actorValue = new ActorValue();
p.actorValue.set("scale", 1.0f);
p.actorValue.set("speed", 3.0f);
p.actorValue.set("speed", 4.0f);
p.actorValue.set("speedmult", 1.0f);
p.actorValue.set("accel", p.WALK_ACCEL_BASE);
p.actorValue.set("accelmult", 1.0f);
p.actorValue.set("jumppower", 6f);
p.actorValue.set("jumppower", 6.5f);
// in frames
p.actorValue.set("jumplength", 30f);
@@ -58,6 +54,8 @@ public class PBFSigrid {
p.inventory = new ActorInventory((int) p.actorValue.get("encumbrance"), true);
p.setPosition(2048 * 16, 300 * 16);
return p;
}

View File

@@ -1,5 +1,6 @@
package com.Torvald.Terrarum.Actors;
import com.Torvald.Terrarum.Game;
import com.Torvald.Terrarum.GameControl.EnumKeyFunc;
import com.Torvald.Terrarum.GameControl.KeyMap;
import com.Torvald.spriteAnimation.SpriteAnimation;
@@ -15,8 +16,6 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
@Nullable public Controllable vehicleRiding;
ActorValue actorValue;
int jumpPowerCounter = 0;
int walkPowerCounter = 0;
private final int WALK_FRAMES_TO_MAX_ACCEL = 6;
@@ -27,8 +26,6 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
@NotNull int walkHeading;
ActorInventory inventory;
private final int LEFT = 1;
private final int RIGHT = 2;
@@ -51,7 +48,8 @@ public class Player extends ActorWithBody implements Controllable, Pocketed {
*/
public Player() throws SlickException {
super();
actorValue = new ActorValue();
referenceID = Game.PLAYER_REF_ID;
setVisible(true);
}
@Override

View File

@@ -19,102 +19,13 @@ public class PlayerBuildFactory {
private static String jsonString = new String();
public Player build(String jsonFileName) throws IOException, SlickException {
JsonObject jsonObj = readJson(jsonFileName);
Player p = new Player();
Player p = (Player) (new CreatureBuildFactory().build("CreatureHuman"));
// attach sprite
String[] elementsString = {
"racename"
, "racenameplural"
};
String[] elementsFloat = {
"baseheight"
, "basemass"
, "toolsize"
, "encumbrance"
};
String[] elementsFloatVariable = {
"baseheight"
, "strength"
, "speed"
, "jumppower"
, "scale"
};
setAVStrings(p, elementsString, jsonObj);
setAVFloats(p, elementsFloat, jsonObj);
setAVFloatsVariable(p, elementsFloatVariable, jsonObj);
p.inventory = new ActorInventory((int) p.actorValue.get("encumberance"), true);
// do etc.
return p;
}
/**
* Fetch and set actor values that have 'variable' appended. E.g. strength
* @param p
* @param elemSet
* @param jsonObject
*/
private void setAVFloatsVariable(Player p, String[] elemSet, JsonObject jsonObject) {
for (String s : elemSet) {
float baseValue = jsonObject.get(s).getAsFloat();
// roll fudge dice and get value [-3, 3] as [0, 6]
int varSelected = new Fudge3().create(new HighQualityRandom()).roll() + 3;
// get multiplier from json. Assuming percentile
int multiplier = jsonObject.get(s + "variable").getAsJsonArray().get(varSelected).getAsInt();
float realValue = baseValue * multiplier / 100f;
p.actorValue.set(s, realValue);
}
}
/**
* Fetch and set string actor values
* @param p
* @param elemSet
* @param jsonObject
*/
private void setAVStrings(Player p, String[] elemSet, JsonObject jsonObject) {
for (String s : elemSet) {
p.actorValue.set(s, jsonObject.get(s).getAsString());
}
}
/**
* Fetch and set float actor values
* @param p
* @param elemSet
* @param jsonObject
*/
private void setAVFloats(Player p, String[] elemSet, JsonObject jsonObject) {
for (String s : elemSet) {
p.actorValue.set(s, jsonObject.get(s).getAsFloat());
}
}
private JsonObject readJson(String jsonFileName) throws IOException {
readJsonFileAsString(jsonFileName);
JsonParser jsonParser = new JsonParser();
JsonObject jsonObj = jsonParser.parse(jsonString).getAsJsonObject();
return jsonObj;
}
private void readJsonFileAsString(String filename) throws IOException {
Files.lines(
FileSystems.getDefault().getPath(JSONPATH + filename)
).forEach(this::strAppend);
}
private void strAppend( String s) {
jsonString += s;
}
}

View File

@@ -21,28 +21,33 @@ public class ExportMap implements ConsoleCommand {
private int mapDataPointer = 0;
private static final byte AIR = 0;
private static final byte COAL = 16;
private static final byte COPPER = 17;
private static final byte IRON = 18;
private static final byte GOLD = 19;
private static final byte COBALTITE = 20;
private static final byte ILMENITE = 21;
private static final byte AURICHALCUM = 22;
private static final byte DIAMOND = 23;
private static final byte RUBY = 24;
private static final byte EMERALD = 25;
private static final byte SAPPHIRE = 26;
private static final byte TOPAZ = 27;
private static final byte AMETHYST = 28;
private static final byte DIRT = 2;
private static final byte GRAVEL = 15;
private static final byte SAND = 14;
private static final byte STONE = 1;
private static final byte DIRT = 2;
private static final byte GRASS = 3;
private static final byte SAND = 13;
private static final byte GRAVEL = 14;
private static final byte COPPER = 15;
private static final byte IRON = 16;
private static final byte GOLD = 17;
private static final byte SILVER = 18;
private static final byte ILMENITE = 19;
private static final byte AURICHALCUM = 20;
private static final byte DIAMOND = 21;
private static final byte RUBY = 22;
private static final byte EMERALD = 23;
private static final byte SAPPHIRE = 24;
private static final byte TOPAZ = 25;
private static final byte AMETHYST = 26;
private static final byte SNOW = 27;
private static final byte ICE_FRAGILE = 28;
private static final byte ICE_NATURAL = 29;
private static final byte ICE_MAGICAL = 30;
private static final byte WATER = (byte) 239;
private static final byte LAVA = (byte) 255;
@@ -121,11 +126,9 @@ public class ExportMap implements ConsoleCommand {
colorTable.put(DIRT, new Col12(0x763));
colorTable.put(GRASS, new Col12(0x251));
colorTable.put(COAL, new Col12(0x221));
colorTable.put(COPPER, new Col12(0x6A8));
colorTable.put(IRON, new Col12(0xC75));
colorTable.put(GOLD, new Col12(0xCB6));
colorTable.put(COBALTITE, new Col12(0xDCD));
colorTable.put(ILMENITE, new Col12(0x8AB));
colorTable.put(AURICHALCUM, new Col12(0xD92));
@@ -142,6 +145,11 @@ public class ExportMap implements ConsoleCommand {
colorTable.put(SAND, new Col12(0xDCA));
colorTable.put(GRAVEL, new Col12(0x664));
colorTable.put(ICE_NATURAL, new Col12(0x9AB));
colorTable.put(ICE_MAGICAL, new Col12(0x7AC));
colorTable.put(ICE_FRAGILE, new Col12(0x6AF));
colorTable.put(SNOW, new Col12(0xCDE));
}

View File

@@ -1,5 +1,6 @@
package com.Torvald.Terrarum;
import com.Torvald.Rand.HighQualityRandom;
import com.Torvald.Terrarum.Actors.*;
import com.Torvald.Terrarum.ConsoleCommand.CommandDict;
import com.Torvald.Terrarum.GameControl.GameController;
@@ -73,6 +74,7 @@ public class Game {
MapGenerator.attachMap(map);
MapGenerator.setSeed(0x51621D);
//MapGenerator.setSeed(new HighQualityRandom().nextLong());
MapGenerator.generateMap();
new CommandDict();
@@ -80,7 +82,6 @@ public class Game {
// add new player and put it to actorContainer
//player = new Player();
player = new PBFSigrid().build();
player.setPosition(24, 24);
//player.setNoClip(true);
actorContainer.add(player);

View File

@@ -8,6 +8,8 @@ import com.Torvald.Terrarum.GameMap.MapLayer;
import com.jme3.math.FastMath;
import org.newdawn.slick.*;
import java.util.Arrays;
/**
* Created by minjaesong on 16-01-19.
*/
@@ -35,8 +37,6 @@ public class MapCamera {
private static int renderWidth;
private static int renderHeight;
private static final int TILE_AIR = 0;
private static final int NEARBY_TILE_KEY_UP = 0;
private static final int NEARBY_TILE_KEY_RIGHT = 1;
private static final int NEARBY_TILE_KEY_DOWN = 2;
@@ -47,6 +47,47 @@ public class MapCamera {
private static final int NEARBY_TILE_CODE_DOWN = 0b0100;
private static final int NEARBY_TILE_CODE_LEFT = 0b1000;
private static final byte AIR = 0;
private static final byte STONE = 1;
private static final byte DIRT = 2;
private static final byte GRASS = 3;
private static final byte SAND = 13;
private static final byte GRAVEL = 14;
private static final byte COPPER = 15;
private static final byte IRON = 16;
private static final byte GOLD = 17;
private static final byte SILVER = 18;
private static final byte ILMENITE = 19;
private static final byte AURICHALCUM = 20;
private static final byte SNOW = 27;
private static final byte ICE_FRAGILE = 28;
private static final byte ICE_NATURAL = 29;
private static final byte ICE_MAGICAL = 30;
private static final Byte[] TILES_CONNECT_SELF = {
COPPER
, IRON
, GOLD
, SILVER
, ILMENITE
, AURICHALCUM
, ICE_MAGICAL
};
private static final Byte[] TILES_DARKEN_AIR = {
STONE
, DIRT
, GRASS
, SAND
, GRAVEL
, SNOW
, ICE_NATURAL
};
/**
* @param map
* @param tileSize
@@ -146,7 +187,24 @@ public class MapCamera {
) {
if (mode == TERRAIN) {
int nearbyTilesInfo = getNearbyTilesInfo(x, y, TILE_AIR);
int nearbyTilesInfo;
//if (thisTile == DIRT) {
// nearbyTilesInfo = getGrassInfo(x, y, GRASS);
//}
//else {
// nearbyTilesInfo = getNearbyTilesInfo(x, y, AIR);
//}
if (isDarkenAir((byte) thisTile)) {
nearbyTilesInfo = getNearbyTilesInfo(x, y, AIR);
}
else if (isConnectSelf((byte) thisTile)) {
nearbyTilesInfo = getNearbyTilesInfo(x, y, thisTile);
}
else {
nearbyTilesInfo = 0;
}
int thisTileX = nearbyTilesInfo;
int thisTileY = thisTile;
@@ -164,6 +222,10 @@ public class MapCamera {
tilesetBook[mode].endUse();
}
private static int getGrassInfo(int x, int y, int from, int to) {
return 0;
}
/**
*
* @param x
@@ -172,22 +234,23 @@ public class MapCamera {
*/
private static int getNearbyTilesInfo(int x, int y, int mark) {
int[] nearbyTiles = new int[4];
if (x == 0) { nearbyTiles[NEARBY_TILE_KEY_LEFT] = 0; }
if (x == map.width - 1) { nearbyTiles[NEARBY_TILE_KEY_RIGHT] = 0; }
if (y == 0) { nearbyTiles[NEARBY_TILE_KEY_UP] = 0; }
if (y == map.height - 1) { nearbyTiles[NEARBY_TILE_KEY_DOWN] = 0; }
try {
nearbyTiles[NEARBY_TILE_KEY_UP] = map.getTileFromTerrain(x, y - 1);
nearbyTiles[NEARBY_TILE_KEY_DOWN] = map.getTileFromTerrain(x, y + 1);
nearbyTiles[NEARBY_TILE_KEY_LEFT] = map.getTileFromTerrain(x - 1, y);
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = map.getTileFromTerrain(x + 1, y);
}
catch (ArrayIndexOutOfBoundsException e) { }
if (x == 0) { nearbyTiles[NEARBY_TILE_KEY_LEFT] = 0xFF; }
else { nearbyTiles[NEARBY_TILE_KEY_LEFT] = map.getTileFromTerrain(x - 1, y); }
if (x == map.width - 1) { nearbyTiles[NEARBY_TILE_KEY_RIGHT] = 0xFF; }
else { nearbyTiles[NEARBY_TILE_KEY_RIGHT] = map.getTileFromTerrain(x + 1, y); }
if (y == 0) { nearbyTiles[NEARBY_TILE_KEY_UP] = 0; }
else { nearbyTiles[NEARBY_TILE_KEY_UP] = map.getTileFromTerrain(x, y - 1); }
if (y == map.height - 1) { nearbyTiles[NEARBY_TILE_KEY_DOWN] = 0xFF; }
else { nearbyTiles[NEARBY_TILE_KEY_DOWN] = map.getTileFromTerrain(x, y + 1); }
// try for
int ret = 0;
for (int i = 0; i < 4; i++) {
if (nearbyTiles[i] == mark) {
ret += (1 << i); // write 1, 2, 4, 8 for i = 0, 1, 2, 3
ret += (1 << i); // add 1, 2, 4, 8 for i = 0, 1, 2, 3
}
}
@@ -332,4 +395,12 @@ public class MapCamera {
public static int getRenderEndY() {
return clampHTile(getRenderStartY() + div16(renderHeight) + 2);
}
private static boolean isConnectSelf(byte b) {
return (Arrays.asList(TILES_CONNECT_SELF).contains(b));
}
private static boolean isDarkenAir(byte b) {
return (Arrays.asList(TILES_DARKEN_AIR).contains(b));
}
}

View File

@@ -17,53 +17,63 @@ public class MapGenerator {
private static int[] heightMap;
private static int dirtThickness;
private static int terrainHeightFromZeroPoint;
private static int TERRAIN_AVERAGE_HEIGHT;
private static int minimumFloatingIsleHeight;
private static final float noiseGradientStart = 0.67f;
private static final float noiseGradientEnd = 0.56f;
private static final float noiseGrdCaveEnd = 0.54f;
private static final float floatingIslandsProb = 0.63f;
private static final int HILL_WIDTH = 256; // power of two!
private static final int MAX_HILL_HEIGHT = 100;
private static final int OCEAN_WIDTH = 400;
private static final int SHORE_WIDTH = 120;
private static final int MAX_OCEAN_DEPTH = 200;
private static final int OCEAN_WIDTH = 200;
private static int GLACIER_MOUNTAIN_WIDTH;
private static final int GLACIER_MOUNTAIN_HEIGHT = 300;
private static final int MAX_HILL_HEIGHT = 200;
private static final byte AIR = 0;
private static final byte COPPER = 16;
private static final byte IRON = 17;
private static final byte GOLD = 18;
private static final byte SILVER = 19;
private static final byte ILMENITE = 20;
private static final byte AURICHALCUM = 21;
private static final byte DIAMOND = 22;
private static final byte RUBY = 23;
private static final byte EMERALD = 24;
private static final byte SAPPHIRE = 25;
private static final byte TOPAZ = 26;
private static final byte AMETHYST = 27;
private static final byte DIRT = 2;
private static final byte GRAVEL = 15;
private static final byte SAND = 14;
private static final byte STONE = 1;
private static final byte DIRT = 2;
private static final byte GRASS = 3;
private static final byte SNOW = 28;
private static final byte ICE_FRAGILE = 29;
private static final byte ICE_NATURAL = 30;
private static final byte SAND = 13;
private static final byte GRAVEL = 14;
private static final byte COPPER = 15;
private static final byte IRON = 16;
private static final byte GOLD = 17;
private static final byte SILVER = 18;
private static final byte ILMENITE = 19;
private static final byte AURICHALCUM = 20;
private static final byte DIAMOND = 21;
private static final byte RUBY = 22;
private static final byte EMERALD = 23;
private static final byte SAPPHIRE = 24;
private static final byte TOPAZ = 25;
private static final byte AMETHYST = 26;
private static final byte SNOW = 27;
private static final byte ICE_FRAGILE = 28;
private static final byte ICE_NATURAL = 29;
private static final byte ICE_MAGICAL = 30;
private static final byte WATER = (byte) 239;
private static final byte LAVA = (byte) 255;
@NotNull private static int worldOceanPosition;
private static final int TYPE_OCEAN_LEFT = 0;
private static final int TYPE_OCEAN_RIGHT = 1;
private static final int GRASSCUR_UP = 0;
private static final int GRASSCUR_RIGHT = 1;
private static final int GRASSCUR_DOWN = 2;
private static final int GRASSCUR_LEFT = 3;
public static void attachMap(GameMap map) {
MapGenerator.map = map;
width = map.width;
@@ -71,7 +81,7 @@ public class MapGenerator {
dirtThickness = (int) (100 * height / 1024f);
minimumFloatingIsleHeight = (int) (25 * (height / 1024f));
terrainHeightFromZeroPoint = height / 4;
TERRAIN_AVERAGE_HEIGHT = height / 4;
GLACIER_MOUNTAIN_WIDTH = Math.round(900 * (width / 8192f));
}
@@ -86,7 +96,7 @@ public class MapGenerator {
random = new HighQualityRandom(seed);
System.out.println("[MapGenerator] Seed: " + seed);
worldOceanPosition = random.nextInt() & 0x1; // 0 or 1
worldOceanPosition = random.nextBoolean() ? TYPE_OCEAN_LEFT : TYPE_OCEAN_RIGHT;
heightMap = raise2(MAX_HILL_HEIGHT / 2);
generateOcean(heightMap);
@@ -174,15 +184,13 @@ public class MapGenerator {
, "Planting coals..."
);*/
//flood
floodBottomLava();
//plant
freeze();
fillOcean();
plantGrass();
//post-process
generateFloatingIslands();
//fillOcean();
//wire layer
for (int i = 0; i < height; i++) {
@@ -268,16 +276,16 @@ public class MapGenerator {
if (worldOceanPosition == TYPE_OCEAN_LEFT) {
noiseArrayLocal[i] = Math.round(
interpolateCosine(
Math.round((float) (i) / OCEAN_WIDTH)
, -MAX_HILL_HEIGHT, oceanLeftP1
(float) (i) / OCEAN_WIDTH
, -MAX_OCEAN_DEPTH, oceanLeftP1
)
);
}
else if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
noiseArrayLocal[noiseArrayLocal.length - OCEAN_WIDTH + i] = Math.round(
interpolateCosine(
Math.round((float) (i) / OCEAN_WIDTH)
, oceanRightP1, -MAX_HILL_HEIGHT
(float) (i) / OCEAN_WIDTH
, oceanRightP1, -MAX_OCEAN_DEPTH
)
);
}
@@ -437,8 +445,8 @@ public class MapGenerator {
// iterate for heightmap
for (int x = 0; x < width; x++) {
int medianPosition = terrainHeightFromZeroPoint;
int pillarOffset = medianPosition - fs[x] - 1;
int medianPosition = TERRAIN_AVERAGE_HEIGHT;
int pillarOffset = medianPosition - fs[x];
// for pillar length
for (int i = 0; i < height - pillarOffset; i++) {
@@ -589,13 +597,13 @@ public class MapGenerator {
*/
private static float noiseMapGetGradientQuadPoly(int func_argX, float start, float end) {
float graph_gradient =
FastMath.pow(FastMath.sqr(1 - terrainHeightFromZeroPoint), -1) // 1/4 -> 3/4 -> 9/16 -> 16/9
FastMath.pow(FastMath.sqr(1 - TERRAIN_AVERAGE_HEIGHT), -1) // 1/4 -> 3/4 -> 9/16 -> 16/9
* (start - end) / FastMath.sqr(height)
* FastMath.sqr(func_argX - height)
+ end
;
if (func_argX < terrainHeightFromZeroPoint) {
if (func_argX < TERRAIN_AVERAGE_HEIGHT) {
return start;
}
else if (func_argX >= height) {
@@ -631,13 +639,13 @@ public class MapGenerator {
*/
private static float noiseMapGetGradientCubicPoly(int func_argX, float start, float end) {
float graph_gradient =
-FastMath.pow(FastMath.pow(1 - terrainHeightFromZeroPoint, 3), -1) // 1/4 -> 3/4 -> 9/16 -> 16/9
-FastMath.pow(FastMath.pow(1 - TERRAIN_AVERAGE_HEIGHT, 3), -1) // 1/4 -> 3/4 -> 9/16 -> 16/9
* (start - end) / FastMath.pow(height, 3)
* FastMath.pow(func_argX - height, 3)
+ end
;
if (func_argX < terrainHeightFromZeroPoint) {
if (func_argX < TERRAIN_AVERAGE_HEIGHT) {
return start;
}
else if (func_argX >= height) {
@@ -673,13 +681,13 @@ public class MapGenerator {
*/
private static float noiseMapGetGradientMinusQuadPoly(int func_argX, float start, float end) {
float graph_gradient =
-FastMath.pow(FastMath.sqr(1 - terrainHeightFromZeroPoint), -1) // 1/4 -> 3/4 -> 9/16 -> 16/9
-FastMath.pow(FastMath.sqr(1 - TERRAIN_AVERAGE_HEIGHT), -1) // 1/4 -> 3/4 -> 9/16 -> 16/9
* (start - end) / FastMath.sqr(height)
* FastMath.sqr(func_argX - terrainHeightFromZeroPoint)
* FastMath.sqr(func_argX - TERRAIN_AVERAGE_HEIGHT)
+ start
;
if (func_argX < terrainHeightFromZeroPoint) {
if (func_argX < TERRAIN_AVERAGE_HEIGHT) {
return start;
}
else if (func_argX >= height) {
@@ -693,7 +701,9 @@ public class MapGenerator {
private static void generateFloatingIslands() {
System.out.println("[MapGenerator] Placing floating islands...");
int nIslands = map.width / 1024;
int nIslandsMax = Math.round(map.width * 6f / 8192f);
int nIslandsMin = Math.max(2, Math.round(map.width * 4f / 8192f));
int nIslands = random.nextInt(nIslandsMax - nIslandsMin) + nIslandsMin;
int prevIndex = -1;
for (int i = 0; i < nIslands; i++) {
@@ -703,13 +713,14 @@ public class MapGenerator {
}
int[][] island = FloatingIslandsPreset.generatePreset(currentIndex, random);
int startingPosX = 1024 * i + 256 + random.nextInt(256);
int startingPosX = random.nextInt(map.width - 2048) + 1024;
int startingPosY = minimumFloatingIsleHeight + random.nextInt(minimumFloatingIsleHeight);
if (random.nextFloat() >= floatingIslandsProb) {
for (int j = 0; j < island.length; j++) {
for (int k = 0; k < island[0].length; k++) {
map.getTerrainArray()[j + startingPosY][k + startingPosX] = (byte) island[j][k];
for (int j = 0; j < island.length; j++) {
for (int k = 0; k < island[0].length; k++) {
if (island[j][k] > 0) {
map.getTerrainArray()[j + startingPosY][k + startingPosX]
= (byte) island[j][k];
}
}
}
@@ -723,7 +734,7 @@ public class MapGenerator {
for (int i = height * 14 / 15; i < height; i++) {
for (int j = 0; j < width; j++) {
if (map.getTerrainArray()[i][j] == 0) {
map.getTerrainArray()[i][j] = (byte) 0xFF;
map.getTerrainArray()[i][j] = LAVA;
}
}
}
@@ -734,89 +745,157 @@ public class MapGenerator {
private static void plantGrass() {
System.out.println("[MapGenerator] Planting grass...");
int[] heightMap = new int[width]; //where topmost block sits
/* TODO composing dirt and stone
* over certain level, use background dirt with stone 'peckles'
* beetween levels, use background dirt with larger and denser stone peckles.
* under another certain level, use background stone with dirt peckles.
*/
for (int i = 0; i < width; i++) {
//count down until hits block 2
int grassCounter = 0;
boolean hitDirt = false;
for (int y = TERRAIN_AVERAGE_HEIGHT - MAX_HILL_HEIGHT
; y < TERRAIN_AVERAGE_HEIGHT + MAX_HILL_HEIGHT
; y++) {
for (int x = 0; x < map.width; x++) {
while (grassCounter < height - 2 && map.getTerrainArray()[grassCounter][i] == 0) {
grassCounter++;
int thisTile = map.getTileFromTerrain(x, y);
for (int i = 0; i < 9; i++) {
int nearbyTile = -1;
try { nearbyTile = map.getTileFromTerrain(x + (i / 3) - 1, y + (i % 3) - 1); }
catch (ArrayIndexOutOfBoundsException e) {}
if (i != 4 && thisTile == DIRT && nearbyTile == AIR) {
map.getTerrainArray()[y][x] = GRASS;
break;
}
}
}
//actually hit grass or just counting halted?
if (map.getTerrainArray()[grassCounter][i] == 2) {
hitDirt = true;
}
//System.out.println(i+" ... "+grassCounter);
//plant grass
if (hitDirt) {
map.getTerrainArray()[grassCounter][i] = 3;
}
//compose heightMap
heightMap[i] = grassCounter;
}
}
private static boolean isGrassOrDirt(int x, int y) {
return map.getTileFromTerrain(x, y) == GRASS || map.getTileFromTerrain(x, y) == DIRT;
}
private static void replaceIfTerrain(byte ifTile, int x, int y, byte replaceTile) {
if (map.getTileFromTerrain(x, y) == ifTile) {
map.getTerrainArray()[y][x] = replaceTile;
}
}
private static void replaceIfWall(byte ifTile, int x, int y, byte replaceTile) {
if (map.getTileFromWall(x, y) == ifTile) {
map.getWallArray()[y][x] = replaceTile;
}
}
/* Post-process */
private static void fillOcean() {
int oceanLeftHeight = 0;
int oceanRightHeight = 0;
//get height
if (worldOceanPosition == TYPE_OCEAN_LEFT) {
while (map.getTerrainArray()[oceanLeftHeight][OCEAN_WIDTH] == 0) {
oceanLeftHeight++;
}
}
else if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
while (map.getTerrainArray()[oceanRightHeight][map.width - 1 - OCEAN_WIDTH] == 0) {
oceanRightHeight++;
}
}
for (int i = 0; i < OCEAN_WIDTH * 1.5; i++) {
int oceanDepthCounterLeft = 0;
int oceanDepthCounterRight = 0;
for (int ix = 0; ix < OCEAN_WIDTH * 1.5; ix++) {
//flooding
if (i < OCEAN_WIDTH) {
if (ix < OCEAN_WIDTH) {
if (worldOceanPosition == TYPE_OCEAN_LEFT) {
while (map.getTerrainArray()[oceanLeftHeight + oceanDepthCounterLeft][i] == 0) {
map.getTerrainArray()[oceanLeftHeight + oceanDepthCounterLeft][i] = (byte) 239;
oceanDepthCounterLeft++;
for (int y = getTerrainHeightFromHeightMap(OCEAN_WIDTH)
; y < getTerrainHeightFromHeightMap(ix)
; y++) {
map.getTerrainArray()
[y][ix] = WATER;
}
}
else if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
while (map.getTerrainArray()[oceanRightHeight + oceanDepthCounterRight][map.width - 1 - i] == 0) {
map.getTerrainArray()[oceanRightHeight + oceanDepthCounterRight][map.width - 1 - i] = (byte) 239;
oceanDepthCounterRight++;
for (int y = getTerrainHeightFromHeightMap(map.width - 1 - OCEAN_WIDTH)
; y < getTerrainHeightFromHeightMap(map.width - 1 - ix)
; y++) {
map.getTerrainArray()
[y][map.width - 1 - ix] = WATER;
}
}
}
//sand
for (int j = 0; j < 40 - (i * 40 / (OCEAN_WIDTH + 20)); j++) { //20 => seashore size
// linearly increase thickness of the sand sheet
for (int iy = 0; iy < 40 - (ix * 40 / (OCEAN_WIDTH + SHORE_WIDTH)); iy++) {
if (worldOceanPosition == TYPE_OCEAN_LEFT) {
map.getTerrainArray()[oceanLeftHeight + oceanDepthCounterLeft + j][i] = 14;
int terrainPoint = getTerrainHeightFromHeightMap(ix);
map.getTerrainArray()
[terrainPoint + iy]
[ix] = SAND;
map.getTerrainArray()
[terrainPoint + iy - 1] // clear grass and make the sheet thicker
[ix] = SAND;
}
else if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
map.getTerrainArray()[oceanRightHeight + oceanDepthCounterRight + j][map.width - 1 - i] = SAND;
int terrainPoint = getTerrainHeightFromHeightMap(map.width - 1 - ix);
map.getTerrainArray()
[terrainPoint + iy]
[map.width - 1 - ix] = SAND;
map.getTerrainArray()
[terrainPoint + iy - 1] // clear grass and make the sheet thicker
[map.width - 1 - ix] = SAND;
}
}
}
}
private static void freeze() {
for (int y = 0; y < map.height - 1; y++) {
for (int x = 0; x < getFrozenAreaWidth(y); x++) {
if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
replaceIfTerrain(DIRT, x, y, SNOW);
replaceIfTerrain(STONE, x, y, ICE_NATURAL);
replaceIfWall(DIRT, x, y, SNOW);
replaceIfWall(STONE, x, y, ICE_NATURAL);
}
else {
replaceIfTerrain(DIRT, map.width - 1 - x, y, SNOW);
replaceIfTerrain(STONE, map.width - 1 - x, y, ICE_NATURAL);
replaceIfWall(DIRT, map.width - 1 - x, y, SNOW);
replaceIfWall(STONE, map.width - 1 - x, y, ICE_NATURAL);
}
}
}
}
/**
*
* @return width of the frozen area for MapGenerator.freeze
*/
private static int getFrozenAreaWidth(int y) {
int randDeviation = 7;
// narrower that the actual width
int width = Math.round(GLACIER_MOUNTAIN_WIDTH * 0.625f);
int height;
if (worldOceanPosition == TYPE_OCEAN_RIGHT) {
height = getTerrainHeightFromHeightMap(width);
}
else {
height = getTerrainHeightFromHeightMap(map.width - 1 - width);
}
float k = (width) / FastMath.sqrt(height);
if (y < height) {
return width;
}
else {
return Math.round(
k * FastMath.sqrt(y)
);
}
}
/**
*
* @param x position of heightmap
* @return
*/
private static int getTerrainHeightFromHeightMap(int x) {
return TERRAIN_AVERAGE_HEIGHT - heightMap[x];
}
/* Utility */
private static int clampN(int clampNumber, int num) {

View File

@@ -39,7 +39,7 @@ public class Terrarum extends BasicGame {
public static String defaultDir;
public static String defaultSaveDir;
public static String gameLocale = "fr";
public static String gameLocale = "ko";
public static Font gameFontWhite;