mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 10:04:05 +09:00
limitedly successful attempt to create a title screen
This commit is contained in:
@@ -63,7 +63,7 @@
|
|||||||
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9188";"0.0000";"0.7156";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"212"; "212";"BLOCK_ILLUMINATOR_FUCHSIA" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.9188";"0.0000";"0.7156";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.7156";"0.0000";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"213"; "213";"BLOCK_ILLUMINATOR_PURPLE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.7156";"0.0000";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.1996";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"214"; "214";"BLOCK_ILLUMINATOR_BLUE" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.1996";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.0000";"0.8368";"0.9188";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"215"; "215";"BLOCK_ILLUMINATOR_CYAN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.4621";"1.4188";"1.2368";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2112";"1.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"216"; "216";"BLOCK_ILLUMINATOR_GREEN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.2112";"1.0000";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.1252";"0.4068";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"217"; "217";"BLOCK_ILLUMINATOR_GREEN_DARK";"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.1252";"0.4068";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.3324";"0.1252";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
"218"; "218";"BLOCK_ILLUMINATOR_BROWN" ;"0.0312";"0.0312";"0.0312";"0.0312"; "1"; "N/A";"glas"; "0"; "1"; "0"; "1";"0.3324";"0.1252";"0.0000";"0.0000"; "0"; "0"; "N/A"; "0";"16"
|
||||||
@@ -164,6 +164,10 @@
|
|||||||
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
|
# Sunstone: Artificial sunlight, change colour over time in sync with sunlight. The light is set by game's code.
|
||||||
# Sunlight capacitor: daylight at noon. Set by game's code.
|
# Sunlight capacitor: daylight at noon. Set by game's code.
|
||||||
|
|
||||||
|
# BLOCK_ILLUMINATOR_CYAN is actually a SUPER_LUMINATOR, cyan colour is used as:
|
||||||
|
# 1. It has quite a brightness on RGB colour space
|
||||||
|
# 2. Helmholz-Kohlraush effect
|
||||||
|
|
||||||
|
|
||||||
## Tiles ##
|
## Tiles ##
|
||||||
|
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 1 and column 20.
|
@@ -76,6 +76,14 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val lightmapDownsample = 2f //2f: still has choppy look when the camera moves but unnoticeable when blurred
|
val lightmapDownsample = 2f //2f: still has choppy look when the camera moves but unnoticeable when blurred
|
||||||
|
|
||||||
|
|
||||||
|
/** Sets camera position so that (0,0) would be top-left of the screen, (width, height) be bottom-right. */
|
||||||
|
fun setCameraPosition(batch: SpriteBatch, camera: Camera, newX: Float, newY: Float) {
|
||||||
|
camera.position.set((-newX + Terrarum.HALFW).round(), (-newY + Terrarum.HALFH).round(), 0f)
|
||||||
|
camera.update()
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -156,23 +164,6 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
var camera = OrthographicCamera(Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
var camera = OrthographicCamera(Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||||
|
|
||||||
/** Actually just a mesh of four vertices, two triangles -- not a literal glQuad */
|
|
||||||
var fullscreenQuad = Mesh(
|
|
||||||
true, 4, 6,
|
|
||||||
VertexAttribute.Position(),
|
|
||||||
VertexAttribute.ColorUnpacked(),
|
|
||||||
VertexAttribute.TexCoords(0)
|
|
||||||
)
|
|
||||||
|
|
||||||
init {
|
|
||||||
fullscreenQuad.setVertices(floatArrayOf(
|
|
||||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
|
||||||
Terrarum.WIDTH.toFloat(), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
|
||||||
Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
|
||||||
0f, Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
|
||||||
))
|
|
||||||
fullscreenQuad.setIndices(shortArrayOf(0, 1, 2, 2, 3, 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
// invert Y
|
// invert Y
|
||||||
fun initViewPort(width: Int, height: Int) {
|
fun initViewPort(width: Int, height: Int) {
|
||||||
@@ -200,13 +191,18 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
override fun show() {
|
override fun show() {
|
||||||
//initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
//initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||||
|
|
||||||
|
|
||||||
// gameLoadMode and gameLoadInfoPayload must be set beforehand!!
|
// gameLoadMode and gameLoadInfoPayload must be set beforehand!!
|
||||||
|
|
||||||
when (gameLoadMode) {
|
when (gameLoadMode) {
|
||||||
GameLoadMode.CREATE_NEW -> enter(gameLoadInfoPayload as NewWorldParameters)
|
GameLoadMode.CREATE_NEW -> enter(gameLoadInfoPayload as NewWorldParameters)
|
||||||
GameLoadMode.LOAD_FROM -> enter(gameLoadInfoPayload as GameSaveData)
|
GameLoadMode.LOAD_FROM -> enter(gameLoadInfoPayload as GameSaveData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LightmapRenderer.world = this.world
|
||||||
|
//BlocksDrawer.world = this.world
|
||||||
|
FeaturesDrawer.world = this.world
|
||||||
|
|
||||||
|
gameInitialised = true
|
||||||
}
|
}
|
||||||
|
|
||||||
data class GameSaveData(
|
data class GameSaveData(
|
||||||
@@ -236,13 +232,11 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
world = gameSaveData.world
|
world = gameSaveData.world
|
||||||
historicalFigureIDBucket = gameSaveData.historicalFigureIDBucket
|
historicalFigureIDBucket = gameSaveData.historicalFigureIDBucket
|
||||||
playableActorDelegate = PlayableActorDelegate(gameSaveData.realGamePlayer)
|
playableActorDelegate = PlayableActorDelegate(gameSaveData.realGamePlayer)
|
||||||
addNewActor(player!!)
|
addNewActor(player)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//initGame()
|
//initGame()
|
||||||
|
|
||||||
gameInitialised = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,12 +278,15 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
|
|
||||||
//initGame()
|
//initGame()
|
||||||
|
|
||||||
gameInitialised = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initGame() {
|
/** Load rest of the game with GL context */
|
||||||
|
fun postInit() {
|
||||||
|
//LightmapRenderer.world = this.world
|
||||||
|
BlocksDrawer.world = this.world
|
||||||
|
//FeaturesDrawer.world = this.world
|
||||||
|
|
||||||
|
|
||||||
Gdx.input.inputProcessor = GameController
|
Gdx.input.inputProcessor = GameController
|
||||||
|
|
||||||
@@ -415,27 +412,16 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
if (gameLoadMode == GameLoadMode.CREATE_NEW) {
|
if (gameLoadMode == GameLoadMode.CREATE_NEW) {
|
||||||
playableActorDelegate = PlayableActorDelegate(PlayerBuilderSigrid())
|
playableActorDelegate = PlayableActorDelegate(PlayerBuilderSigrid())
|
||||||
|
|
||||||
// determine spawn position
|
// go to spawn position
|
||||||
val spawnX = world.width / 2
|
|
||||||
var solidTileCounter = 0
|
|
||||||
while (true) {
|
|
||||||
if (BlockCodex[world.getTileFromTerrain(spawnX, solidTileCounter)].isSolid ||
|
|
||||||
BlockCodex[world.getTileFromTerrain(spawnX - 1, solidTileCounter)].isSolid ||
|
|
||||||
BlockCodex[world.getTileFromTerrain(spawnX + 1, solidTileCounter)].isSolid
|
|
||||||
) break
|
|
||||||
|
|
||||||
solidTileCounter += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
player.setPosition(
|
player.setPosition(
|
||||||
spawnX * FeaturesDrawer.TILE_SIZE.toDouble(),
|
world.spawnX * FeaturesDrawer.TILE_SIZE.toDouble(),
|
||||||
solidTileCounter * FeaturesDrawer.TILE_SIZE.toDouble()
|
world.spawnY * FeaturesDrawer.TILE_SIZE.toDouble()
|
||||||
)
|
)
|
||||||
|
|
||||||
addNewActor(player)
|
addNewActor(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
initGame()
|
postInit()
|
||||||
|
|
||||||
|
|
||||||
gameFullyLoaded = true
|
gameFullyLoaded = true
|
||||||
@@ -496,7 +482,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
BlockPropUtil.dynamicLumFuncTickClock()
|
BlockPropUtil.dynamicLumFuncTickClock()
|
||||||
world.updateWorldTime(delta)
|
world.updateWorldTime(delta)
|
||||||
//WorldSimulator(player, delta)
|
//WorldSimulator(player, delta)
|
||||||
WeatherMixer.update(delta)
|
WeatherMixer.update(delta, player)
|
||||||
BlockStats.update()
|
BlockStats.update()
|
||||||
if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride)
|
if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride)
|
||||||
world.globalLight = WeatherMixer.globalLightNow
|
world.globalLight = WeatherMixer.globalLightNow
|
||||||
@@ -506,7 +492,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
// camera-related updates //
|
// camera-related updates //
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
FeaturesDrawer.update(delta)
|
FeaturesDrawer.update(delta)
|
||||||
WorldCamera.update()
|
WorldCamera.update(world, player)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -555,7 +541,6 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
|
|
||||||
// Post-update; ones that needs everything is completed //
|
// Post-update; ones that needs everything is completed //
|
||||||
FeaturesDrawer.render(batch) //
|
|
||||||
// update lightmap on every other frames, OR full-frame if the option is true
|
// update lightmap on every other frames, OR full-frame if the option is true
|
||||||
if (Terrarum.getConfigBoolean("fullframelightupdate") or (Terrarum.GLOBAL_RENDER_TIMER % 2 == 1)) { //
|
if (Terrarum.getConfigBoolean("fullframelightupdate") or (Terrarum.GLOBAL_RENDER_TIMER % 2 == 1)) { //
|
||||||
LightmapRenderer.fireRecalculateEvent() //
|
LightmapRenderer.fireRecalculateEvent() //
|
||||||
@@ -579,7 +564,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
///////////////////////////
|
///////////////////////////
|
||||||
// draw world to the FBO //
|
// draw world to the FBO //
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
processBlur(LightmapRenderer.DRAW_FOR_RGB)
|
processBlur(lightmapFboA, lightmapFboB, LightmapRenderer.DRAW_FOR_RGB)
|
||||||
|
|
||||||
worldDrawFrameBuffer.inAction(camera, batch) {
|
worldDrawFrameBuffer.inAction(camera, batch) {
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
@@ -658,7 +643,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
//////////////////////////
|
//////////////////////////
|
||||||
// draw glow to the FBO //
|
// draw glow to the FBO //
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
processBlur(LightmapRenderer.DRAW_FOR_ALPHA)
|
processBlur(lightmapFboA, lightmapFboB, LightmapRenderer.DRAW_FOR_ALPHA)
|
||||||
|
|
||||||
worldGlowFrameBuffer.inAction(camera, batch) {
|
worldGlowFrameBuffer.inAction(camera, batch) {
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
@@ -736,7 +721,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
Terrarum.shaderBlendGlow.setUniformMatrix("u_projTrans", camera.combined)
|
Terrarum.shaderBlendGlow.setUniformMatrix("u_projTrans", camera.combined)
|
||||||
Terrarum.shaderBlendGlow.setUniformi("u_texture", 0)
|
Terrarum.shaderBlendGlow.setUniformi("u_texture", 0)
|
||||||
Terrarum.shaderBlendGlow.setUniformi("tex1", 1)
|
Terrarum.shaderBlendGlow.setUniformi("tex1", 1)
|
||||||
fullscreenQuad.render(Terrarum.shaderBlendGlow, GL20.GL_TRIANGLES)
|
Terrarum.fullscreenQuad.render(Terrarum.shaderBlendGlow, GL20.GL_TRIANGLES)
|
||||||
Terrarum.shaderBlendGlow.end()
|
Terrarum.shaderBlendGlow.end()
|
||||||
|
|
||||||
|
|
||||||
@@ -767,7 +752,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
// draw skybox to screen //
|
// draw skybox to screen //
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
|
|
||||||
WeatherMixer.render(camera)
|
WeatherMixer.render(camera, world)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -857,12 +842,12 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// draw some overlays (UI) //
|
// draw some overlays (UI) //
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
uiContainer.forEach { if (it != consoleHandler) it.render(batch) }
|
uiContainer.forEach { if (it != consoleHandler) it.render(batch, camera) }
|
||||||
|
|
||||||
debugWindow.render(batch)
|
debugWindow.render(batch, camera)
|
||||||
// make sure console draws on top of other UIs
|
// make sure console draws on top of other UIs
|
||||||
consoleHandler.render(batch)
|
consoleHandler.render(batch, camera)
|
||||||
notifier.render(batch)
|
notifier.render(batch, camera)
|
||||||
|
|
||||||
|
|
||||||
blendNormal()
|
blendNormal()
|
||||||
@@ -1030,7 +1015,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
gwin.drawLine(0f, Terrarum.HEIGHT / 2f, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT / 2f)*/
|
gwin.drawLine(0f, Terrarum.HEIGHT / 2f, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT / 2f)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processBlur(mode: Int) {
|
fun processBlur(lightmapFboA: FrameBuffer, lightmapFboB: FrameBuffer, mode: Int) {
|
||||||
val blurIterations = 5 // ideally, 4 * radius; must be even/odd number -- odd/even number will flip the image
|
val blurIterations = 5 // ideally, 4 * radius; must be even/odd number -- odd/even number will flip the image
|
||||||
val blurRadius = 4f / lightmapDownsample // (5, 4f); using low numbers for pixel-y aesthetics
|
val blurRadius = 4f / lightmapDownsample // (5, 4f); using low numbers for pixel-y aesthetics
|
||||||
|
|
||||||
@@ -1530,6 +1515,7 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
* @see net.torvald.terrarum.Terrarum
|
* @see net.torvald.terrarum.Terrarum
|
||||||
*/
|
*/
|
||||||
override fun resize(width: Int, height: Int) {
|
override fun resize(width: Int, height: Int) {
|
||||||
|
|
||||||
worldDrawFrameBuffer.dispose()
|
worldDrawFrameBuffer.dispose()
|
||||||
worldDrawFrameBuffer = FrameBuffer(worldFBOformat, Terrarum.WIDTH, Terrarum.HEIGHT, false)
|
worldDrawFrameBuffer = FrameBuffer(worldFBOformat, Terrarum.WIDTH, Terrarum.HEIGHT, false)
|
||||||
worldGlowFrameBuffer.dispose()
|
worldGlowFrameBuffer.dispose()
|
||||||
@@ -1547,23 +1533,6 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// re-calculate fullscreen quad
|
|
||||||
fullscreenQuad = Mesh(
|
|
||||||
true, 4, 6,
|
|
||||||
VertexAttribute.Position(),
|
|
||||||
VertexAttribute.ColorUnpacked(),
|
|
||||||
VertexAttribute.TexCoords(0)
|
|
||||||
)
|
|
||||||
fullscreenQuad.setVertices(floatArrayOf(
|
|
||||||
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
|
||||||
Terrarum.WIDTH.toFloat(), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
|
||||||
Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
|
||||||
0f, Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
|
||||||
))
|
|
||||||
fullscreenQuad.setIndices(shortArrayOf(0, 1, 2, 2, 3, 0))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (gameInitialised) {
|
if (gameInitialised) {
|
||||||
LightmapRenderer.fireRecalculateEvent()
|
LightmapRenderer.fireRecalculateEvent()
|
||||||
}
|
}
|
||||||
@@ -1614,8 +1583,6 @@ class Ingame(val batch: SpriteBatch) : Screen {
|
|||||||
* Camera will be moved so that (newX, newY) would be sit on the top-left edge.
|
* Camera will be moved so that (newX, newY) would be sit on the top-left edge.
|
||||||
*/
|
*/
|
||||||
fun setCameraPosition(newX: Float, newY: Float) {
|
fun setCameraPosition(newX: Float, newY: Float) {
|
||||||
camera.position.set((-newX + Terrarum.HALFW).round(), (-newY + Terrarum.HALFH).round(), 0f)
|
Ingame.setCameraPosition(batch, camera, newX, newY)
|
||||||
camera.update()
|
|
||||||
batch.projectionMatrix = camera.combined
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var errorTrapped = false
|
||||||
|
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
messages.clear()
|
messages.clear()
|
||||||
@@ -72,7 +74,16 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
else {
|
else {
|
||||||
val runnable = object : Runnable {
|
val runnable = object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
screenToLoad!!.show()
|
try {
|
||||||
|
screenToLoad!!.show()
|
||||||
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
|
addMessage("$ccR$e")
|
||||||
|
errorTrapped = true
|
||||||
|
|
||||||
|
System.err.println("Error while loading:")
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
screenLoadingThread = Thread(runnable, "LoadScreen GameLoader")
|
screenLoadingThread = Thread(runnable, "LoadScreen GameLoader")
|
||||||
@@ -85,7 +96,10 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
|
|
||||||
textFbo = FrameBuffer(
|
textFbo = FrameBuffer(
|
||||||
Pixmap.Format.RGBA4444,
|
Pixmap.Format.RGBA4444,
|
||||||
Terrarum.fontGame.getWidth(Lang["MENU_IO_LOADING"]),
|
maxOf(
|
||||||
|
Terrarum.fontGame.getWidth(Lang["MENU_IO_LOADING"]),
|
||||||
|
Terrarum.fontGame.getWidth(Lang["ERROR_GENERIC_TEXT"])
|
||||||
|
),
|
||||||
Terrarum.fontGame.lineHeight.toInt(),
|
Terrarum.fontGame.lineHeight.toInt(),
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -97,7 +111,7 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val textX: Float; get() = (Terrarum.WIDTH * 0.75f).floor()
|
val textX: Float; get() = (Terrarum.WIDTH * 0.72f).floor()
|
||||||
|
|
||||||
private var genuineSonic = false // the "NOW LOADING..." won't appear unless the arrow first run passes it (it's totally not a GenuineIntel tho)
|
private var genuineSonic = false // the "NOW LOADING..." won't appear unless the arrow first run passes it (it's totally not a GenuineIntel tho)
|
||||||
private var doContextChange = false
|
private var doContextChange = false
|
||||||
@@ -119,36 +133,50 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
glideTimer += delta
|
// update arrow object
|
||||||
// reset timer
|
if (!errorTrapped) {
|
||||||
if (glideTimer >= arrowObjGlideSize / arrowGlideSpeed) {
|
glideTimer += delta
|
||||||
glideTimer -= arrowObjGlideSize / arrowGlideSpeed
|
// reset timer
|
||||||
|
if (glideTimer >= arrowObjGlideSize / arrowGlideSpeed) {
|
||||||
|
glideTimer -= arrowObjGlideSize / arrowGlideSpeed
|
||||||
|
|
||||||
// change screen WHEN the timer is reset.
|
// change screen WHEN the timer is reset.
|
||||||
// In other words, the arrow must hit the goal BEFORE context change take place
|
// In other words, the arrow must hit the goal BEFORE context change take place
|
||||||
if (screenToLoad?.gameInitialised ?: false) {
|
if (screenToLoad?.gameInitialised ?: false) {
|
||||||
doContextChange = true
|
doContextChange = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
arrowObjPos = glideTimer * arrowGlideSpeed
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
genuineSonic = true
|
||||||
|
arrowObjPos = 0f
|
||||||
}
|
}
|
||||||
arrowObjPos = glideTimer * arrowGlideSpeed
|
|
||||||
|
|
||||||
|
|
||||||
|
val textToPrint = if (errorTrapped) Lang["ERROR_GENERIC_TEXT"] else Lang["MENU_IO_LOADING"]
|
||||||
|
val textWidth = Terrarum.fontGame.getWidth(textToPrint).toFloat()
|
||||||
|
|
||||||
if (!doContextChange) {
|
if (!doContextChange) {
|
||||||
// draw text to FBO
|
// draw text to FBO
|
||||||
textFbo.inAction(camera, Terrarum.batch) {
|
textFbo.inAction(camera, Terrarum.batch) {
|
||||||
Terrarum.batch.inUse {
|
Terrarum.batch.inUse {
|
||||||
|
|
||||||
|
|
||||||
blendNormal()
|
blendNormal()
|
||||||
Terrarum.fontGame
|
Terrarum.fontGame
|
||||||
it.color = Color.WHITE
|
it.color = Color.WHITE
|
||||||
Terrarum.fontGame.draw(it, Lang["MENU_IO_LOADING"], 0.33f, 0f) // x 0.5? I dunno but it breaks w/o it
|
|
||||||
|
|
||||||
|
Terrarum.fontGame.draw(it, textToPrint, (textFbo.width - textWidth) / 2f + 0.33f, 0f) // x 0.33? I dunno but it breaks w/o it
|
||||||
|
|
||||||
|
|
||||||
blendMul()
|
blendMul()
|
||||||
// draw flipped
|
// draw colour overlay, flipped
|
||||||
it.draw(textOverlayTex,
|
it.draw(textOverlayTex,
|
||||||
0f,
|
(textFbo.width - textWidth) / 2f,
|
||||||
Terrarum.fontGame.lineHeight,
|
Terrarum.fontGame.lineHeight,
|
||||||
textOverlayTex.width.toFloat(),
|
textWidth,
|
||||||
-Terrarum.fontGame.lineHeight
|
-Terrarum.fontGame.lineHeight
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -186,9 +214,11 @@ object LoadScreen : ScreenAdapter() {
|
|||||||
|
|
||||||
|
|
||||||
// draw coloured arrows
|
// draw coloured arrows
|
||||||
arrowColours.forEachIndexed { index, color ->
|
if (!errorTrapped) {
|
||||||
it.color = color
|
arrowColours.forEachIndexed { index, color ->
|
||||||
it.draw(arrowObjTex, arrowObjPos + arrowObjGlideOffsetX + arrowObjTex.width * index, glideDispY)
|
it.color = color
|
||||||
|
it.draw(arrowObjTex, arrowObjPos + arrowObjGlideOffsetX + arrowObjTex.width * index, glideDispY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import java.util.*
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const val GAME_NAME = "Terrarum"
|
const val GAME_NAME = "Terrarum"
|
||||||
|
const val COPYRIGHT_DATE_NAME = "Copyright 2013-2017 Torvald (minjaesong)"
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
Terrarum // invoke
|
Terrarum // invoke
|
||||||
@@ -258,6 +259,11 @@ object Terrarum : Game() {
|
|||||||
lateinit var textureWhiteSquare: Texture
|
lateinit var textureWhiteSquare: Texture
|
||||||
|
|
||||||
|
|
||||||
|
/** Actually just a mesh of four vertices, two triangles -- not a literal glQuad */
|
||||||
|
lateinit var fullscreenQuad: Mesh; private set
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
println("$NAME version $VERSION_STRING")
|
println("$NAME version $VERSION_STRING")
|
||||||
|
|
||||||
@@ -314,6 +320,25 @@ object Terrarum : Game() {
|
|||||||
|
|
||||||
|
|
||||||
override fun create() {
|
override fun create() {
|
||||||
|
fullscreenQuad = Mesh(
|
||||||
|
true, 4, 6,
|
||||||
|
VertexAttribute.Position(),
|
||||||
|
VertexAttribute.ColorUnpacked(),
|
||||||
|
VertexAttribute.TexCoords(0)
|
||||||
|
)
|
||||||
|
|
||||||
|
fullscreenQuad.setVertices(floatArrayOf(
|
||||||
|
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||||
|
Terrarum.WIDTH.toFloat(), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||||
|
Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
||||||
|
0f, Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
||||||
|
))
|
||||||
|
fullscreenQuad.setIndices(shortArrayOf(0, 1, 2, 2, 3, 0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TextureRegionPack.globalFlipY = true // !! TO MAKE LEGACY CODE RENDER ON ITS POSITION !!
|
TextureRegionPack.globalFlipY = true // !! TO MAKE LEGACY CODE RENDER ON ITS POSITION !!
|
||||||
Gdx.graphics.isContinuousRendering = true
|
Gdx.graphics.isContinuousRendering = true
|
||||||
|
|
||||||
@@ -375,13 +400,18 @@ object Terrarum : Game() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ingame = Ingame(batch)
|
//ingame = Ingame(batch)
|
||||||
ingame!!.gameLoadInfoPayload = Ingame.NewWorldParameters(8192, 2048, HQRNG().nextLong())
|
//ingame!!.gameLoadInfoPayload = Ingame.NewWorldParameters(8192, 2048, HQRNG().nextLong())
|
||||||
ingame!!.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
|
||||||
|
// TODO: create world being used by title screen, and serialise it.
|
||||||
|
//ingame!!.gameLoadInfoPayload = Ingame.NewWorldParameters(2400, 800, HQRNG().nextLong())
|
||||||
|
//ingame!!.gameLoadMode = Ingame.GameLoadMode.CREATE_NEW
|
||||||
|
|
||||||
|
|
||||||
LoadScreen.screenToLoad = ingame!!
|
//LoadScreen.screenToLoad = ingame!!
|
||||||
super.setScreen(LoadScreen)
|
|
||||||
|
super.setScreen(TitleScreen(batch))
|
||||||
|
//super.setScreen(LoadScreen)
|
||||||
|
|
||||||
//super.setScreen(ingame)
|
//super.setScreen(ingame)
|
||||||
}
|
}
|
||||||
@@ -423,6 +453,17 @@ object Terrarum : Game() {
|
|||||||
screenW = width
|
screenW = width
|
||||||
screenH = height
|
screenH = height
|
||||||
|
|
||||||
|
|
||||||
|
// re-calculate fullscreen quad
|
||||||
|
fullscreenQuad.setVertices(floatArrayOf(
|
||||||
|
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f,
|
||||||
|
Terrarum.WIDTH.toFloat(), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f,
|
||||||
|
Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 1f, 0f,
|
||||||
|
0f, Terrarum.HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 0f, 0f
|
||||||
|
))
|
||||||
|
fullscreenQuad.setIndices(shortArrayOf(0, 1, 2, 2, 3, 0))
|
||||||
|
|
||||||
|
|
||||||
super.screen.resize(WIDTH, HEIGHT)
|
super.screen.resize(WIDTH, HEIGHT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
363
src/net/torvald/terrarum/TitleScreen.kt
Normal file
363
src/net/torvald/terrarum/TitleScreen.kt
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.Input
|
||||||
|
import com.badlogic.gdx.Screen
|
||||||
|
import com.badlogic.gdx.graphics.*
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
|
import net.torvald.terrarum.gameactors.Hitbox
|
||||||
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.langpack.Lang
|
||||||
|
import net.torvald.terrarum.serialise.ReadLayerData
|
||||||
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
import net.torvald.terrarum.ui.UIHandler
|
||||||
|
import net.torvald.terrarum.ui.UIStartMenu
|
||||||
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
|
import net.torvald.terrarum.worlddrawer.BlocksDrawer
|
||||||
|
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||||
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
class TitleScreen(val batch: SpriteBatch) : Screen {
|
||||||
|
|
||||||
|
var camera = OrthographicCamera(Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
|
||||||
|
|
||||||
|
// invert Y
|
||||||
|
fun initViewPort(width: Int, height: Int) {
|
||||||
|
//val width = if (width % 1 == 1) width + 1 else width
|
||||||
|
//val height = if (height % 1 == 1) height + 1 else width
|
||||||
|
|
||||||
|
// Set Y to point downwards
|
||||||
|
camera.setToOrtho(true, width.toFloat(), height.toFloat())
|
||||||
|
|
||||||
|
// Update camera matrix
|
||||||
|
camera.update()
|
||||||
|
|
||||||
|
// Set viewport to restrict drawing
|
||||||
|
Gdx.gl20.glViewport(0, 0, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var loadDone = false
|
||||||
|
|
||||||
|
private lateinit var demoWorld: GameWorld
|
||||||
|
private val cameraPlayer = object : ActorWithBody(RenderOrder.BEHIND) {
|
||||||
|
override fun drawBody(batch: SpriteBatch) { }
|
||||||
|
override fun drawGlow(batch: SpriteBatch) { }
|
||||||
|
override fun dispose() { }
|
||||||
|
override fun onActorValueChange(key: String, value: Any?) { }
|
||||||
|
override fun run() { }
|
||||||
|
|
||||||
|
override fun update(delta: Float) {
|
||||||
|
// camera walk?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gradWhiteTop = Color(0xf8f8f8ff.toInt())
|
||||||
|
private val gradWhiteBottom = Color(0xd8d8d8ff.toInt())
|
||||||
|
|
||||||
|
private val lightFBOformat = Pixmap.Format.RGB888
|
||||||
|
var lightmapFboA = FrameBuffer(lightFBOformat, Terrarum.WIDTH.div(Ingame.lightmapDownsample.toInt()), Terrarum.HEIGHT.div(Ingame.lightmapDownsample.toInt()), false)
|
||||||
|
var lightmapFboB = FrameBuffer(lightFBOformat, Terrarum.WIDTH.div(Ingame.lightmapDownsample.toInt()), Terrarum.HEIGHT.div(Ingame.lightmapDownsample.toInt()), false)
|
||||||
|
|
||||||
|
lateinit var logo: TextureRegion
|
||||||
|
|
||||||
|
|
||||||
|
private lateinit var uiMenu: UIHandler
|
||||||
|
|
||||||
|
private fun loadThingsWhileIntroIsVisible() {
|
||||||
|
demoWorld = ReadLayerData(FileInputStream(ModMgr.getFile("basegame", "demoworld")))
|
||||||
|
|
||||||
|
cameraPlayer.hitbox.setPosition(
|
||||||
|
demoWorld.spawnX * FeaturesDrawer.TILE_SIZE.toDouble(),
|
||||||
|
demoWorld.spawnY * FeaturesDrawer.TILE_SIZE.toDouble()
|
||||||
|
)
|
||||||
|
cameraPlayer.hitbox.setDimension(2.0, 2.0)
|
||||||
|
|
||||||
|
demoWorld.time.timeDelta = 45
|
||||||
|
|
||||||
|
|
||||||
|
LightmapRenderer.world = demoWorld
|
||||||
|
BlocksDrawer.world = demoWorld
|
||||||
|
FeaturesDrawer.world = demoWorld
|
||||||
|
|
||||||
|
|
||||||
|
uiMenu = UIHandler(UIStartMenu())
|
||||||
|
uiMenu.setPosition(0, UIStartMenu.menubarOffY)
|
||||||
|
uiMenu.setAsOpen()
|
||||||
|
|
||||||
|
|
||||||
|
loadDone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun hide() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
|
||||||
|
|
||||||
|
logo = TextureRegion(Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")))
|
||||||
|
logo.flip(false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var blurWriteBuffer = lightmapFboA
|
||||||
|
private var blurReadBuffer = lightmapFboB
|
||||||
|
|
||||||
|
private val minimumIntroTime = 1.0f
|
||||||
|
private var deltaCounter = 0f
|
||||||
|
|
||||||
|
override fun render(delta: Float) {
|
||||||
|
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||||
|
|
||||||
|
if (!loadDone || deltaCounter < minimumIntroTime) {
|
||||||
|
// draw load screen
|
||||||
|
Terrarum.shaderBayerSkyboxFill.begin()
|
||||||
|
Terrarum.shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined)
|
||||||
|
Terrarum.shaderBayerSkyboxFill.setUniformf("topColor", gradWhiteTop.r, gradWhiteTop.g, gradWhiteTop.b)
|
||||||
|
Terrarum.shaderBayerSkyboxFill.setUniformf("bottomColor", gradWhiteBottom.r, gradWhiteBottom.g, gradWhiteBottom.b)
|
||||||
|
Terrarum.fullscreenQuad.render(Terrarum.shaderBayerSkyboxFill, GL20.GL_TRIANGLES)
|
||||||
|
Terrarum.shaderBayerSkyboxFill.end()
|
||||||
|
|
||||||
|
batch.inUse {
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
blendNormal()
|
||||||
|
batch.shader = null
|
||||||
|
|
||||||
|
|
||||||
|
setCameraPosition(0f, 0f)
|
||||||
|
batch.draw(logo, (Terrarum.WIDTH - logo.regionWidth) / 2f, (Terrarum.HEIGHT - logo.regionHeight) / 2f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loadDone) {
|
||||||
|
loadThingsWhileIntroIsVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//if (Terrarum.GLOBAL_RENDER_TIMER % 2 == 1) {
|
||||||
|
LightmapRenderer.fireRecalculateEvent()
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
cameraPlayer.hitbox.setPosition(1024 * 16.0, 340 * 16.0)
|
||||||
|
|
||||||
|
|
||||||
|
demoWorld.updateWorldTime(delta)
|
||||||
|
WeatherMixer.update(delta, cameraPlayer)
|
||||||
|
cameraPlayer.update(delta)
|
||||||
|
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
|
||||||
|
WorldCamera.update(demoWorld, cameraPlayer)
|
||||||
|
|
||||||
|
|
||||||
|
// update UIs //
|
||||||
|
uiMenu.update(delta)
|
||||||
|
|
||||||
|
|
||||||
|
// render and blur lightmap
|
||||||
|
//processBlur(LightmapRenderer.DRAW_FOR_RGB)
|
||||||
|
|
||||||
|
// render world
|
||||||
|
batch.inUse {
|
||||||
|
batch.shader = null
|
||||||
|
camera.position.set(WorldCamera.gdxCamX, WorldCamera.gdxCamY, 0f) // make camara work
|
||||||
|
camera.update()
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
blendNormal()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
renderDemoWorld()
|
||||||
|
|
||||||
|
renderMenus()
|
||||||
|
|
||||||
|
renderOverlayTexts()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
deltaCounter += delta
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderDemoWorld() {
|
||||||
|
// draw skybox //
|
||||||
|
|
||||||
|
setCameraPosition(0f, 0f)
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
blendNormal()
|
||||||
|
WeatherMixer.render(camera, demoWorld)
|
||||||
|
|
||||||
|
|
||||||
|
// draw tiles //
|
||||||
|
|
||||||
|
// using custom code for camera; this is obscure and tricky
|
||||||
|
camera.position.set(WorldCamera.gdxCamX, WorldCamera.gdxCamY, 0f) // make camara work
|
||||||
|
camera.update()
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
batch.shader = null
|
||||||
|
|
||||||
|
blendNormal()
|
||||||
|
BlocksDrawer.renderWall(batch)
|
||||||
|
BlocksDrawer.renderTerrain(batch)
|
||||||
|
BlocksDrawer.renderFront(batch, false)
|
||||||
|
FeaturesDrawer.drawEnvOverlay(batch)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderMenus() {
|
||||||
|
setCameraPosition(0f, 0f)
|
||||||
|
blendNormal()
|
||||||
|
batch.shader = null
|
||||||
|
|
||||||
|
|
||||||
|
uiMenu.render(batch, camera)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderOverlayTexts() {
|
||||||
|
setCameraPosition(0f, 0f)
|
||||||
|
blendNormal()
|
||||||
|
batch.shader = null
|
||||||
|
|
||||||
|
batch.color = Color.LIGHT_GRAY
|
||||||
|
|
||||||
|
val COPYTING = arrayOf(
|
||||||
|
COPYRIGHT_DATE_NAME,
|
||||||
|
Lang["COPYRIGHT_GNU_GPL_3"]
|
||||||
|
)
|
||||||
|
|
||||||
|
COPYTING.forEachIndexed { index, s ->
|
||||||
|
val textWidth = Terrarum.fontGame.getWidth(s)
|
||||||
|
Terrarum.fontGame.draw(batch, s,
|
||||||
|
Terrarum.WIDTH - textWidth - 1f - 0.667f,
|
||||||
|
Terrarum.HEIGHT - Terrarum.fontGame.lineHeight * (COPYTING.size - index) - 1f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pause() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resume() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun resize(width: Int, height: Int) {
|
||||||
|
// Set up viewport when window is resized
|
||||||
|
initViewPort(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
logo.texture.dispose()
|
||||||
|
lightmapFboA.dispose()
|
||||||
|
lightmapFboB.dispose()
|
||||||
|
|
||||||
|
uiMenu.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setCameraPosition(newX: Float, newY: Float) {
|
||||||
|
Ingame.setCameraPosition(batch, camera, newX, newY)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun processBlur(mode: Int) {
|
||||||
|
val blurIterations = 5 // ideally, 4 * radius; must be even/odd number -- odd/even number will flip the image
|
||||||
|
val blurRadius = 4f / Ingame.lightmapDownsample // (5, 4f); using low numbers for pixel-y aesthetics
|
||||||
|
|
||||||
|
blurWriteBuffer = lightmapFboA
|
||||||
|
blurReadBuffer = lightmapFboB
|
||||||
|
|
||||||
|
|
||||||
|
lightmapFboA.inAction(null, null) {
|
||||||
|
Gdx.gl.glClearColor(0f, 0f, 0f, 0f)
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||||
|
}
|
||||||
|
lightmapFboB.inAction(null, null) {
|
||||||
|
Gdx.gl.glClearColor(0f, 0f, 0f, 0f)
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (mode == LightmapRenderer.DRAW_FOR_RGB) {
|
||||||
|
// initialise readBuffer with untreated lightmap
|
||||||
|
blurReadBuffer.inAction(camera, batch) {
|
||||||
|
batch.inUse {
|
||||||
|
// using custom code for camera; this is obscure and tricky
|
||||||
|
camera.position.set(
|
||||||
|
(WorldCamera.gdxCamX / Ingame.lightmapDownsample).round(),
|
||||||
|
(WorldCamera.gdxCamY / Ingame.lightmapDownsample).round(),
|
||||||
|
0f
|
||||||
|
) // make camara work
|
||||||
|
camera.update()
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
|
||||||
|
|
||||||
|
blendNormal()
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
LightmapRenderer.draw(batch, LightmapRenderer.DRAW_FOR_RGB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// initialise readBuffer with untreated lightmap
|
||||||
|
blurReadBuffer.inAction(camera, batch) {
|
||||||
|
batch.inUse {
|
||||||
|
// using custom code for camera; this is obscure and tricky
|
||||||
|
camera.position.set(
|
||||||
|
(WorldCamera.gdxCamX / Ingame.lightmapDownsample).round(),
|
||||||
|
(WorldCamera.gdxCamY / Ingame.lightmapDownsample).round(),
|
||||||
|
0f
|
||||||
|
) // make camara work
|
||||||
|
camera.update()
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
|
||||||
|
|
||||||
|
blendNormal()
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
LightmapRenderer.draw(batch, LightmapRenderer.DRAW_FOR_ALPHA)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (i in 0 until blurIterations) {
|
||||||
|
blurWriteBuffer.inAction(camera, batch) {
|
||||||
|
|
||||||
|
batch.inUse {
|
||||||
|
val texture = blurReadBuffer.colorBufferTexture
|
||||||
|
|
||||||
|
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear)
|
||||||
|
|
||||||
|
|
||||||
|
batch.shader = Terrarum.shaderBlur
|
||||||
|
batch.shader.setUniformf("iResolution",
|
||||||
|
blurWriteBuffer.width.toFloat(), blurWriteBuffer.height.toFloat())
|
||||||
|
batch.shader.setUniformf("flip", 1f)
|
||||||
|
if (i % 2 == 0)
|
||||||
|
batch.shader.setUniformf("direction", blurRadius, 0f)
|
||||||
|
else
|
||||||
|
batch.shader.setUniformf("direction", 0f, blurRadius)
|
||||||
|
|
||||||
|
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
batch.draw(texture, 0f, 0f)
|
||||||
|
|
||||||
|
|
||||||
|
// swap
|
||||||
|
val t = blurWriteBuffer
|
||||||
|
blurWriteBuffer = blurReadBuffer
|
||||||
|
blurReadBuffer = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -94,8 +94,8 @@ object BlockPropUtil {
|
|||||||
fun getDynamicLumFunc(baseLum: Color, type: Int): Color {
|
fun getDynamicLumFunc(baseLum: Color, type: Int): Color {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
1 -> getTorchFlicker(baseLum)
|
1 -> getTorchFlicker(baseLum)
|
||||||
2 -> Terrarum.ingame!!.world.globalLight // current global light
|
2 -> Terrarum.ingame!!.world.globalLight.cpy().mul(LightmapRenderer.DIV_FLOAT) // current global light
|
||||||
3 -> WeatherMixer.getGlobalLightOfTime(WorldTime.DAY_LENGTH / 2) // daylight at noon
|
3 -> WeatherMixer.getGlobalLightOfTime(WorldTime.DAY_LENGTH / 2).cpy().mul(LightmapRenderer.DIV_FLOAT) // daylight at noon
|
||||||
4 -> getSlowBreath(baseLum)
|
4 -> getSlowBreath(baseLum)
|
||||||
5 -> getPulsate(baseLum)
|
5 -> getPulsate(baseLum)
|
||||||
else -> baseLum
|
else -> baseLum
|
||||||
|
|||||||
@@ -51,7 +51,11 @@ object CommandDict {
|
|||||||
"spawntorch" to SpawnTikiTorch,
|
"spawntorch" to SpawnTikiTorch,
|
||||||
"musictest" to MusicTest,
|
"musictest" to MusicTest,
|
||||||
"spawntapestry" to SpawnTapestry,
|
"spawntapestry" to SpawnTapestry,
|
||||||
"imtest" to JavaIMTest
|
"imtest" to JavaIMTest,
|
||||||
|
|
||||||
|
|
||||||
|
/* !! */"exportlayer" to ExportLayerData,
|
||||||
|
/* !! */"importlayer" to ImportLayerData
|
||||||
)
|
)
|
||||||
|
|
||||||
operator fun get(commandName: String): ConsoleCommand {
|
operator fun get(commandName: String): ConsoleCommand {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.torvald.terrarum.console
|
package net.torvald.terrarum.console
|
||||||
|
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.ccR
|
||||||
import net.torvald.terrarum.ui.ConsoleWindow
|
import net.torvald.terrarum.ui.ConsoleWindow
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,7 +14,7 @@ internal object EchoError : ConsoleCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun execute(single_line: String) {
|
fun execute(single_line: String) {
|
||||||
(Terrarum.ingame!!.consoleHandler.UI as ConsoleWindow).sendMessage(single_line)
|
(Terrarum.ingame!!.consoleHandler.UI as ConsoleWindow).sendMessage("$ccR$single_line")
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun invoke(args: Array<String>) = execute(args)
|
operator fun invoke(args: Array<String>) = execute(args)
|
||||||
|
|||||||
26
src/net/torvald/terrarum/console/ExportLayerData.kt
Normal file
26
src/net/torvald/terrarum/console/ExportLayerData.kt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package net.torvald.terrarum.console
|
||||||
|
|
||||||
|
import net.torvald.terrarum.serialise.WriteLayerData
|
||||||
|
import net.torvald.terrarum.serialise.WriteMeta
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2017-07-18.
|
||||||
|
*/
|
||||||
|
object ExportLayerData : ConsoleCommand {
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
if (args.size < 2) {
|
||||||
|
printUsage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val saveDirectoryName = args[1]
|
||||||
|
|
||||||
|
WriteLayerData(saveDirectoryName)
|
||||||
|
|
||||||
|
Echo("Layer data exported to $saveDirectoryName/${WriteLayerData.META_FILENAME}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
Echo("Usage: exportlayer savename")
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/net/torvald/terrarum/console/ImportLayerData.kt
Normal file
33
src/net/torvald/terrarum/console/ImportLayerData.kt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package net.torvald.terrarum.console
|
||||||
|
|
||||||
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.serialise.ReadLayerData
|
||||||
|
import net.torvald.terrarum.worlddrawer.FeaturesDrawer
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.util.zip.GZIPInputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2017-07-18.
|
||||||
|
*/
|
||||||
|
object ImportLayerData : ConsoleCommand {
|
||||||
|
override fun execute(args: Array<String>) {
|
||||||
|
if (args.size < 2) {
|
||||||
|
ExportLayerData.printUsage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//val fis = GZIPInputStream(FileInputStream(args[1])) // this gzip is kaput
|
||||||
|
val fis = FileInputStream(args[1])
|
||||||
|
Terrarum.ingame!!.world = ReadLayerData(fis)
|
||||||
|
Terrarum.ingame!!.player.setPosition(
|
||||||
|
Terrarum.ingame!!.world.spawnY * FeaturesDrawer.TILE_SIZE.toDouble(),
|
||||||
|
Terrarum.ingame!!.world.spawnX * FeaturesDrawer.TILE_SIZE.toDouble()
|
||||||
|
)
|
||||||
|
fis.close()
|
||||||
|
Echo("Successfully loaded ${args[1]}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun printUsage() {
|
||||||
|
Echo("Usage: importlayer path/to/layer.data")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -79,7 +79,7 @@ object PlayerBuilderSigrid {
|
|||||||
Block.STONE_QUARRIED, Block.STONE_TILE_WHITE, Block.TORCH,
|
Block.STONE_QUARRIED, Block.STONE_TILE_WHITE, Block.TORCH,
|
||||||
Block.DAYLIGHT_CAPACITOR, Block.ICE_FRAGILE,
|
Block.DAYLIGHT_CAPACITOR, Block.ICE_FRAGILE,
|
||||||
Block.ILLUMINATOR_WHITE, Block.ILLUMINATOR_BLACK, Block.ILLUMINATOR_ORANGE,
|
Block.ILLUMINATOR_WHITE, Block.ILLUMINATOR_BLACK, Block.ILLUMINATOR_ORANGE,
|
||||||
Block.ILLUMINATOR_GREEN
|
Block.ILLUMINATOR_GREEN, Block.ILLUMINATOR_CYAN, Block.SUNSTONE
|
||||||
)
|
)
|
||||||
val walls = arrayOf(
|
val walls = arrayOf(
|
||||||
Block.AIR, Block.DIRT, Block.GLASS_CRUDE,
|
Block.AIR, Block.DIRT, Block.GLASS_CRUDE,
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import net.torvald.dataclass.Float16
|
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
@@ -23,8 +22,10 @@ class GameWorld(val width: Int, val height: Int) {
|
|||||||
|
|
||||||
val layerThermal: MapLayerFloat // in Kelvins
|
val layerThermal: MapLayerFloat // in Kelvins
|
||||||
|
|
||||||
val spawnX: Int
|
/** Tilewise spawn point */
|
||||||
val spawnY: Int
|
var spawnX: Int
|
||||||
|
/** Tilewise spawn point */
|
||||||
|
var spawnY: Int
|
||||||
|
|
||||||
val wallDamages = HashMap<BlockAddress, BlockDamage>()
|
val wallDamages = HashMap<BlockAddress, BlockDamage>()
|
||||||
val terrainDamages = HashMap<BlockAddress, BlockDamage>()
|
val terrainDamages = HashMap<BlockAddress, BlockDamage>()
|
||||||
@@ -73,7 +74,7 @@ class GameWorld(val width: Int, val height: Int) {
|
|||||||
|
|
||||||
* @return byte[][] terrain layer
|
* @return byte[][] terrain layer
|
||||||
*/
|
*/
|
||||||
val terrainArray: Array<ByteArray>
|
val terrainArray: ByteArray
|
||||||
get() = layerTerrain.data
|
get() = layerTerrain.data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,7 +82,7 @@ class GameWorld(val width: Int, val height: Int) {
|
|||||||
|
|
||||||
* @return byte[][] wall layer
|
* @return byte[][] wall layer
|
||||||
*/
|
*/
|
||||||
val wallArray: Array<ByteArray>
|
val wallArray: ByteArray
|
||||||
get() = layerWall.data
|
get() = layerWall.data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,7 +90,7 @@ class GameWorld(val width: Int, val height: Int) {
|
|||||||
|
|
||||||
* @return byte[][] wire layer
|
* @return byte[][] wire layer
|
||||||
*/
|
*/
|
||||||
val wireArray: Array<ByteArray>
|
val wireArray: ByteArray
|
||||||
get() = layerWire.data
|
get() = layerWire.data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,8 +98,8 @@ class GameWorld(val width: Int, val height: Int) {
|
|||||||
* Format: 0baaaabbbb, aaaa for x = 0, 2, 4, ..., bbbb for x = 1, 3, 5, ...
|
* Format: 0baaaabbbb, aaaa for x = 0, 2, 4, ..., bbbb for x = 1, 3, 5, ...
|
||||||
* @return byte[][] damage code pair
|
* @return byte[][] damage code pair
|
||||||
*/
|
*/
|
||||||
val damageDataArray: Array<ByteArray>
|
val damageDataArray: ByteArray
|
||||||
get() = layerTerrainLowBits.dataPair
|
get() = layerTerrainLowBits.data
|
||||||
|
|
||||||
fun getTileFromWall(x: Int, y: Int): Int? {
|
fun getTileFromWall(x: Int, y: Int): Int? {
|
||||||
val wall: Int? = layerWall.getTile(x fmod width, y)
|
val wall: Int? = layerWall.getTile(x fmod width, y)
|
||||||
@@ -167,7 +168,7 @@ class GameWorld(val width: Int, val height: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setTileWire(x: Int, y: Int, tile: Byte) {
|
fun setTileWire(x: Int, y: Int, tile: Byte) {
|
||||||
layerWire.data[y][x fmod width] = tile
|
layerWire.setTile(x fmod width, y, tile)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTileFrom(mode: Int, x: Int, y: Int): Int? {
|
fun getTileFrom(mode: Int, x: Int, y: Int): Int? {
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
|
import net.torvald.terrarum.virtualcomputer.tvd.ByteArray64
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-01-17.
|
* Created by minjaesong on 16-01-17.
|
||||||
*/
|
*/
|
||||||
class MapLayer(val width: Int, val height: Int) : Iterable<Byte> {
|
class MapLayer(val width: Int, val height: Int) : Iterable<Byte> {
|
||||||
|
|
||||||
internal @Volatile var data: Array<ByteArray> // in parallel programming: do not trust your register; always read freshly from RAM!
|
internal @Volatile var data: ByteArray // in parallel programming: do not trust your register; always read freshly from RAM!
|
||||||
|
|
||||||
init {
|
init {
|
||||||
data = Array(height) { ByteArray(width) }
|
data = ByteArray(width * height)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,7 +33,7 @@ class MapLayer(val width: Int, val height: Int) : Iterable<Byte> {
|
|||||||
// advance counter
|
// advance counter
|
||||||
iteratorCount += 1
|
iteratorCount += 1
|
||||||
|
|
||||||
return data[y][x]
|
return data[y * width + x]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,11 +42,11 @@ class MapLayer(val width: Int, val height: Int) : Iterable<Byte> {
|
|||||||
return if (x !in 0..width - 1 || y !in 0..height - 1)
|
return if (x !in 0..width - 1 || y !in 0..height - 1)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
data[y][x].toUint()
|
data[y * width + x].toUint()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun setTile(x: Int, y: Int, tile: Byte) {
|
internal fun setTile(x: Int, y: Int, tile: Byte) {
|
||||||
data[y][x] = tile
|
data[y * width + x] = tile
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
fun isInBound(x: Int, y: Int) = (x >= 0 && y >= 0 && x < width && y < height)
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package net.torvald.terrarum.gameworld
|
package net.torvald.terrarum.gameworld
|
||||||
|
|
||||||
import java.io.Serializable
|
|
||||||
import java.util.Spliterator
|
|
||||||
import java.util.function.Consumer
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-02-15.
|
* Created by minjaesong on 16-02-15.
|
||||||
*/
|
*/
|
||||||
@@ -17,14 +13,14 @@ class PairedMapLayer(width: Int, val height: Int) : Iterable<Byte> {
|
|||||||
* 0110 1101 is interpreted as
|
* 0110 1101 is interpreted as
|
||||||
* 6 for tile 0, 13 for tile 1.
|
* 6 for tile 0, 13 for tile 1.
|
||||||
*/
|
*/
|
||||||
internal @Volatile var dataPair: Array<ByteArray>
|
internal @Volatile var data: ByteArray
|
||||||
|
|
||||||
val width: Int
|
val width: Int
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.width = width / 2
|
this.width = width / 2
|
||||||
|
|
||||||
dataPair = Array(height) { ByteArray(width / 2) }
|
data = ByteArray(width * height / 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +44,7 @@ class PairedMapLayer(width: Int, val height: Int) : Iterable<Byte> {
|
|||||||
// advance counter
|
// advance counter
|
||||||
iteratorCount += 1
|
iteratorCount += 1
|
||||||
|
|
||||||
return dataPair[y][x]
|
return data[y * width + x]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,10 +55,10 @@ class PairedMapLayer(width: Int, val height: Int) : Iterable<Byte> {
|
|||||||
else {
|
else {
|
||||||
if (x and 0x1 == 0)
|
if (x and 0x1 == 0)
|
||||||
// higher four bits for i = 0, 2, 4, ...
|
// higher four bits for i = 0, 2, 4, ...
|
||||||
(java.lang.Byte.toUnsignedInt(dataPair[y][x / 2]) and 0xF0) ushr 4
|
(java.lang.Byte.toUnsignedInt(data[y * width + x / 2]) and 0xF0) ushr 4
|
||||||
else
|
else
|
||||||
// lower four bits for i = 1, 3, 5, ...
|
// lower four bits for i = 1, 3, 5, ...
|
||||||
java.lang.Byte.toUnsignedInt(dataPair[y][x / 2]) and 0x0F
|
java.lang.Byte.toUnsignedInt(data[y * width + x / 2]) and 0x0F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,12 +66,12 @@ class PairedMapLayer(width: Int, val height: Int) : Iterable<Byte> {
|
|||||||
if (data < 0 || data >= 16) throw IllegalArgumentException("[PairedMapLayer] $data: invalid data value.")
|
if (data < 0 || data >= 16) throw IllegalArgumentException("[PairedMapLayer] $data: invalid data value.")
|
||||||
if (x and 0x1 == 0)
|
if (x and 0x1 == 0)
|
||||||
// higher four bits for i = 0, 2, 4, ...
|
// higher four bits for i = 0, 2, 4, ...
|
||||||
dataPair[y][x / 2] =
|
this.data[y * width + x / 2] =
|
||||||
(java.lang.Byte.toUnsignedInt(dataPair[y][x / 2]) and 0x0F
|
(java.lang.Byte.toUnsignedInt(this.data[y * width + x / 2]) and 0x0F
|
||||||
or (data and 0xF shl 4)).toByte()
|
or (data and 0xF shl 4)).toByte()
|
||||||
else
|
else
|
||||||
// lower four bits for i = 1, 3, 5, ...
|
// lower four bits for i = 1, 3, 5, ...
|
||||||
dataPair[y][x / 2] = (java.lang.Byte.toUnsignedInt(dataPair[y][x / 2]) and 0xF0
|
this.data[y * width + x / 2] = (java.lang.Byte.toUnsignedInt(this.data[y * width + x / 2]) and 0xF0
|
||||||
or (data and 0xF)).toByte()
|
or (data and 0xF)).toByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
package net.torvald.terrarum.serialise
|
|
||||||
|
|
||||||
import java.io.IOException
|
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 16-08-24.
|
|
||||||
*/
|
|
||||||
// internal for everything: prevent malicious module from messing up the savedata
|
|
||||||
internal object ReadGameMapData {
|
|
||||||
|
|
||||||
internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int {
|
|
||||||
if (b == null) {
|
|
||||||
throw NullPointerException()
|
|
||||||
} else if (off < 0 || len < 0 || len > b.size) {
|
|
||||||
throw IndexOutOfBoundsException()
|
|
||||||
} else if (len == 0) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var c = read()
|
|
||||||
if (c == -1) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
b[0] = c.toByte()
|
|
||||||
|
|
||||||
var i = 1
|
|
||||||
try {
|
|
||||||
while (i < len) {
|
|
||||||
c = read()
|
|
||||||
if (c == -1) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
b[i] = c.toByte()
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
} catch (ee: IOException) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
114
src/net/torvald/terrarum/serialise/ReadLayerData.kt
Normal file
114
src/net/torvald/terrarum/serialise/ReadLayerData.kt
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 16-08-24.
|
||||||
|
*/
|
||||||
|
// internal for everything: prevent malicious module from messing up the savedata
|
||||||
|
internal object ReadLayerData {
|
||||||
|
|
||||||
|
|
||||||
|
internal operator fun invoke(inputStream: InputStream, inWorld: GameWorld? = null): GameWorld {
|
||||||
|
val magicBytes = ByteArray(4)
|
||||||
|
val layerSizeBytes = ByteArray(1)
|
||||||
|
val layerCountBytes = ByteArray(1)
|
||||||
|
val worldWidthBytes = ByteArray(4)
|
||||||
|
val worldHeightBytes = ByteArray(4)
|
||||||
|
val spawnCoordXBytes = ByteArray(4)
|
||||||
|
val spawnCoordYBytes = ByteArray(4)
|
||||||
|
|
||||||
|
// read header first
|
||||||
|
inputStream.read(magicBytes)
|
||||||
|
if (!Arrays.equals(magicBytes, WriteLayerData.MAGIC)) {
|
||||||
|
throw IllegalArgumentException("File not a Layer Data")
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream.read(layerSizeBytes)
|
||||||
|
inputStream.read(layerCountBytes)
|
||||||
|
inputStream.skip(2) // reserved bytes
|
||||||
|
inputStream.read(worldWidthBytes)
|
||||||
|
inputStream.read(worldHeightBytes)
|
||||||
|
inputStream.read(spawnCoordXBytes)
|
||||||
|
inputStream.read(spawnCoordYBytes)
|
||||||
|
|
||||||
|
val worldWidth = worldWidthBytes.toLittleInt()
|
||||||
|
val worldHeight = worldHeightBytes.toLittleInt()
|
||||||
|
val bytesPerTile = layerSizeBytes[0].toUint()
|
||||||
|
val layerCount = layerCountBytes[0].toUint()
|
||||||
|
val layerSize = worldWidth * worldHeight * bytesPerTile
|
||||||
|
|
||||||
|
val terrainLayerMSB = ByteArray(layerSize)
|
||||||
|
val wallLayerMSB = ByteArray(layerSize)
|
||||||
|
val terrainLayerLSB = ByteArray(layerSize / 2)
|
||||||
|
val wallLayerLSB = ByteArray(layerSize / 2)
|
||||||
|
var wireLayer: ByteArray? = null
|
||||||
|
|
||||||
|
inputStream.read(terrainLayerMSB)
|
||||||
|
inputStream.read(wallLayerMSB)
|
||||||
|
inputStream.read(terrainLayerLSB)
|
||||||
|
inputStream.read(wallLayerLSB)
|
||||||
|
|
||||||
|
if (layerCount == 4) {
|
||||||
|
wireLayer = ByteArray(layerSize)
|
||||||
|
inputStream.read(wireLayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// create world out of tiles data
|
||||||
|
|
||||||
|
val retWorld = inWorld ?: GameWorld(worldWidth, worldHeight)
|
||||||
|
|
||||||
|
retWorld.layerTerrain.data = terrainLayerMSB
|
||||||
|
retWorld.layerWall.data = wallLayerMSB
|
||||||
|
retWorld.layerTerrainLowBits.data = terrainLayerLSB
|
||||||
|
retWorld.layerWallLowBits.data = wallLayerLSB
|
||||||
|
|
||||||
|
if (wireLayer != null) {
|
||||||
|
retWorld.layerWire.data = wireLayer
|
||||||
|
}
|
||||||
|
|
||||||
|
retWorld.spawnX = spawnCoordXBytes.toLittleInt()
|
||||||
|
retWorld.spawnY = spawnCoordYBytes.toLittleInt()
|
||||||
|
|
||||||
|
|
||||||
|
return retWorld
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal fun InputStream.readRelative(b: ByteArray, off: Int, len: Int): Int {
|
||||||
|
if (b == null) {
|
||||||
|
throw NullPointerException()
|
||||||
|
} else if (off < 0 || len < 0 || len > b.size) {
|
||||||
|
throw IndexOutOfBoundsException()
|
||||||
|
} else if (len == 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = read()
|
||||||
|
if (c == -1) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
b[0] = c.toByte()
|
||||||
|
|
||||||
|
var i = 1
|
||||||
|
try {
|
||||||
|
while (i < len) {
|
||||||
|
c = read()
|
||||||
|
if (c == -1) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b[i] = c.toByte()
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
} catch (ee: IOException) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ internal object WriteCSV {
|
|||||||
Files.copy(tempPathMat, pathMat, StandardCopyOption.REPLACE_EXISTING)
|
Files.copy(tempPathMat, pathMat, StandardCopyOption.REPLACE_EXISTING)
|
||||||
Files.deleteIfExists(tempPathMat)
|
Files.deleteIfExists(tempPathMat)
|
||||||
|
|
||||||
println("Saved map data '${WriteGameMapData.META_FILENAME}' to $saveDirectoryName.")
|
println("Saved map data '${WriteLayerData.META_FILENAME}' to $saveDirectoryName.")
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
package net.torvald.terrarum.serialise
|
|
||||||
|
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
|
||||||
import net.torvald.terrarum.Terrarum
|
|
||||||
import java.io.IOException
|
|
||||||
import java.nio.charset.Charset
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.nio.file.StandardCopyOption
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 16-03-18.
|
|
||||||
*/
|
|
||||||
// internal for everything: prevent malicious module from messing up the savedata
|
|
||||||
internal object WriteGameMapData {
|
|
||||||
|
|
||||||
val META_FILENAME = "worldinfo1"
|
|
||||||
|
|
||||||
val MAGIC = "TEMD".toByteArray(charset = Charset.forName("US-ASCII"))
|
|
||||||
|
|
||||||
val BYTE_NULL: Byte = 0
|
|
||||||
|
|
||||||
|
|
||||||
internal fun write(saveDirectoryName: String): Boolean {
|
|
||||||
val path = Paths.get("${Terrarum.defaultSaveDir}" +
|
|
||||||
"/$saveDirectoryName/${WriteMeta.META_FILENAME}")
|
|
||||||
val tempPath = Files.createTempFile(path.toString(), "_temp")
|
|
||||||
val map = Terrarum.ingame!!.world
|
|
||||||
|
|
||||||
// TODO gzip
|
|
||||||
|
|
||||||
// write binary
|
|
||||||
Files.write(tempPath, MAGIC)
|
|
||||||
Files.write(tempPath, byteArrayOf(GameWorld.SIZEOF))
|
|
||||||
Files.write(tempPath, byteArrayOf(GameWorld.LAYERS))
|
|
||||||
Files.write(tempPath, byteArrayOf(BYTE_NULL))
|
|
||||||
Files.write(tempPath, byteArrayOf(BYTE_NULL))
|
|
||||||
Files.write(tempPath, toByteArray(map.width))
|
|
||||||
Files.write(tempPath, toByteArray(map.height))
|
|
||||||
Files.write(tempPath, toByteArray(map.spawnX))
|
|
||||||
Files.write(tempPath, toByteArray(map.spawnY))
|
|
||||||
map.layerTerrain.forEach(
|
|
||||||
{ b -> Files.write(tempPath, byteArrayOf(b)) })
|
|
||||||
map.layerWall.forEach(
|
|
||||||
{ b -> Files.write(tempPath, byteArrayOf(b)) })
|
|
||||||
map.layerTerrainLowBits.forEach(
|
|
||||||
{ b -> Files.write(tempPath, byteArrayOf(b)) })
|
|
||||||
map.layerWallLowBits.forEach(
|
|
||||||
{ b -> Files.write(tempPath, byteArrayOf(b)) })
|
|
||||||
map.layerWire.forEach(
|
|
||||||
{ b -> Files.write(tempPath, byteArrayOf(b)) })
|
|
||||||
|
|
||||||
// replace savemeta with tempfile
|
|
||||||
try {
|
|
||||||
Files.copy(tempPath, path, StandardCopyOption.REPLACE_EXISTING)
|
|
||||||
Files.deleteIfExists(tempPath)
|
|
||||||
println("Saved map data '$META_FILENAME' to $saveDirectoryName.")
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toByteArray(int: Int): ByteArray {
|
|
||||||
return byteArrayOf(
|
|
||||||
((int ushr 0x18) and 0xFF).toByte(),
|
|
||||||
((int ushr 0x10) and 0xFF).toByte(),
|
|
||||||
((int ushr 0x08) and 0xFF).toByte(),
|
|
||||||
((int ) and 0xFF).toByte()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
126
src/net/torvald/terrarum/serialise/WriteLayerData.kt
Normal file
126
src/net/torvald/terrarum/serialise/WriteLayerData.kt
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.console.EchoError
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.IOException
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.util.zip.GZIPOutputStream
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 16-03-18.
|
||||||
|
*/
|
||||||
|
// internal for everything: prevent malicious module from messing up the savedata
|
||||||
|
internal object WriteLayerData {
|
||||||
|
|
||||||
|
val META_FILENAME = "worldinfo1"
|
||||||
|
|
||||||
|
val MAGIC = "TEMD".toByteArray(charset = Charset.forName("US-ASCII"))
|
||||||
|
|
||||||
|
val BYTE_NULL: Byte = 0
|
||||||
|
|
||||||
|
|
||||||
|
internal operator fun invoke(saveDirectoryName: String): Boolean {
|
||||||
|
val path = "${Terrarum.defaultSaveDir}/$saveDirectoryName/${META_FILENAME}"
|
||||||
|
val tempPath = "${path}_bak"
|
||||||
|
val map = Terrarum.ingame!!.world
|
||||||
|
|
||||||
|
val parentDir = File("${Terrarum.defaultSaveDir}/$saveDirectoryName")
|
||||||
|
if (!parentDir.exists()) {
|
||||||
|
parentDir.mkdir()
|
||||||
|
}
|
||||||
|
else if (!parentDir.isDirectory) {
|
||||||
|
EchoError("Savegame directory is not actually a directory, aborting...")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val tempFile = File(tempPath)
|
||||||
|
val outFile = File(path)
|
||||||
|
tempFile.createNewFile()
|
||||||
|
|
||||||
|
val outputStream = GZIPOutputStream(FileOutputStream(tempFile))
|
||||||
|
|
||||||
|
|
||||||
|
// write binary
|
||||||
|
outputStream.write(MAGIC)
|
||||||
|
outputStream.write(byteArrayOf(GameWorld.SIZEOF))
|
||||||
|
outputStream.write(byteArrayOf(GameWorld.LAYERS))
|
||||||
|
outputStream.write(byteArrayOf(BYTE_NULL))
|
||||||
|
outputStream.write(byteArrayOf(BYTE_NULL))
|
||||||
|
outputStream.write(map.width.toLittle())
|
||||||
|
outputStream.write(map.height.toLittle())
|
||||||
|
outputStream.write(map.spawnX.toLittle())
|
||||||
|
outputStream.write(map.spawnY.toLittle())
|
||||||
|
// write one row (byteArray) at a time
|
||||||
|
outputStream.write(map.layerTerrain.data)
|
||||||
|
outputStream.write(map.layerWall.data)
|
||||||
|
outputStream.write(map.layerTerrainLowBits.data)
|
||||||
|
outputStream.write(map.layerWallLowBits.data)
|
||||||
|
outputStream.write(map.layerWire.data)
|
||||||
|
|
||||||
|
// replace savemeta with tempfile
|
||||||
|
try {
|
||||||
|
outputStream.flush()
|
||||||
|
outputStream.close()
|
||||||
|
|
||||||
|
outFile.delete()
|
||||||
|
tempFile.copyTo(outFile, overwrite = true)
|
||||||
|
tempFile.delete()
|
||||||
|
println("Saved map data '$META_FILENAME' to $saveDirectoryName.")
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
outputStream.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Int.toLittle() = byteArrayOf(
|
||||||
|
this.and(0xFF).toByte(),
|
||||||
|
this.ushr(8).and(0xFF).toByte(),
|
||||||
|
this.ushr(16).and(0xFF).toByte(),
|
||||||
|
this.ushr(24).and(0xFF).toByte()
|
||||||
|
)
|
||||||
|
fun Long.toLittle() = byteArrayOf(
|
||||||
|
this.and(0xFF).toByte(),
|
||||||
|
this.ushr(8).and(0xFF).toByte(),
|
||||||
|
this.ushr(16).and(0xFF).toByte(),
|
||||||
|
this.ushr(24).and(0xFF).toByte(),
|
||||||
|
this.ushr(32).and(0xFF).toByte(),
|
||||||
|
this.ushr(40).and(0xFF).toByte(),
|
||||||
|
this.ushr(48).and(0xFF).toByte(),
|
||||||
|
this.ushr(56).and(0xFF).toByte()
|
||||||
|
)
|
||||||
|
fun Double.toLittle() = java.lang.Double.doubleToRawLongBits(this).toLittle()
|
||||||
|
fun Boolean.toLittle() = byteArrayOf(if (this) 0xFF.toByte() else 0.toByte())
|
||||||
|
|
||||||
|
fun ByteArray.toLittleInt() =
|
||||||
|
if (this.size != 4) throw Error("Array not in size of 4")
|
||||||
|
else this[0].toUint() or
|
||||||
|
this[1].toUint().shl(8) or
|
||||||
|
this[2].toUint().shl(16) or
|
||||||
|
this[3].toUint().shl(24)
|
||||||
|
fun ByteArray.toLittleLong() =
|
||||||
|
if (this.size != 8) throw Error("Array not in size of 8")
|
||||||
|
else this[0].toUlong() or
|
||||||
|
this[1].toUlong().shl(8) or
|
||||||
|
this[2].toUlong().shl(16) or
|
||||||
|
this[3].toUlong().shl(24) or
|
||||||
|
this[4].toUlong().shl(32) or
|
||||||
|
this[5].toUlong().shl(40) or
|
||||||
|
this[6].toUlong().shl(48) or
|
||||||
|
this[7].toUlong().shl(56)
|
||||||
|
fun ByteArray.toLittleDouble() = java.lang.Double.longBitsToDouble(this.toLittleLong())
|
||||||
|
|
||||||
|
fun Byte.toUlong() = java.lang.Byte.toUnsignedLong(this)
|
||||||
|
fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this)
|
||||||
@@ -8,6 +8,8 @@ import net.torvald.terrarum.gameactors.roundInt
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* UIItems must be added manually at the init!
|
||||||
|
*
|
||||||
* Created by minjaesong on 15-12-31.
|
* Created by minjaesong on 15-12-31.
|
||||||
*/
|
*/
|
||||||
abstract class UICanvas {
|
abstract class UICanvas {
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
package net.torvald.terrarum.ui
|
package net.torvald.terrarum.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.Ingame
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
|
import net.torvald.terrarum.round
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UIHandler is a handler for UICanvas. It opens/closes the attached UI, moves the "window" (or "canvas")
|
* UIHandler is a handler for UICanvas. It opens/closes the attached UI, moves the "window" (or "canvas")
|
||||||
* to the coordinate of displayed cartesian coords, and update and render the UI.
|
* to the coordinate of displayed cartesian coords, and update and render the UI.
|
||||||
* It also process game inputs and send control events to the UI so that the UI can handle them.
|
* It also process game inputs and send control events to the UI so that the UI can handle them.
|
||||||
*
|
*
|
||||||
* Newly created UI is invisible by default.
|
* New UIs are NORMALLY HIDDEN; set it visible as you need!
|
||||||
*
|
*
|
||||||
* Created by minjaesong on 15-12-31.
|
* Created by minjaesong on 15-12-31.
|
||||||
*/
|
*/
|
||||||
@@ -129,7 +132,7 @@ class UIHandler(var UI: UICanvas,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(batch: SpriteBatch) {
|
fun render(batch: SpriteBatch, camera: Camera) {
|
||||||
if (isVisible || alwaysVisible) {
|
if (isVisible || alwaysVisible) {
|
||||||
// camera SHOULD BE CENTERED to HALFX and HALFY (see StateInGame) //
|
// camera SHOULD BE CENTERED to HALFX and HALFY (see StateInGame) //
|
||||||
|
|
||||||
@@ -141,8 +144,9 @@ class UIHandler(var UI: UICanvas,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!customPositioning)
|
if (!customPositioning) {
|
||||||
Terrarum.ingame?.setCameraPosition(posX.toFloat(), posY.toFloat())
|
setCameraPosition(batch, camera, posX.toFloat(), posY.toFloat())
|
||||||
|
}
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
|
|
||||||
UI.render(batch)
|
UI.render(batch)
|
||||||
@@ -289,4 +293,8 @@ class UIHandler(var UI: UICanvas,
|
|||||||
fun dispose() {
|
fun dispose() {
|
||||||
UI.dispose()
|
UI.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setCameraPosition(batch: SpriteBatch, camera: Camera, newX: Float, newY: Float) {
|
||||||
|
Ingame.setCameraPosition(batch, camera, newX, newY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class UIInventory(
|
|||||||
else
|
else
|
||||||
"${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
|
"${0xe069.toChar()} ${Lang["GAME_ACTION_CLOSE"]}"
|
||||||
|
|
||||||
private var oldCatSelect = -1
|
private var oldCatSelect: Int? = null
|
||||||
|
|
||||||
private var encumbrancePerc = 0f
|
private var encumbrancePerc = 0f
|
||||||
private var isEncumbered = false
|
private var isEncumbered = false
|
||||||
@@ -294,70 +294,72 @@ class UIInventory(
|
|||||||
|
|
||||||
|
|
||||||
fun shutUpAndRebuild() {
|
fun shutUpAndRebuild() {
|
||||||
val filter = catButtonsToCatIdent[catButtons.selectedButton.labelText]
|
if (catButtons.selectedButton != null) {
|
||||||
|
val filter = catButtonsToCatIdent[catButtons.selectedButton!!.labelText]
|
||||||
|
|
||||||
// encumbrance
|
// encumbrance
|
||||||
encumbrancePerc = inventory!!.capacity.toFloat() / inventory!!.maxCapacity
|
encumbrancePerc = inventory!!.capacity.toFloat() / inventory!!.maxCapacity
|
||||||
isEncumbered = inventory!!.isEncumbered
|
isEncumbered = inventory!!.isEncumbered
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inventorySortList = ArrayList<InventoryPair>()
|
inventorySortList = ArrayList<InventoryPair>()
|
||||||
|
|
||||||
// filter items
|
// filter items
|
||||||
inventory?.forEach {
|
inventory?.forEach {
|
||||||
if (it.item.inventoryCategory == filter || filter == "__all__")
|
if (it.item.inventoryCategory == filter || filter == "__all__")
|
||||||
inventorySortList.add(it)
|
inventorySortList.add(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
rebuildList = false
|
rebuildList = false
|
||||||
|
|
||||||
// sort if needed
|
// sort if needed
|
||||||
// test sort by name
|
// test sort by name
|
||||||
inventorySortList.sortBy { it.item.name }
|
inventorySortList.sortBy { it.item.name }
|
||||||
|
|
||||||
// map sortList to item list
|
// map sortList to item list
|
||||||
for (k in 0..items.size - 1) {
|
for (k in 0..items.size - 1) {
|
||||||
// we have an item
|
// we have an item
|
||||||
try {
|
try {
|
||||||
val sortListItem = inventorySortList[k + itemPage * items.size]
|
val sortListItem = inventorySortList[k + itemPage * items.size]
|
||||||
items[k].item = sortListItem.item
|
items[k].item = sortListItem.item
|
||||||
items[k].amount = sortListItem.amount
|
items[k].amount = sortListItem.amount
|
||||||
items[k].itemImage = ItemCodex.getItemImage(sortListItem.item)
|
items[k].itemImage = ItemCodex.getItemImage(sortListItem.item)
|
||||||
|
|
||||||
// set quickslot number
|
// set quickslot number
|
||||||
for (qs in 1..UIQuickBar.SLOT_COUNT) {
|
for (qs in 1..UIQuickBar.SLOT_COUNT) {
|
||||||
if (sortListItem.item == actor?.inventory?.getQuickBar(qs - 1)?.item) {
|
if (sortListItem.item == actor?.inventory?.getQuickBar(qs - 1)?.item) {
|
||||||
items[k].quickslot = qs % 10 // 10 -> 0, 1..9 -> 1..9
|
items[k].quickslot = qs % 10 // 10 -> 0, 1..9 -> 1..9
|
||||||
break
|
|
||||||
}
|
|
||||||
else
|
|
||||||
items[k].quickslot = null
|
|
||||||
}
|
|
||||||
|
|
||||||
// set equippedslot number
|
|
||||||
for (eq in 0..actor!!.inventory.itemEquipped.size - 1) {
|
|
||||||
if (eq < actor!!.inventory.itemEquipped.size) {
|
|
||||||
if (actor!!.inventory.itemEquipped[eq] == items[k].item) {
|
|
||||||
items[k].equippedSlot = eq
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
items[k].equippedSlot = null
|
items[k].quickslot = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// set equippedslot number
|
||||||
|
for (eq in 0..actor!!.inventory.itemEquipped.size - 1) {
|
||||||
|
if (eq < actor!!.inventory.itemEquipped.size) {
|
||||||
|
if (actor!!.inventory.itemEquipped[eq] == items[k].item) {
|
||||||
|
items[k].equippedSlot = eq
|
||||||
|
break
|
||||||
|
}
|
||||||
|
else
|
||||||
|
items[k].equippedSlot = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// we do not have an item, empty the slot
|
||||||
|
catch (e: IndexOutOfBoundsException) {
|
||||||
|
items[k].item = null
|
||||||
|
items[k].amount = 0
|
||||||
|
items[k].itemImage = null
|
||||||
|
items[k].quickslot = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// we do not have an item, empty the slot
|
|
||||||
catch (e: IndexOutOfBoundsException) {
|
|
||||||
items[k].item = null
|
itemPageCount = maxOf(1, 1 + (inventorySortList.size.minus(1) / items.size))
|
||||||
items[k].amount = 0
|
|
||||||
items[k].itemImage = null
|
|
||||||
items[k].quickslot = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
itemPageCount = maxOf(1, 1 + (inventorySortList.size.minus(1) / items.size))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,32 @@ import net.torvald.terrarum.Terrarum
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* ## Attaching Input Listeners
|
||||||
|
*
|
||||||
|
* UIItem provides following listeners:
|
||||||
|
*
|
||||||
|
* - updateListener
|
||||||
|
* - keyDownListener
|
||||||
|
* - keyUpListener
|
||||||
|
* - mouseMovedListene
|
||||||
|
* - touchDraggedListe
|
||||||
|
* - touchDownListener
|
||||||
|
* - touchUpListener
|
||||||
|
* - scrolledListener
|
||||||
|
* - clickOnceListener
|
||||||
|
*
|
||||||
|
* Each listeners are implemented using _functions_, instead of traditional listener _classes_.
|
||||||
|
* What you should do is just override one or more of these variables which has 'function' as their type.
|
||||||
|
* For example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* <<some_name>>.clickOnceListener = { mouseX, mouseY, button ->
|
||||||
|
* println("Bo-ing!")
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This listener will print out 'Bo-ing!' whenever it's clicked.
|
||||||
|
*
|
||||||
* Created by minjaesong on 15-12-31.
|
* Created by minjaesong on 15-12-31.
|
||||||
*/
|
*/
|
||||||
abstract class UIItem(var parentUI: UICanvas) { // do not replace parentUI to UIHandler!
|
abstract class UIItem(var parentUI: UICanvas) { // do not replace parentUI to UIHandler!
|
||||||
@@ -88,6 +114,8 @@ abstract class UIItem(var parentUI: UICanvas) { // do not replace parentUI to UI
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
open fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
open fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
|
println("trsaneirsatneioarsteniotrsaneioarstineoarstneio")
|
||||||
|
|
||||||
var actionDone = false
|
var actionDone = false
|
||||||
|
|
||||||
if (touchDownListener != null) {
|
if (touchDownListener != null) {
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
|||||||
class UIItemTextButtonList(
|
class UIItemTextButtonList(
|
||||||
parentUI: UICanvas,
|
parentUI: UICanvas,
|
||||||
labelsList: Array<String>,
|
labelsList: Array<String>,
|
||||||
override val width: Int,
|
override var width: Int,
|
||||||
override val height: Int,
|
override var height: Int,
|
||||||
val verticalGutter: Int = 0,
|
val verticalGutter: Int = 0,
|
||||||
val readFromLang: Boolean = false,
|
val readFromLang: Boolean = false,
|
||||||
val defaultSelection: Int = 0,
|
val defaultSelection: Int? = null, // negative: INVALID, positive: valid, null: no select
|
||||||
|
|
||||||
// icons
|
// icons
|
||||||
val textAreaWidth: Int,
|
val textAreaWidth: Int,
|
||||||
@@ -36,7 +36,7 @@ class UIItemTextButtonList(
|
|||||||
val highlightBackCol: Color = Color(0xb0b0b0_ff.toInt()),
|
val highlightBackCol: Color = Color(0xb0b0b0_ff.toInt()),
|
||||||
val highlightBackBlendMode: String = BlendMode.MULTIPLY,
|
val highlightBackBlendMode: String = BlendMode.MULTIPLY,
|
||||||
val inactiveCol: Color = Color(0xc0c0c0_ff.toInt()),
|
val inactiveCol: Color = Color(0xc0c0c0_ff.toInt()),
|
||||||
val backgroundCol: Color = Color(0),
|
val backgroundCol: Color = Color(0x242424_80),
|
||||||
val backgroundBlendMode: String = BlendMode.NORMAL,
|
val backgroundBlendMode: String = BlendMode.NORMAL,
|
||||||
val kinematic: Boolean = false
|
val kinematic: Boolean = false
|
||||||
) : UIItem(parentUI) {
|
) : UIItem(parentUI) {
|
||||||
@@ -93,10 +93,10 @@ class UIItemTextButtonList(
|
|||||||
override var posX = 0
|
override var posX = 0
|
||||||
override var posY = 0
|
override var posY = 0
|
||||||
|
|
||||||
var selectedIndex = defaultSelection
|
var selectedIndex: Int? = defaultSelection
|
||||||
val selectedButton: UIItemTextButton
|
val selectedButton: UIItemTextButton?
|
||||||
get() = buttons[selectedIndex]
|
get() = if (selectedIndex != null) buttons[selectedIndex!!] else null
|
||||||
private var highlightY = buttons[selectedIndex].posY.toDouble()
|
private var highlightY: Double? = if (selectedIndex != null) buttons[selectedIndex!!].posY.toDouble() else null
|
||||||
private val highlighterMoveDuration: Second = 0.1f
|
private val highlighterMoveDuration: Second = 0.1f
|
||||||
private var highlighterMoveTimer: Second = 0f
|
private var highlighterMoveTimer: Second = 0f
|
||||||
private var highlighterMoving = false
|
private var highlighterMoving = false
|
||||||
@@ -107,12 +107,15 @@ class UIItemTextButtonList(
|
|||||||
override fun update(delta: Float) {
|
override fun update(delta: Float) {
|
||||||
if (highlighterMoving) {
|
if (highlighterMoving) {
|
||||||
highlighterMoveTimer += delta
|
highlighterMoveTimer += delta
|
||||||
highlightY = UIUtils.moveQuick(
|
|
||||||
highlighterYStart,
|
if (selectedIndex != null) {
|
||||||
highlighterYEnd,
|
highlightY = UIUtils.moveQuick(
|
||||||
highlighterMoveTimer.toDouble(),
|
highlighterYStart!!,
|
||||||
highlighterMoveDuration.toDouble()
|
highlighterYEnd!!,
|
||||||
)
|
highlighterMoveTimer.toDouble(),
|
||||||
|
highlighterMoveDuration.toDouble()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (highlighterMoveTimer > highlighterMoveDuration) {
|
if (highlighterMoveTimer > highlighterMoveDuration) {
|
||||||
highlighterMoveTimer = 0f
|
highlighterMoveTimer = 0f
|
||||||
@@ -128,14 +131,14 @@ class UIItemTextButtonList(
|
|||||||
|
|
||||||
if (btn.mousePushed && index != selectedIndex) {
|
if (btn.mousePushed && index != selectedIndex) {
|
||||||
if (kinematic) {
|
if (kinematic) {
|
||||||
highlighterYStart = buttons[selectedIndex].posY.toDouble()
|
highlighterYStart = buttons[selectedIndex!!].posY.toDouble()
|
||||||
selectedIndex = index
|
selectedIndex = index
|
||||||
highlighterMoving = true
|
highlighterMoving = true
|
||||||
highlighterYEnd = buttons[selectedIndex].posY.toDouble()
|
highlighterYEnd = buttons[selectedIndex!!].posY.toDouble()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
selectedIndex = index
|
selectedIndex = index
|
||||||
highlightY = buttons[selectedIndex].posY.toDouble()
|
highlightY = buttons[selectedIndex!!].posY.toDouble()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null
|
btn.highlighted = (index == selectedIndex) // forcibly highlight if this.highlighted != null
|
||||||
@@ -150,7 +153,9 @@ class UIItemTextButtonList(
|
|||||||
|
|
||||||
batch.color = highlightBackCol
|
batch.color = highlightBackCol
|
||||||
BlendMode.resolve(highlightBackBlendMode)
|
BlendMode.resolve(highlightBackBlendMode)
|
||||||
batch.fillRect(posX.toFloat(), highlightY.toFloat(), width.toFloat(), UIItemTextButton.height.toFloat())
|
if (highlightY != null) {
|
||||||
|
batch.fillRect(posX.toFloat(), highlightY!!.toFloat(), width.toFloat(), UIItemTextButton.height.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
buttons.forEach { it.render(batch) }
|
buttons.forEach { it.render(batch) }
|
||||||
|
|
||||||
|
|||||||
107
src/net/torvald/terrarum/ui/UIStartMenu.kt
Normal file
107
src/net/torvald/terrarum/ui/UIStartMenu.kt
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package net.torvald.terrarum.ui
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.terrarum.Terrarum
|
||||||
|
|
||||||
|
class UIStartMenu : UICanvas() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** Contains STRING_IDs */
|
||||||
|
val menuLabels = arrayOf(
|
||||||
|
"MENU_MODE_SINGLEPLAYER",
|
||||||
|
"MENU_OPTIONS",
|
||||||
|
"MENU_MODULES",
|
||||||
|
"MENU_LABEL_EXIT"
|
||||||
|
)
|
||||||
|
|
||||||
|
val menubarOffY = Terrarum.HEIGHT - 180 - 40 * menuLabels.size.plus(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override var width: Int = 240
|
||||||
|
override var height: Int = 40 * menuLabels.size.plus(1)
|
||||||
|
override var handler: UIHandler? = null
|
||||||
|
override var openCloseTime = 0f
|
||||||
|
|
||||||
|
|
||||||
|
private val menubar = UIItemTextButtonList(
|
||||||
|
this,
|
||||||
|
menuLabels,
|
||||||
|
240, this.height,
|
||||||
|
textAreaWidth = 240,
|
||||||
|
readFromLang = true,
|
||||||
|
activeBackCol = Color(0),
|
||||||
|
highlightBackCol = Color(0),
|
||||||
|
defaultSelection = null
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
uiItems.add(menubar)
|
||||||
|
|
||||||
|
|
||||||
|
// attach listeners
|
||||||
|
menubar.buttons[3].clickOnceListener = { _, _, _ -> System.exit(0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(delta: Float) {
|
||||||
|
menubar.update(delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render(batch: SpriteBatch) {
|
||||||
|
menubar.render(batch)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doOpening(delta: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doClosing(delta: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endOpening(delta: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun endClosing(delta: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
|
||||||
|
return super.mouseMoved(screenX, screenY)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
|
||||||
|
return super.touchDragged(screenX, screenY, pointer)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
|
return super.touchDown(screenX, screenY, pointer, button)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
|
||||||
|
return super.touchUp(screenX, screenY, pointer, button)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun scrolled(amount: Int): Boolean {
|
||||||
|
return super.scrolled(amount)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyDown(keycode: Int): Boolean {
|
||||||
|
return super.keyDown(keycode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyUp(keycode: Int): Boolean {
|
||||||
|
return super.keyUp(keycode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun keyTyped(character: Char): Boolean {
|
||||||
|
return super.keyTyped(character)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,8 +6,10 @@ import net.torvald.terrarum.utils.JsonFetcher
|
|||||||
import net.torvald.colourutil.*
|
import net.torvald.colourutil.*
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameactors.ParticleTestRain
|
import net.torvald.terrarum.gameactors.ParticleTestRain
|
||||||
import net.torvald.terrarum.gamecontroller.KeyToggler
|
import net.torvald.terrarum.gamecontroller.KeyToggler
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.gameworld.WorldTime
|
import net.torvald.terrarum.gameworld.WorldTime
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -31,7 +33,6 @@ object WeatherMixer {
|
|||||||
lateinit var mixedWeather: BaseModularWeather
|
lateinit var mixedWeather: BaseModularWeather
|
||||||
|
|
||||||
val globalLightNow = Color(0)
|
val globalLightNow = Color(0)
|
||||||
private val world = Terrarum.ingame!!.world
|
|
||||||
|
|
||||||
// Weather indices
|
// Weather indices
|
||||||
const val WEATHER_GENERIC = "generic"
|
const val WEATHER_GENERIC = "generic"
|
||||||
@@ -68,33 +69,30 @@ object WeatherMixer {
|
|||||||
nextWeather = getRandomWeather(WEATHER_GENERIC)
|
nextWeather = getRandomWeather(WEATHER_GENERIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(delta: Float) {
|
fun update(delta: Float, player: ActorWithBody) {
|
||||||
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
currentWeather = weatherList[WEATHER_GENERIC]!![0]
|
||||||
|
|
||||||
|
|
||||||
if (Terrarum.ingame!!.player != null) {
|
// test rain toggled by F2
|
||||||
// test rain toggled by F2
|
/*if (KeyToggler.isOn(Input.Keys.F2)) {
|
||||||
if (KeyToggler.isOn(Input.Keys.F2)) {
|
val playerPos = player.centrePosPoint
|
||||||
val playerPos = Terrarum.ingame!!.player!!.centrePosPoint
|
kotlin.repeat(4) {
|
||||||
kotlin.repeat(4) {
|
// 4 seems good
|
||||||
// 4 seems good
|
val rainParticle = ParticleTestRain(
|
||||||
val rainParticle = ParticleTestRain(
|
playerPos.x + HQRNG().nextInt(Terrarum.WIDTH) - Terrarum.HALFW,
|
||||||
playerPos.x + HQRNG().nextInt(Terrarum.WIDTH) - Terrarum.HALFW,
|
playerPos.y - Terrarum.HALFH
|
||||||
playerPos.y - Terrarum.HALFH
|
)
|
||||||
)
|
Terrarum.ingame!!.addParticle(rainParticle)
|
||||||
Terrarum.ingame!!.addParticle(rainParticle)
|
|
||||||
}
|
|
||||||
globalLightNow.set(getGlobalLightOfTime(world.time.todaySeconds).mul(0.3f, 0.3f, 0.3f, 0.58f))
|
|
||||||
}
|
}
|
||||||
|
globalLightNow.set(getGlobalLightOfTime(world.time.todaySeconds).mul(0.3f, 0.3f, 0.3f, 0.58f))
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(camera: Camera) {
|
fun render(camera: Camera, world: GameWorld) {
|
||||||
|
|
||||||
// we will not care for nextSkybox for now
|
// we will not care for nextSkybox for now
|
||||||
val timeNow = Terrarum.ingame!!.world.time.todaySeconds
|
val timeNow = world.time.todaySeconds
|
||||||
val skyboxColourMap = currentWeather.skyboxGradColourMap
|
val skyboxColourMap = currentWeather.skyboxGradColourMap
|
||||||
|
|
||||||
// calculate global light
|
// calculate global light
|
||||||
@@ -112,7 +110,7 @@ object WeatherMixer {
|
|||||||
Terrarum.shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined)
|
Terrarum.shaderBayerSkyboxFill.setUniformMatrix("u_projTrans", camera.combined)
|
||||||
Terrarum.shaderBayerSkyboxFill.setUniformf("topColor", topCol.r, topCol.g, topCol.b)
|
Terrarum.shaderBayerSkyboxFill.setUniformf("topColor", topCol.r, topCol.g, topCol.b)
|
||||||
Terrarum.shaderBayerSkyboxFill.setUniformf("bottomColor", bottomCol.r, bottomCol.g, bottomCol.b)
|
Terrarum.shaderBayerSkyboxFill.setUniformf("bottomColor", bottomCol.r, bottomCol.g, bottomCol.b)
|
||||||
Terrarum.ingame!!.fullscreenQuad.render(Terrarum.shaderBayerSkyboxFill, GL20.GL_TRIANGLES)
|
Terrarum.fullscreenQuad.render(Terrarum.shaderBayerSkyboxFill, GL20.GL_TRIANGLES)
|
||||||
Terrarum.shaderBayerSkyboxFill.end()
|
Terrarum.shaderBayerSkyboxFill.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import java.util.zip.GZIPInputStream
|
|||||||
* Created by minjaesong on 16-01-19.
|
* Created by minjaesong on 16-01-19.
|
||||||
*/
|
*/
|
||||||
object BlocksDrawer {
|
object BlocksDrawer {
|
||||||
private inline val world: GameWorld; get() = Terrarum.ingame!!.world
|
lateinit var world: GameWorld
|
||||||
|
|
||||||
|
|
||||||
private val TILE_SIZE = FeaturesDrawer.TILE_SIZE
|
private val TILE_SIZE = FeaturesDrawer.TILE_SIZE
|
||||||
private val TILE_SIZEF = FeaturesDrawer.TILE_SIZE.toFloat()
|
private val TILE_SIZEF = FeaturesDrawer.TILE_SIZE.toFloat()
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,14 @@ import net.torvald.colourutil.ColourTemp
|
|||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.blendMul
|
import net.torvald.terrarum.blendMul
|
||||||
import net.torvald.terrarum.fillRect
|
import net.torvald.terrarum.fillRect
|
||||||
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 15-12-31.
|
* Created by minjaesong on 15-12-31.
|
||||||
*/
|
*/
|
||||||
object FeaturesDrawer {
|
object FeaturesDrawer {
|
||||||
|
lateinit var world: GameWorld
|
||||||
|
|
||||||
const val TILE_SIZE = 16
|
const val TILE_SIZE = 16
|
||||||
|
|
||||||
private val ENV_COLTEMP_LOWEST = 5500
|
private val ENV_COLTEMP_LOWEST = 5500
|
||||||
@@ -36,9 +39,6 @@ object FeaturesDrawer {
|
|||||||
fun update(delta: Float) {
|
fun update(delta: Float) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(batch: SpriteBatch) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A colour filter used to provide effect that makes whole screen look warmer/cooler,
|
* A colour filter used to provide effect that makes whole screen look warmer/cooler,
|
||||||
* usually targeted for the environmental temperature (desert/winterland), hence the name.
|
* usually targeted for the environmental temperature (desert/winterland), hence the name.
|
||||||
@@ -52,7 +52,7 @@ object FeaturesDrawer {
|
|||||||
val colTemp_cold = colTempLinearFunc(onscreen_cold_tiles / onscreen_tiles_cap)
|
val colTemp_cold = colTempLinearFunc(onscreen_cold_tiles / onscreen_tiles_cap)
|
||||||
val colTemp_warm = colTempLinearFunc(-(onscreen_warm_tiles / onscreen_tiles_cap))
|
val colTemp_warm = colTempLinearFunc(-(onscreen_warm_tiles / onscreen_tiles_cap))
|
||||||
colTemp = colTemp_warm + colTemp_cold - ENV_COLTEMP_NOON
|
colTemp = colTemp_warm + colTemp_cold - ENV_COLTEMP_NOON
|
||||||
val zoom = Terrarum.ingame!!.screenZoom
|
val zoom = Terrarum.ingame?.screenZoom ?: 1f
|
||||||
|
|
||||||
blendMul()
|
blendMul()
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import java.util.*
|
|||||||
// NOTE: no Float16 on this thing: 67 kB of memory footage is totally acceptable
|
// NOTE: no Float16 on this thing: 67 kB of memory footage is totally acceptable
|
||||||
|
|
||||||
object LightmapRenderer {
|
object LightmapRenderer {
|
||||||
private val world: GameWorld = Terrarum.ingame!!.world
|
lateinit var world: GameWorld
|
||||||
|
|
||||||
|
|
||||||
// TODO if (VBO works on BlocksDrawer) THEN overscan of 256, utilise same technique in here
|
// TODO if (VBO works on BlocksDrawer) THEN overscan of 256, utilise same technique in here
|
||||||
@@ -38,9 +38,9 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
// TODO resize(int, int) -aware
|
// TODO resize(int, int) -aware
|
||||||
|
|
||||||
val LIGHTMAP_WIDTH = Terrarum.ingame!!.ZOOM_MINIMUM.inv().times(Terrarum.WIDTH)
|
val LIGHTMAP_WIDTH = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(Terrarum.WIDTH)
|
||||||
.div(FeaturesDrawer.TILE_SIZE).ceil() + overscan_open * 2 + 3
|
.div(FeaturesDrawer.TILE_SIZE).ceil() + overscan_open * 2 + 3
|
||||||
val LIGHTMAP_HEIGHT = Terrarum.ingame!!.ZOOM_MINIMUM.inv().times(Terrarum.HEIGHT)
|
val LIGHTMAP_HEIGHT = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(Terrarum.HEIGHT)
|
||||||
.div(FeaturesDrawer.TILE_SIZE).ceil() + overscan_open * 2 + 3
|
.div(FeaturesDrawer.TILE_SIZE).ceil() + overscan_open * 2 + 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +48,7 @@ object LightmapRenderer {
|
|||||||
*/
|
*/
|
||||||
// TODO utilise alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light)
|
// TODO utilise alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light)
|
||||||
private val lightmap: Array<Array<Color>> = Array(LIGHTMAP_HEIGHT) { Array(LIGHTMAP_WIDTH, { Color(0f,0f,0f,0f) }) } // TODO framebuffer?
|
private val lightmap: Array<Array<Color>> = Array(LIGHTMAP_HEIGHT) { Array(LIGHTMAP_WIDTH, { Color(0f,0f,0f,0f) }) } // TODO framebuffer?
|
||||||
private val lanternMap = ArrayList<Lantern>(Terrarum.ingame!!.ACTORCONTAINER_INITIAL_SIZE * 4)
|
private val lanternMap = ArrayList<Lantern>((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4)
|
||||||
|
|
||||||
private val AIR = Block.AIR
|
private val AIR = Block.AIR
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ object LightmapRenderer {
|
|||||||
// build noop map
|
// build noop map
|
||||||
for (i in 0..rect_size) {
|
for (i in 0..rect_size) {
|
||||||
val point = edgeToMaskNum(i)
|
val point = edgeToMaskNum(i)
|
||||||
val tile = Terrarum.ingame!!.world.getTileFromTerrain(point.first, point.second) ?: Block.NULL
|
val tile = world.getTileFromTerrain(point.first, point.second) ?: Block.NULL
|
||||||
val isSolid = BlockCodex[tile].isSolid
|
val isSolid = BlockCodex[tile].isSolid
|
||||||
|
|
||||||
noop_mask.set(i, isSolid)
|
noop_mask.set(i, isSolid)
|
||||||
@@ -235,25 +235,27 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
private fun buildLanternmap() {
|
private fun buildLanternmap() {
|
||||||
lanternMap.clear()
|
lanternMap.clear()
|
||||||
Terrarum.ingame!!.actorContainer.forEach { it ->
|
Terrarum.ingame?.let {
|
||||||
if (it is Luminous && it is ActorWithPhysics) {
|
it.actorContainer.forEach { it ->
|
||||||
// put lanterns to the area the luminantBox is occupying
|
if (it is Luminous && it is ActorWithPhysics) {
|
||||||
for (lightBox in it.lightBoxList) {
|
// put lanterns to the area the luminantBox is occupying
|
||||||
val lightBoxX = it.hitbox.startX + lightBox.startX
|
for (lightBox in it.lightBoxList) {
|
||||||
val lightBoxY = it.hitbox.startY + lightBox.startY
|
val lightBoxX = it.hitbox.startX + lightBox.startX
|
||||||
val lightBoxW = lightBox.width
|
val lightBoxY = it.hitbox.startY + lightBox.startY
|
||||||
val lightBoxH = lightBox.height
|
val lightBoxW = lightBox.width
|
||||||
for (y in lightBoxY.div(TILE_SIZE).floorInt()
|
val lightBoxH = lightBox.height
|
||||||
..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) {
|
for (y in lightBoxY.div(TILE_SIZE).floorInt()
|
||||||
for (x in lightBoxX.div(TILE_SIZE).floorInt()
|
..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) {
|
||||||
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
|
for (x in lightBoxX.div(TILE_SIZE).floorInt()
|
||||||
|
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
|
||||||
|
|
||||||
val normalisedColor = it.color.cpy().mul(DIV_FLOAT)
|
val normalisedColor = it.color.cpy().mul(DIV_FLOAT)
|
||||||
|
|
||||||
lanternMap.add(Lantern(x, y, normalisedColor))
|
lanternMap.add(Lantern(x, y, normalisedColor))
|
||||||
// Q&D fix for Roundworld anomaly
|
// Q&D fix for Roundworld anomaly
|
||||||
lanternMap.add(Lantern(x + world.width, y, normalisedColor))
|
lanternMap.add(Lantern(x + world.width, y, normalisedColor))
|
||||||
lanternMap.add(Lantern(x - world.width, y, normalisedColor))
|
lanternMap.add(Lantern(x - world.width, y, normalisedColor))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,11 +272,11 @@ object LightmapRenderer {
|
|||||||
var ambientAccumulator = Color(0f,0f,0f,0f)
|
var ambientAccumulator = Color(0f,0f,0f,0f)
|
||||||
|
|
||||||
var lightLevelThis: Color = Color(0f,0f,0f,0f)
|
var lightLevelThis: Color = Color(0f,0f,0f,0f)
|
||||||
val thisTerrain = Terrarum.ingame!!.world.getTileFromTerrain(x, y)
|
val thisTerrain = world.getTileFromTerrain(x, y)
|
||||||
val thisWall = Terrarum.ingame!!.world.getTileFromWall(x, y)
|
val thisWall = world.getTileFromWall(x, y)
|
||||||
val thisTileLuminosity = BlockCodex[thisTerrain].luminosity // already been div by four
|
val thisTileLuminosity = BlockCodex[thisTerrain].luminosity // already been div by four
|
||||||
val thisTileOpacity = BlockCodex[thisTerrain].opacity // already been div by four
|
val thisTileOpacity = BlockCodex[thisTerrain].opacity // already been div by four
|
||||||
val sunLight = Terrarum.ingame!!.world.globalLight.cpy().mul(DIV_FLOAT)
|
val sunLight = world.globalLight.cpy().mul(DIV_FLOAT)
|
||||||
|
|
||||||
// MIX TILE
|
// MIX TILE
|
||||||
// open air
|
// open air
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.worlddrawer
|
|||||||
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameactors.floor
|
import net.torvald.terrarum.gameactors.floor
|
||||||
import net.torvald.terrarum.gameactors.floorInt
|
import net.torvald.terrarum.gameactors.floorInt
|
||||||
import net.torvald.terrarum.gameactors.roundInt
|
import net.torvald.terrarum.gameactors.roundInt
|
||||||
@@ -12,7 +13,6 @@ import net.torvald.terrarum.round
|
|||||||
* Created by minjaesong on 2016-12-30.
|
* Created by minjaesong on 2016-12-30.
|
||||||
*/
|
*/
|
||||||
object WorldCamera {
|
object WorldCamera {
|
||||||
private val world: GameWorld? = Terrarum.ingame?.world
|
|
||||||
private val TILE_SIZE = FeaturesDrawer.TILE_SIZE
|
private val TILE_SIZE = FeaturesDrawer.TILE_SIZE
|
||||||
|
|
||||||
var x: Int = 0 // left position
|
var x: Int = 0 // left position
|
||||||
@@ -32,22 +32,20 @@ object WorldCamera {
|
|||||||
val yCentre: Int
|
val yCentre: Int
|
||||||
get() = y + height.ushr(1)
|
get() = y + height.ushr(1)
|
||||||
|
|
||||||
fun update() {
|
fun update(world: GameWorld, player: ActorWithBody) {
|
||||||
if (Terrarum.ingame != null) {
|
if (Terrarum.ingame != null) {
|
||||||
|
|
||||||
val player = Terrarum.ingame!!.player
|
width = FastMath.ceil(Terrarum.WIDTH / (Terrarum.ingame?.screenZoom ?: 1f)) // div, not mul
|
||||||
|
height = FastMath.ceil(Terrarum.HEIGHT / (Terrarum.ingame?.screenZoom ?: 1f))
|
||||||
width = FastMath.ceil(Terrarum.WIDTH / Terrarum.ingame!!.screenZoom) // div, not mul
|
|
||||||
height = FastMath.ceil(Terrarum.HEIGHT / Terrarum.ingame!!.screenZoom)
|
|
||||||
|
|
||||||
// position - (WH / 2)
|
// position - (WH / 2)
|
||||||
x = (// X only: ROUNDWORLD implementation
|
x = (// X only: ROUNDWORLD implementation
|
||||||
(player?.hitbox?.centeredX?.toFloat() ?: 0f) - width / 2).floorInt()
|
player.hitbox.centeredX.toFloat() - width / 2).floorInt()
|
||||||
y = (FastMath.clamp(
|
y = (FastMath.clamp(
|
||||||
(player?.hitbox?.centeredY?.toFloat() ?: 0f) - height / 2,
|
player.hitbox.centeredY.toFloat() - height / 2,
|
||||||
TILE_SIZE.toFloat(),
|
TILE_SIZE.toFloat(),
|
||||||
world!!.height * TILE_SIZE - height - TILE_SIZE.toFloat()
|
world.height * TILE_SIZE - height - TILE_SIZE.toFloat()
|
||||||
)).floorInt().clampCameraY()
|
)).floorInt().clampCameraY(world)
|
||||||
|
|
||||||
|
|
||||||
gdxCamX = x + (width / 2f).floor()
|
gdxCamX = x + (width / 2f).floor()
|
||||||
@@ -55,11 +53,11 @@ object WorldCamera {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Int.clampCameraY(): Int {
|
private fun Int.clampCameraY(world: GameWorld): Int {
|
||||||
return if (this < 0)
|
return if (this < 0)
|
||||||
0
|
0
|
||||||
else if (this > (world?.height ?: Terrarum.HEIGHT).times(TILE_SIZE) - Terrarum.HEIGHT)
|
else if (this > world.height.times(TILE_SIZE) - Terrarum.HEIGHT)
|
||||||
(world?.height ?: Terrarum.HEIGHT).times(TILE_SIZE) - Terrarum.HEIGHT
|
world.height.times(TILE_SIZE) - Terrarum.HEIGHT
|
||||||
else
|
else
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.Random
|
|||||||
object FloatingIslandsPreset {
|
object FloatingIslandsPreset {
|
||||||
|
|
||||||
val PRESETS = 5
|
val PRESETS = 5
|
||||||
|
val MAX_HEIGHT = 100 // arbitrary value
|
||||||
|
|
||||||
internal fun generatePreset(random: HQRNG): Array<IntArray> {
|
internal fun generatePreset(random: HQRNG): Array<IntArray> {
|
||||||
val index = random.nextInt(PRESETS)
|
val index = random.nextInt(PRESETS)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.sudoplay.joise.Joise
|
|||||||
import com.sudoplay.joise.module.*
|
import com.sudoplay.joise.module.*
|
||||||
import net.torvald.terrarum.LoadScreen
|
import net.torvald.terrarum.LoadScreen
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel
|
import net.torvald.terrarum.concurrent.ThreadParallel
|
||||||
import net.torvald.terrarum.gameactors.roundInt
|
import net.torvald.terrarum.gameactors.roundInt
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -64,6 +65,10 @@ object WorldGenerator {
|
|||||||
|
|
||||||
internal val TILE_MACRO_ALL = -1
|
internal val TILE_MACRO_ALL = -1
|
||||||
|
|
||||||
|
private var floatingIslandDownMax = 0
|
||||||
|
|
||||||
|
private var realMinimumHeight = 708 // minimum height on current setting. 705 + some headroom
|
||||||
|
|
||||||
fun attachMap(world: GameWorld) {
|
fun attachMap(world: GameWorld) {
|
||||||
this.world = world
|
this.world = world
|
||||||
WIDTH = world.width
|
WIDTH = world.width
|
||||||
@@ -78,6 +83,20 @@ object WorldGenerator {
|
|||||||
OCEAN_WIDTH = Math.round(OCEAN_WIDTH * widthMulFactor)
|
OCEAN_WIDTH = Math.round(OCEAN_WIDTH * widthMulFactor)
|
||||||
SHORE_WIDTH = Math.round(SHORE_WIDTH * widthMulFactor)
|
SHORE_WIDTH = Math.round(SHORE_WIDTH * widthMulFactor)
|
||||||
GLACIER_MOUNTAIN_WIDTH = Math.round(GLACIER_MOUNTAIN_WIDTH * widthMulFactor)
|
GLACIER_MOUNTAIN_WIDTH = Math.round(GLACIER_MOUNTAIN_WIDTH * widthMulFactor)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// just a code took from island generator
|
||||||
|
floatingIslandDownMax = minimumFloatingIsleHeight * 2 + FloatingIslandsPreset.MAX_HEIGHT
|
||||||
|
|
||||||
|
/*if (TERRAIN_AVERAGE_HEIGHT - TERRAIN_UNDULATION.div(2) -floatingIslandDownMax <= 0) {
|
||||||
|
throw RuntimeException("Terrain height is too small -- must be greater than " +
|
||||||
|
"${HEIGHT - (TERRAIN_AVERAGE_HEIGHT - TERRAIN_UNDULATION.div(2) -floatingIslandDownMax)}"
|
||||||
|
)
|
||||||
|
}*/
|
||||||
|
if (HEIGHT < realMinimumHeight) {
|
||||||
|
throw RuntimeException("Terrain height must be greater than $realMinimumHeight")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,16 +176,25 @@ object WorldGenerator {
|
|||||||
generateFloatingIslands()
|
generateFloatingIslands()
|
||||||
|
|
||||||
//wire layer
|
//wire layer
|
||||||
for (i in 0..HEIGHT - 1) {
|
Arrays.fill(world.wireArray, 0.toByte())
|
||||||
for (j in 0..WIDTH - 1) {
|
|
||||||
world.wireArray[i][j] = 0
|
|
||||||
}
|
// determine spawn position
|
||||||
}
|
world.spawnY = getSpawnHeight(world.spawnX)
|
||||||
|
|
||||||
|
|
||||||
// Free some memories
|
// Free some memories
|
||||||
System.gc()
|
System.gc()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSpawnHeight(x: Int): Int {
|
||||||
|
var y = minimumFloatingIsleHeight * 2 + FloatingIslandsPreset.MAX_HEIGHT
|
||||||
|
while (!BlockCodex[world.getTileFromTerrain(x, y)].isSolid) {
|
||||||
|
y += 1
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
/* 1. Raise */
|
/* 1. Raise */
|
||||||
|
|
||||||
private fun noiseRidged(xStretch: Double, yStretch: Double): Joise {
|
private fun noiseRidged(xStretch: Double, yStretch: Double): Joise {
|
||||||
@@ -485,7 +513,6 @@ object WorldGenerator {
|
|||||||
val sampleY = y / SCALE_Y * 1.5 - 0.6
|
val sampleY = y / SCALE_Y * 1.5 - 0.6
|
||||||
val map: Boolean = joise.get(sampleX, sampleY, sampleZ) == 1.0
|
val map: Boolean = joise.get(sampleX, sampleY, sampleZ) == 1.0
|
||||||
|
|
||||||
// FIXME joise.get(sampleX, sampleY, sampleZ) returns all zero
|
|
||||||
noiseMap[y + TERRAIN_AVERAGE_HEIGHT - (TERRAIN_UNDULATION / 2)].set(x, map)
|
noiseMap[y + TERRAIN_AVERAGE_HEIGHT - (TERRAIN_UNDULATION / 2)].set(x, map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -812,7 +839,7 @@ object WorldGenerator {
|
|||||||
LoadScreen.addMessage("Flooding with lava...")
|
LoadScreen.addMessage("Flooding with lava...")
|
||||||
for (i in HEIGHT * 14 / 15..HEIGHT - 1) {
|
for (i in HEIGHT * 14 / 15..HEIGHT - 1) {
|
||||||
for (j in 0..WIDTH - 1) {
|
for (j in 0..WIDTH - 1) {
|
||||||
if (world.terrainArray[i][j].toInt() == 0) {
|
if (world.getTileFromTerrain(j, i) == 0) {
|
||||||
world.setTileTerrain(j, i, Block.LAVA)
|
world.setTileTerrain(j, i, Block.LAVA)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -997,25 +1024,6 @@ object WorldGenerator {
|
|||||||
return FastMath.sqrt(FastMath.pow(x1 - x2, 2f) + FastMath.pow(y2 - y1, 2f))
|
return FastMath.sqrt(FastMath.pow(x1 - x2, 2f) + FastMath.pow(y2 - y1, 2f))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun circularDig(i: Int, j: Int, brushSize: Int, fillFrom: Int, fill: Int) {
|
|
||||||
val halfBrushSize = brushSize * 0.5f
|
|
||||||
|
|
||||||
for (pointerY in 0..brushSize - 1) {
|
|
||||||
for (pointerX in 0..brushSize - 1) {
|
|
||||||
if (getDistance(j.toFloat(), i.toFloat(), j + pointerX - halfBrushSize, i + pointerY - halfBrushSize) <= FastMath.floor((brushSize / 2).toFloat()) - 1) {
|
|
||||||
if (Math.round(j + pointerX - halfBrushSize) > brushSize
|
|
||||||
&& Math.round(j + pointerX - halfBrushSize) < WIDTH - brushSize
|
|
||||||
&& Math.round(i + pointerY - halfBrushSize) > brushSize
|
|
||||||
&& Math.round(i + pointerY - halfBrushSize) < HEIGHT - brushSize) {
|
|
||||||
if (world.terrainArray[Math.round(i + pointerY - halfBrushSize)][Math.round(j + pointerX - halfBrushSize)] == fillFrom.toByte()) {
|
|
||||||
world.terrainArray[Math.round(i + pointerY - halfBrushSize)][Math.round(j + pointerX - halfBrushSize)] = fill.toByte()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun clamp(x: Int, min: Int, max: Int): Int = if (x < min) min else if (x > max) max else x
|
private fun clamp(x: Int, min: Int, max: Int): Int = if (x < min) min else if (x > max) max else x
|
||||||
|
|
||||||
data class TaggedSimplexNoise(var noiseModule: SimplexNoise, var xStretch: Float, var yStretch: Float)
|
data class TaggedSimplexNoise(var noiseModule: SimplexNoise, var xStretch: Float, var yStretch: Float)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Ord Hex Description
|
|||||||
02 4D M
|
02 4D M
|
||||||
03 44 D
|
03 44 D
|
||||||
|
|
||||||
04 01 Number of bits per tile divided by 8, only 1 is supported
|
04 01 Number of bytes per tile; only 1 is supported
|
||||||
|
|
||||||
05 Number of layers
|
05 Number of layers
|
||||||
|
|
||||||
@@ -35,13 +35,17 @@ Ord Hex Description
|
|||||||
16 Default spawn coord Y
|
16 Default spawn coord Y
|
||||||
17 Default spawn coord Y
|
17 Default spawn coord Y
|
||||||
|
|
||||||
18 Terrain tiles data (MSB)
|
# Layer count 1
|
||||||
|
18 Terrain tiles data MSB
|
||||||
|
|
||||||
... Wall tiles data (MSB)
|
# Layer count 2
|
||||||
|
... Wall tiles data MSB
|
||||||
|
|
||||||
... Tiles data (LSB)
|
# Layer count 3
|
||||||
0bAAAABBBB - A: Terrain, B: Wall (0-15)
|
... Terrain tiles data LSB (half size of MSB byte array)
|
||||||
|
... Wall tiles data LSB (half size of MSB byte array)
|
||||||
|
|
||||||
|
# Layer count 4
|
||||||
... Wire tiles data (0-255)
|
... Wire tiles data (0-255)
|
||||||
|
|
||||||
<EOF>
|
<EOF>
|
||||||
@@ -16,6 +16,8 @@ Multiple maps are multiverse in this game; users don't have an access to the mul
|
|||||||
|
|
||||||
Let's be honest: when you play the Terraria bit heavily, you create multiple world to farm resources; this is cheat and you know it, which is why, in this game, you technically can but after hard working so that it'd be less of a cheat.
|
Let's be honest: when you play the Terraria bit heavily, you create multiple world to farm resources; this is cheat and you know it, which is why, in this game, you technically can but after hard working so that it'd be less of a cheat.
|
||||||
|
|
||||||
|
You can "invite" other persona to your world, from sharing things to multiplayer-on-your-own, but you need to issue "interspace ticket", which will be expensive of course.
|
||||||
|
|
||||||
### New World (New Universe)
|
### New World (New Universe)
|
||||||
|
|
||||||
The teleporter also works as "world manager"; players can create new world or delete existing ones. Lore-wise, creation and deletion is regarded as linking and unlinking.
|
The teleporter also works as "world manager"; players can create new world or delete existing ones. Lore-wise, creation and deletion is regarded as linking and unlinking.
|
||||||
|
|||||||
Reference in New Issue
Block a user