rename TARGET_FPS to PHYS_TIME_FRAME; shader to use multiple atlas tex; and things

This commit is contained in:
Minjae Song
2018-12-16 15:30:25 +09:00
parent cd752bc763
commit a7d12b2b54
9 changed files with 87 additions and 33 deletions

View File

@@ -1,3 +1,13 @@
/*
Texture binding:
0 <- Tiles atlas
1 <- Tiles buffer that holds tiles to be drawn
2 <- Fluid tiles atlas
*/
#version 120 #version 120
#ifdef GL_ES #ifdef GL_ES
precision mediump float; precision mediump float;
@@ -16,7 +26,7 @@ uniform vec2 screenDimension;
uniform vec2 tilesInAxes; // vec2(tiles_in_horizontal, tiles_in_vertical) uniform vec2 tilesInAxes; // vec2(tiles_in_horizontal, tiles_in_vertical)
uniform ivec2 tilemapDimension; uniform ivec2 tilemapDimension;
uniform sampler2D tilemap; // RGB888, A is optional and will be completely ignored uniform sampler2D tilemap; // RGBA8888
uniform sampler2D tilesAtlas; uniform sampler2D tilesAtlas;
uniform sampler2D backgroundTexture; uniform sampler2D backgroundTexture;
@@ -34,23 +44,29 @@ ivec2 getTileXY(int tileNumber) {
return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x)); return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x));
} }
// return: int=0xrrggbb // return: int=0xaarrggbb
int _colToInt(vec4 color) { int _colToInt(vec4 color) {
return int(color.b * 255) | (int(color.g * 255) << 8) | (int(color.r * 255) << 16); return int(color.b * 255) | (int(color.g * 255) << 8) | (int(color.r * 255) << 16) | (int(color.a * 255) << 24);
} }
// 0x0rggbb where int=0xaarrggbb // 0x0rggbb where int=0xaarrggbb
// return: [0..1048575] // return: [0..1048575]
int getTileFromColor(vec4 color) { int getTileFromColor(vec4 color) {
return _colToInt(color) & 0x0FFFFF; return _colToInt(color) & 0xFFFFF;
} }
// 0xr00000 where int=0xaarrggbb // 0x00r00000 where int=0xaarrggbb
// return: [0..15] // return: [0..15]
int getBreakageFromColor(vec4 color) { int getBreakageFromColor(vec4 color) {
return (_colToInt(color) >> 20) & 0xF; return (_colToInt(color) >> 20) & 0xF;
} }
// 0xa0000000 where int=0xaarrggbb
// return: [0..15]
int getTextureIndexFromColor(vec4 color) {
return (_colToInt(color) >> 28) & 0xF;
}
void main() { void main() {
// READ THE FUCKING MANUAL, YOU DONKEY !! // // READ THE FUCKING MANUAL, YOU DONKEY !! //

View File

@@ -31,30 +31,57 @@ public class AppLoader implements ApplicationListener {
* BB: Minor version * BB: Minor version
* XXXX: Revision (Repository commits, or something arbitrary) * XXXX: Revision (Repository commits, or something arbitrary)
* *
* e.g. 0x02010034 can be translated as 2.1.52 * e.g. 0x02010034 will be translated as 2.1.52
*/ */
public static final int VERSION_RAW = 0x00_02_027C; public static final int VERSION_RAW = 0x00_02_027C;
public static final String getVERSION_STRING() {
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
}
/**
* when FALSE, some assertion and print code will not execute
*/
public static final boolean IS_DEVELOPMENT_BUILD = true; public static final boolean IS_DEVELOPMENT_BUILD = true;
/**
* Singleton instance
*/
private static AppLoader INSTANCE = null; private static AppLoader INSTANCE = null;
/**
* Screen injected at init, so that you run THAT screen instead of the main game.
*/
private static Screen injectScreen = null; private static Screen injectScreen = null;
/**
* Initialise the application with the alternative Screen you choose
* @param appConfig LWJGL(2) Application Configuration
* @param injectScreen GDX Screen you want to run
*/
public AppLoader(LwjglApplicationConfiguration appConfig, Screen injectScreen) { public AppLoader(LwjglApplicationConfiguration appConfig, Screen injectScreen) {
AppLoader.injectScreen = injectScreen; AppLoader.injectScreen = injectScreen;
AppLoader.appConfig = appConfig; AppLoader.appConfig = appConfig;
} }
/**
* Initialise the application with default game screen
* @param appConfig LWJGL(2) Application Configuration
*/
public AppLoader(LwjglApplicationConfiguration appConfig) { public AppLoader(LwjglApplicationConfiguration appConfig) {
AppLoader.appConfig = appConfig; AppLoader.appConfig = appConfig;
} }
/**
* Default null constructor. Don't use it.
*/
public AppLoader() { public AppLoader() {
} }
/**
* Singleton pattern implementation in Java.
* @return
*/
public static AppLoader getINSTANCE() { public static AppLoader getINSTANCE() {
if (INSTANCE == null) { if (INSTANCE == null) {
INSTANCE = new AppLoader(); INSTANCE = new AppLoader();
@@ -66,6 +93,9 @@ public class AppLoader implements ApplicationListener {
public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2018 Torvald (minjaesong)"; public static final String COPYRIGHT_DATE_NAME = "Copyright 2013-2018 Torvald (minjaesong)";
public static String GAME_LOCALE = System.getProperty("user.language") + System.getProperty("user.country"); public static String GAME_LOCALE = System.getProperty("user.language") + System.getProperty("user.country");
/**
* These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA)
*/
private static final String[] localeSimple = {"de", "en", "es", "it"}; // must be sorted!! private static final String[] localeSimple = {"de", "en", "es", "it"}; // must be sorted!!
public static String getSysLang() { public static String getSysLang() {
@@ -93,10 +123,6 @@ public class AppLoader implements ApplicationListener {
} }
} }
public static final String getVERSION_STRING() {
return String.format("%d.%d.%d", VERSION_RAW >>> 24, (VERSION_RAW & 0xff0000) >>> 16, VERSION_RAW & 0xFFFF);
}
public static LwjglApplicationConfiguration appConfig; public static LwjglApplicationConfiguration appConfig;
public static GameFontBase fontGame; public static GameFontBase fontGame;

View File

@@ -86,17 +86,17 @@ object Terrarum : Screen {
/** /**
* To be used with physics simulator * To be used with physics simulator
*/ */
val TARGET_FPS: Double = 26.0 + (2.0 / 3.0) val PHYS_TIME_FRAME: Double = 26.0 + (2.0 / 3.0)
// 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!) // 26.0 + (2.0 / 3.0) // lower value == faster gravity response (IT WON'T HOTSWAP!!)
// protip: using METER, game unit and SI unit will have same number // protip: using METER, game unit and SI unit will have same number
/** /**
* To be used with render, to achieve smooth frame drawing * To be used with render, to achieve smooth frame drawing
* TARGET_INTERNAL_FPS > TARGET_FPS for smooth frame drawing * TARGET_INTERNAL_FPS > PHYS_TIME_FRAME for smooth frame drawing
*/ */
val TARGET_INTERNAL_FPS: Double = 60.0 val TARGET_INTERNAL_FPS: Double = 60.0
internal val UPDATE_CATCHUP_MAX_TRIES = 10 internal val UPDATE_CATCHUP_MAX_TRIES = 4

View File

@@ -506,7 +506,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* weight; gravitational force in action * weight; gravitational force in action
* W = mass * G (9.8 [m/s^2]) * W = mass * G (9.8 [m/s^2])
*/ */
val W: Vector2 = gravitation * Terrarum.TARGET_FPS.toDouble() val W: Vector2 = gravitation * Terrarum.PHYS_TIME_FRAME.toDouble()
/** /**
* Area * Area
*/ */
@@ -517,7 +517,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
*/ */
val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble() val D: Vector2 = Vector2(externalForce.x.magnSqr(), externalForce.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / Terrarum.TARGET_FPS * SI_TO_GAME_ACC val V: Vector2 = (W - D) / Terrarum.PHYS_TIME_FRAME * SI_TO_GAME_ACC
return V return V
} }
@@ -833,7 +833,7 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
// slam-into-whatever damage (such dirty; much hack; wow) // slam-into-whatever damage (such dirty; much hack; wow)
// vvvv hack (supposed to be 1.0) vvv 50% hack // vvvv hack (supposed to be 1.0) vvv 50% hack
val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.TARGET_FPS).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC val collisionDamage = mass * (vectorSum.magnitude / (10.0 / Terrarum.PHYS_TIME_FRAME).sqr()) / fallDamageDampening.sqr() * GAME_TO_SI_ACC
// kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI() // kg * m / s^2 (mass * acceleration), acceleration -> (vectorMagn / (0.01)^2).gameToSI()
if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N") if (collisionDamage != 0.0) debug1("Collision damage: $collisionDamage N")
// FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills // FIXME instead of 0.5mv^2, we can model after "change of velocity (aka accel)", just as in real-life; big change of accel on given unit time is what kills
@@ -1492,16 +1492,16 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
/** /**
* [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2] * [m / s^2] * SI_TO_GAME_ACC -> [px / InternalFrame^2]
*/ */
@Transient val SI_TO_GAME_ACC = METER / (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS) @Transient val SI_TO_GAME_ACC = METER / (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME)
/** /**
* [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame] * [m / s] * SI_TO_GAME_VEL -> [px / InternalFrame]
*/ */
@Transient val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS @Transient val SI_TO_GAME_VEL = METER / Terrarum.PHYS_TIME_FRAME
/** /**
* [px / InternalFrame^2] * GAME_TO_SI_ACC -> [m / s^2] * [px / InternalFrame^2] * GAME_TO_SI_ACC -> [m / s^2]
*/ */
@Transient val GAME_TO_SI_ACC = (Terrarum.TARGET_FPS * Terrarum.TARGET_FPS) / METER @Transient val GAME_TO_SI_ACC = (Terrarum.PHYS_TIME_FRAME * Terrarum.PHYS_TIME_FRAME) / METER
/** /**

View File

@@ -481,6 +481,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
} }
else { else {
var updateTries = 0 var updateTries = 0
val oldDeltaCtr = updateDeltaCounter
while (updateDeltaCounter >= renderRate) { while (updateDeltaCounter >= renderRate) {
//updateGame(delta) //updateGame(delta)
@@ -490,6 +491,7 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
updateTries++ updateTries++
if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) { if (updateTries >= Terrarum.UPDATE_CATCHUP_MAX_TRIES) {
printdbg(this, "Update couldn't catch up -- delta-T buildup was $oldDeltaCtr seconds")
break break
} }
} }

View File

@@ -533,7 +533,7 @@ open class ActorHumanoid(
} }
field = frames * (1.0 / Terrarum.TARGET_FPS) field = frames * (1.0 / Terrarum.PHYS_TIME_FRAME)
// fixme: looks good but return value is wrong -- 2.25 seconds? when I jump it barely goes past 1 sec // fixme: looks good but return value is wrong -- 2.25 seconds? when I jump it barely goes past 1 sec

View File

@@ -50,6 +50,8 @@ object WorldSimulator {
private val world = (Terrarum.ingame!!.world) private val world = (Terrarum.ingame!!.world)
operator fun invoke(p: ActorHumanoid?, delta: Float) { operator fun invoke(p: ActorHumanoid?, delta: Float) {
//printdbg(this, "============================") //printdbg(this, "============================")
@@ -77,8 +79,8 @@ object WorldSimulator {
fun moveFluids(delta: Float) { fun moveFluids(delta: Float) {
makeFluidMapFromWorld() makeFluidMapFromWorld()
//simCompression() simCompression()
for (y in 1 until fluidMap.size - 1) { /*for (y in 1 until fluidMap.size - 1) {
for (x in 1 until fluidMap[0].size - 1) { for (x in 1 until fluidMap[0].size - 1) {
val worldX = x + updateXFrom val worldX = x + updateXFrom
val worldY = y + updateYFrom val worldY = y + updateYFrom
@@ -105,7 +107,7 @@ object WorldSimulator {
fluidNewTypeMap[y + 1][x] = remainingType fluidNewTypeMap[y + 1][x] = remainingType
} }
} }
} }*/
if (AppLoader.IS_DEVELOPMENT_BUILD) { if (AppLoader.IS_DEVELOPMENT_BUILD) {
monitorIllegalFluidSetup() // non-air non-zero fluid is kinda inevitable monitorIllegalFluidSetup() // non-air non-zero fluid is kinda inevitable
@@ -183,6 +185,7 @@ object WorldSimulator {
// after data: fluidNewMap/fluidNewTypeMap // after data: fluidNewMap/fluidNewTypeMap
var flow = 0f var flow = 0f
var remainingMass = 0f var remainingMass = 0f
var remainingType = Fluid.NULL
for (y in 1 until fluidMap.size - 1) { for (y in 1 until fluidMap.size - 1) {
for (x in 1 until fluidMap[0].size - 1) { for (x in 1 until fluidMap[0].size - 1) {
@@ -197,12 +200,13 @@ object WorldSimulator {
// Custom push-only flow // Custom push-only flow
flow = 0f flow = 0f
remainingMass = fluidMap[y][x] remainingMass = fluidNewMap[y][x]
remainingType = fluidNewTypeMap[y][x]
if (remainingMass <= 0) continue if (remainingMass <= 0) continue
// The block below this one // The block below this one
if (!isSolid(worldX, worldY + 1)) { // TODO use isFlowable if (!isSolid(worldX, worldY + 1)) { // TODO use isFlowable
flow = getStableStateB(remainingMass + fluidMap[y + 1][x]) - fluidMap[y + 1][x] flow = getStableStateB(remainingMass + fluidNewMap[y + 1][x]) - fluidNewMap[y + 1][x]
if (flow > minFlow) { if (flow > minFlow) {
flow *= 0.5f // leads to smoother flow flow *= 0.5f // leads to smoother flow
} }
@@ -210,6 +214,7 @@ object WorldSimulator {
fluidNewMap[y][x] -= flow fluidNewMap[y][x] -= flow
fluidNewMap[y + 1][x] += flow fluidNewMap[y + 1][x] += flow
fluidNewTypeMap[y + 1][x] = remainingType
remainingMass -= flow remainingMass -= flow
} }
@@ -218,7 +223,7 @@ object WorldSimulator {
// Left // Left
if (!isSolid(worldX - 1, worldY)) { // TODO use isFlowable if (!isSolid(worldX - 1, worldY)) { // TODO use isFlowable
// Equalise the amount fo water in this block and its neighbour // Equalise the amount fo water in this block and its neighbour
flow = (fluidMap[y][x] - fluidMap[y][x - 1]) / 4f flow = (fluidNewMap[y][x] - fluidNewMap[y][x - 1]) / 4f
if (flow > minFlow) { if (flow > minFlow) {
flow *= 0.5f flow *= 0.5f
} }
@@ -226,6 +231,7 @@ object WorldSimulator {
fluidNewMap[y][x] -= flow fluidNewMap[y][x] -= flow
fluidNewMap[y][x - 1] += flow fluidNewMap[y][x - 1] += flow
fluidNewTypeMap[y][x - 1] = remainingType
remainingMass -= flow remainingMass -= flow
} }
@@ -234,7 +240,7 @@ object WorldSimulator {
// Right // Right
if (!isSolid(worldX + 1, worldY)) { // TODO use isFlowable if (!isSolid(worldX + 1, worldY)) { // TODO use isFlowable
// Equalise the amount fo water in this block and its neighbour // Equalise the amount fo water in this block and its neighbour
flow = (fluidMap[y][x] - fluidMap[y][x + 1]) / 4f flow = (fluidNewMap[y][x] - fluidNewMap[y][x + 1]) / 4f
if (flow > minFlow) { if (flow > minFlow) {
flow *= 0.5f flow *= 0.5f
} }
@@ -242,6 +248,7 @@ object WorldSimulator {
fluidNewMap[y][x] -= flow fluidNewMap[y][x] -= flow
fluidNewMap[y][x + 1] += flow fluidNewMap[y][x + 1] += flow
fluidNewTypeMap[y][x + 1] = remainingType
remainingMass -= flow remainingMass -= flow
} }
@@ -249,7 +256,7 @@ object WorldSimulator {
// Up; only compressed water flows upwards // Up; only compressed water flows upwards
if (!isSolid(worldX, worldY - 1)) { // TODO use isFlowable if (!isSolid(worldX, worldY - 1)) { // TODO use isFlowable
flow = remainingMass - getStableStateB(remainingMass + fluidMap[y - 1][x]) flow = remainingMass - getStableStateB(remainingMass + fluidNewMap[y - 1][x])
if (flow > minFlow) { if (flow > minFlow) {
flow *= 0.5f flow *= 0.5f
} }
@@ -257,6 +264,7 @@ object WorldSimulator {
fluidNewMap[y][x] -= flow fluidNewMap[y][x] -= flow
fluidNewMap[y - 1][x] += flow fluidNewMap[y - 1][x] += flow
fluidNewTypeMap[y - 1][x] = remainingType
remainingMass -= flow remainingMass -= flow
} }

View File

@@ -128,11 +128,13 @@ class BasicDebugInfoWindow : UICanvas() {
printLine(batch, 8, "light@cursor $ccG$lightVal") printLine(batch, 8, "light@cursor $ccG$lightVal")
val tileNum = ingame.world.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1 val tileNum = ingame.world.getTileFromTerrain(mouseTileX, mouseTileY) ?: -1
val fluid = ingame.world.getFluid(mouseTileX, mouseTileY)
printLine(batch, 9, "tile@cursor $ccG$tileNum ($mtX, $mtY)") printLine(batch, 9, "tile@cursor $ccG$tileNum ($mtX, $mtY)")
printLine(batch, 10, "fluid@cursor ${ccY}Type $ccM${fluid.type.value} ${ccY}Fill $ccG${fluid.amount}f")
var dbgCnt = 11 var dbgCnt = 12
Terrarum.debugTimers.forEach { t, u -> Terrarum.debugTimers.forEach { t, u ->
printLine(batch, dbgCnt, "$ccM$t $ccG$u$ccY ns") printLine(batch, dbgCnt, "$ccM$t $ccG$u$ccY ns")
dbgCnt++ dbgCnt++

View File

@@ -72,7 +72,7 @@ internal object BlocksDrawer {
private lateinit var terrainTilesBuffer: Array<IntArray> private lateinit var terrainTilesBuffer: Array<IntArray>
private lateinit var wallTilesBuffer: Array<IntArray> private lateinit var wallTilesBuffer: Array<IntArray>
private lateinit var wireTilesBuffer: Array<IntArray> private lateinit var wireTilesBuffer: Array<IntArray>
private var tilesBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGB888) private var tilesBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888)
private lateinit var tilesQuad: Mesh private lateinit var tilesQuad: Mesh
@@ -793,7 +793,7 @@ internal object BlocksDrawer {
wireTilesBuffer = Array<IntArray>(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) }) wireTilesBuffer = Array<IntArray>(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) })
tilesBuffer.dispose() tilesBuffer.dispose()
tilesBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGB888) tilesBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888)
} }
if (oldScreenW != screenW || oldScreenH != screenH) { if (oldScreenW != screenW || oldScreenH != screenH) {