mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-14 12:34:05 +09:00
more clouds
This commit is contained in:
@@ -2,17 +2,17 @@
|
|||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
"daylightClut": "clut_daylight.tga",
|
"daylightClut": "clut_daylight.tga",
|
||||||
"classification": "generic",
|
"classification": "generic",
|
||||||
"cloudChance": 6,
|
"cloudChance": 10,
|
||||||
"cloudGamma": [0.59, 2.0],
|
"cloudGamma": [0.59, 2.0],
|
||||||
"cloudDriftSpeed": 0.4,
|
"cloudDriftSpeed": 10.4,
|
||||||
"clouds": {
|
"clouds": {
|
||||||
"normal": {
|
|
||||||
"filename": "cloud_normal.png",
|
|
||||||
"tw": 1024, "th": 512, "probability": 1.0, "baseScale": 0.4, "scaleVariance": 0.2
|
|
||||||
},
|
|
||||||
"large": {
|
"large": {
|
||||||
"filename": "cloud_large.png",
|
"filename": "cloud_large.png",
|
||||||
"tw": 2048, "th": 1024, "probability": 0.1, "baseScale": 0.26, "scaleVariance": 0.2
|
"tw": 2048, "th": 1024, "probability": 0.2, "baseScale": 0.45, "scaleVariance": 0.7
|
||||||
|
},
|
||||||
|
"normal": {
|
||||||
|
"filename": "cloud_normal.png",
|
||||||
|
"tw": 1024, "th": 512, "probability": 1.0, "baseScale": 0.5, "scaleVariance": 0.8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.weather
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.math.Vector3
|
import com.badlogic.gdx.math.Vector3
|
||||||
@@ -192,7 +193,9 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
it?.let {
|
it?.let {
|
||||||
it.update(cloudDriftVector, currentWeather.cloudDriftSpeed)
|
it.update(cloudDriftVector, currentWeather.cloudDriftSpeed)
|
||||||
|
|
||||||
if (it.posX < -1500f || it.posX > App.scr.width + 1500f || it.scale < 1f / 2048f) {
|
val pjx = it.posX / it.posZ
|
||||||
|
|
||||||
|
if (pjx !in -1500f..App.scr.wf + 1500f || it.scale < 1f / 2048f) {
|
||||||
it.flagToDespawn = true
|
it.flagToDespawn = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -211,11 +214,20 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
private val scrHscaler = App.scr.height / 720f
|
private val scrHscaler = App.scr.height / 720f
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param range: range of the randomised number
|
||||||
|
* @param random: random number in the range of `[-1, 1]`
|
||||||
|
*/
|
||||||
|
private fun randomPosWithin(range: ClosedFloatingPointRange<Float>, random: Float) =
|
||||||
|
((range.start + range.endInclusive) / 2f) + random * (range.endInclusive - range.start) / 2f
|
||||||
|
|
||||||
private fun tryToSpawnCloud(currentWeather: BaseModularWeather) {
|
private fun tryToSpawnCloud(currentWeather: BaseModularWeather) {
|
||||||
printdbg(this, "Trying to spawn a cloud... (${cloudsSpawned} / ${clouds.size})")
|
printdbg(this, "Trying to spawn a cloud... (${cloudsSpawned} / ${clouds.size})")
|
||||||
|
|
||||||
if (cloudsSpawned < clouds.size) {
|
if (cloudsSpawned < clouds.size) {
|
||||||
|
val flip = Math.random() < 0.5
|
||||||
val rC = Math.random().toFloat()
|
val rC = Math.random().toFloat()
|
||||||
|
val rZ = (Math.random() * 3.0 + 1.0).toFloat() // 1..4
|
||||||
val r0 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
val r0 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
||||||
val r1 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
val r1 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
||||||
val r2 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
val r2 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
||||||
@@ -237,15 +249,15 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
cloudsToSpawn?.let { cloud ->
|
cloudsToSpawn?.let { cloud ->
|
||||||
val scaleVariance = 1f + rT1.absoluteValue * cloud.scaleVariance
|
val scaleVariance = 1f + rT1.absoluteValue * cloud.scaleVariance
|
||||||
val cloudScale = cloud.baseScale * (if (rT1 < 0) 1f / scaleVariance else scaleVariance)
|
val cloudScale = cloud.baseScale * (if (rT1 < 0) 1f / scaleVariance else scaleVariance)
|
||||||
val hCloudSize = cloud.spriteSheet.tileW * cloudScale + 1f
|
val hCloudSize = (cloud.spriteSheet.tileW * cloudScale) + 1f
|
||||||
val posX = if (cloudDriftVector.x < 0) App.scr.width + hCloudSize else -hCloudSize
|
val posX = if (cloudDriftVector.x < 0) (App.scr.width + hCloudSize) * rZ else -hCloudSize * rZ
|
||||||
val posY = when (cloud.category) {
|
val posY = when (cloud.category) {
|
||||||
"large" -> (100f + r0 * 80f) * scrHscaler
|
"large" -> randomPosWithin(-10f..120f, r0) * scrHscaler
|
||||||
else -> (150f + r0 * 50f) * scrHscaler
|
else -> randomPosWithin(-50f..150f, r0) * scrHscaler // -50..150
|
||||||
}
|
}
|
||||||
val sheetX = rA % cloud.spriteSheet.horizontalCount
|
val sheetX = rA % cloud.spriteSheet.horizontalCount
|
||||||
val sheetY = rB % cloud.spriteSheet.verticalCount
|
val sheetY = rB % cloud.spriteSheet.verticalCount
|
||||||
WeatherObjectCloud(cloud.spriteSheet.get(sheetX, sheetY)).also {
|
WeatherObjectCloud(cloud.spriteSheet.get(sheetX, sheetY), flip).also {
|
||||||
it.scale = cloudScale
|
it.scale = cloudScale
|
||||||
|
|
||||||
it.darkness.set(currentWeather.cloudGamma)
|
it.darkness.set(currentWeather.cloudGamma)
|
||||||
@@ -255,12 +267,13 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
it.posX = posX
|
it.posX = posX
|
||||||
it.posY = posY
|
it.posY = posY
|
||||||
|
it.posZ = rZ
|
||||||
|
|
||||||
clouds.addAtFreeSpot(it)
|
clouds.addAtFreeSpot(it)
|
||||||
cloudsSpawned += 1
|
cloudsSpawned += 1
|
||||||
|
|
||||||
|
|
||||||
printdbg(this, "... Spawning ${cloud.category}($sheetX, $sheetY) cloud at pos ${it.pos}, invGamma ${it.darkness}")
|
printdbg(this, "... Spawning ${cloud.category}($sheetX, $sheetY) cloud at pos ${it.pos}, scale ${it.scale}, invGamma ${it.darkness}")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -289,25 +302,21 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
*/
|
*/
|
||||||
internal fun render(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
internal fun render(camera: Camera, batch: FlippingSpriteBatch, world: GameWorld) {
|
||||||
drawSkybox(camera, batch, world)
|
drawSkybox(camera, batch, world)
|
||||||
|
drawClouds(batch)
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun drawClouds(batch: SpriteBatch) {
|
||||||
|
|
||||||
|
|
||||||
batch.color = globalLightNow.toGdxColor().also {
|
batch.color = globalLightNow.toGdxColor().also {
|
||||||
it.a = 1f
|
it.a = 1f
|
||||||
} // TODO add cloud-only colour strip on the CLUT
|
} // TODO add cloud-only colour strip on the CLUT
|
||||||
batch.shader = shaderClouds
|
batch.shader = shaderClouds
|
||||||
clouds.forEach {
|
clouds.filterNotNull().sortedByDescending { it.posZ }.forEach {
|
||||||
it?.let {
|
batch.inUse { _ ->
|
||||||
batch.inUse { _ ->
|
batch.shader.setUniformf("gamma", it.darkness)
|
||||||
batch.shader.setUniformf("gamma", it.darkness)
|
it.render(batch, 0f, 0f) // TODO parallax
|
||||||
it.render(batch, 0f, 0f) // TODO parallax
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
batch.color = Color.WHITE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val parallaxDomainSize = 400f
|
private val parallaxDomainSize = 400f
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import com.badlogic.gdx.utils.Disposable
|
|||||||
abstract class WeatherObject : Disposable {
|
abstract class WeatherObject : Disposable {
|
||||||
|
|
||||||
/** vec3(posX, posY, scale) */
|
/** vec3(posX, posY, scale) */
|
||||||
var pos: Vector3 = Vector3()
|
var pos: Vector3 = Vector3(0f, 0f, 1f)
|
||||||
|
|
||||||
var posX: Float
|
var posX: Float
|
||||||
get() = pos.x
|
get() = pos.x
|
||||||
@@ -18,9 +18,10 @@ abstract class WeatherObject : Disposable {
|
|||||||
var posY: Float
|
var posY: Float
|
||||||
get() = pos.y
|
get() = pos.y
|
||||||
set(value) { pos.y = value }
|
set(value) { pos.y = value }
|
||||||
var scale: Float
|
var posZ: Float
|
||||||
get() = pos.z
|
get() = pos.z
|
||||||
set(value) { pos.z = value }
|
set(value) { pos.z = value }
|
||||||
|
var scale: Float = 1f
|
||||||
|
|
||||||
var flagToDespawn = false
|
var flagToDespawn = false
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
import com.badlogic.gdx.math.Vector2
|
import com.badlogic.gdx.math.Vector2
|
||||||
import com.badlogic.gdx.math.Vector3
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import net.torvald.terrarum.App
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-08-21.
|
* Created by minjaesong on 2023-08-21.
|
||||||
*/
|
*/
|
||||||
class WeatherObjectCloud(private val texture: TextureRegion) : WeatherObject() {
|
class WeatherObjectCloud(private val texture: TextureRegion, private val flipW: Boolean) : WeatherObject() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To actually utilise this value, your render code must begin the spritebatch per-object, like so:
|
* To actually utilise this value, your render code must begin the spritebatch per-object, like so:
|
||||||
@@ -32,8 +33,8 @@ class WeatherObjectCloud(private val texture: TextureRegion) : WeatherObject() {
|
|||||||
* Resulting vector: (x + dX, y + dY, scale * dScale)
|
* Resulting vector: (x + dX, y + dY, scale * dScale)
|
||||||
*/
|
*/
|
||||||
fun update(flowVector: Vector3, gait: Float) {
|
fun update(flowVector: Vector3, gait: Float) {
|
||||||
posX += flowVector.x * gait * scale * scale
|
posX += flowVector.x * gait * scale
|
||||||
posY += flowVector.y * gait * scale * scale
|
posY += flowVector.y * gait * scale
|
||||||
scale *= flowVector.z
|
scale *= flowVector.z
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,8 +45,18 @@ class WeatherObjectCloud(private val texture: TextureRegion) : WeatherObject() {
|
|||||||
override fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float) {
|
override fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float) {
|
||||||
val x = posX + offsetX - texture.regionWidth * scale * 0.5f
|
val x = posX + offsetX - texture.regionWidth * scale * 0.5f
|
||||||
val y = posY + offsetY - texture.regionHeight * scale
|
val y = posY + offsetY - texture.regionHeight * scale
|
||||||
|
val z = posZ // must be at least 1.0
|
||||||
|
val w = App.scr.halfwf
|
||||||
|
val h = App.scr.halfhf // 50% to the screen height, or 35%?
|
||||||
|
|
||||||
batch.draw(texture, x, y, texture.regionWidth * scale, texture.regionHeight * scale)
|
val drawX = (x + w * (z-1)) / z
|
||||||
|
val drawY = (y + h * (z-1)) / z
|
||||||
|
val drawScale = scale / z
|
||||||
|
|
||||||
|
if (flipW)
|
||||||
|
batch.draw(texture, drawX + texture.regionWidth / z, drawY, -texture.regionWidth * drawScale, texture.regionHeight * drawScale)
|
||||||
|
else
|
||||||
|
batch.draw(texture, drawX, drawY, texture.regionWidth * drawScale, texture.regionHeight * drawScale)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() { /* cloud texture will be disposed of by the WeatherMixer */ }
|
override fun dispose() { /* cloud texture will be disposed of by the WeatherMixer */ }
|
||||||
|
|||||||
Reference in New Issue
Block a user