grow grass randomly on dirt if viable

This commit is contained in:
minjaesong
2023-09-15 22:45:58 +09:00
parent 016c23a97f
commit 932204deed
2 changed files with 91 additions and 53 deletions

View File

@@ -97,7 +97,7 @@ public class UnpackedColourSpriteBatch extends SpriteBatch {
this(size, null);
}
private static int VERTEX_ATTR_SIZE = 48;
private static final int VERTEX_ATTR_SIZE = 48;
/** Constructs a new SpriteBatch. Sets the projection matrix to an orthographic projection with y-axis point upwards, x-axis
* point to the right and the origin being in the bottom left corner of the screen. The projection will be pixel perfect with

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.gameworld
import com.badlogic.gdx.utils.Queue
import net.torvald.random.HQRNG
import net.torvald.terrarum.*
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
@@ -34,10 +35,10 @@ object WorldSimulator {
const private val DOUBLE_RADIUS = FLUID_UPDATING_SQUARE_RADIUS * 2
// maps are separated as old-new for obvious reason, also it'll allow concurrent modification
private val fluidMap = Array(DOUBLE_RADIUS, { FloatArray(DOUBLE_RADIUS) })
private val fluidTypeMap = Array(DOUBLE_RADIUS, { Array<FluidType>(DOUBLE_RADIUS) { Fluid.NULL } })
private val fluidNewMap = Array(DOUBLE_RADIUS, { FloatArray(DOUBLE_RADIUS) })
private val fluidNewTypeMap = Array(DOUBLE_RADIUS, { Array<FluidType>(DOUBLE_RADIUS) { Fluid.NULL } })
private val fluidMap = Array(DOUBLE_RADIUS) { FloatArray(DOUBLE_RADIUS) }
private val fluidTypeMap = Array(DOUBLE_RADIUS) { Array(DOUBLE_RADIUS) { Fluid.NULL } }
private val fluidNewMap = Array(DOUBLE_RADIUS) { FloatArray(DOUBLE_RADIUS) }
private val fluidNewTypeMap = Array(DOUBLE_RADIUS) { Array(DOUBLE_RADIUS) { Fluid.NULL } }
const val FLUID_MAX_MASS = 1f // The normal, un-pressurized mass of a full water cell
const val FLUID_MAX_COMP = 0.02f // How much excess water a cell can store, compared to the cell above it. A tile of fluid can contain more than MaxMass water.
@@ -67,6 +68,8 @@ object WorldSimulator {
}
private val rng = HQRNG()
/** Must be called BEFORE the actors update -- actors depend on the R-Tree for various things */
operator fun invoke(player: ActorHumanoid?, delta: Float) {
@@ -80,75 +83,85 @@ object WorldSimulator {
updateYTo = updateYFrom + DOUBLE_RADIUS
}
degrass()
App.measureDebugTime("WorldSimulator.fluids") {
//moveFluids(delta)
}
App.measureDebugTime("WorldSimulator.fallables") {
displaceFallables(delta)
}
if (ingame.terrainChangeQueue.isNotEmpty()) { App.measureDebugTime("WorldSimulator.degrass") { buryGrassImmediately() } }
App.measureDebugTime("WorldSimulator.growGrass") { growOrKillGrass() }
App.measureDebugTime("WorldSimulator.fluids") { /*moveFluids(delta)*/ }
App.measureDebugTime("WorldSimulator.fallables") { displaceFallables(delta) }
if (ingame.WORLD_UPDATE_TIMER % 2 == 1) {
App.measureDebugTime("WorldSimulator.wires") {
simulateWires(delta)
}
App.measureDebugTime("WorldSimulator.wires") { simulateWires(delta) }
}
else {
// TODO update logic
}
App.measureDebugTime("WorldSimulator.collisionDroppedItem") {
collideDroppedItems()
}
App.measureDebugTime("WorldSimulator.collisionDroppedItem") { collideDroppedItems() }
//printdbg(this, "============================")
}
fun degrass() {
if (ingame.terrainChangeQueue.isNotEmpty()) { App.measureDebugTime("WorldSimulator.degrass") {
fun buryGrassImmediately() {
//val grassPlacedByPlayer = ArrayList<IngameInstance.BlockChangeQueueItem>()
//val grassPlacedByPlayer = ArrayList<IngameInstance.BlockChangeQueueItem>()
ingame.terrainChangeQueue.forEach {
if (BlockCodex[it.new].isSolid) {
if (world.getTileFromTerrain(it.posX, it.posY + 1) == Block.GRASS) {
//grassPlacedByPlayer.add(it)
world.setTileTerrain(it.posX, it.posY + 1, Block.DIRT, true)
}
ingame.terrainChangeQueue.forEach {
if (BlockCodex[it.new].isSolid) {
if (world.getTileFromTerrain(it.posX, it.posY + 1) == Block.GRASS) {
//grassPlacedByPlayer.add(it)
world.setTileTerrain(it.posX, it.posY + 1, Block.DIRT, true)
}
}
}
// kill grasses surrounded by dirts in cruciform formation
// NOPE this part would not work; environment-depending degrassing must be done by the "grass spread simulator"
/*val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorToInt()
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical - 1
// kill grasses surrounded by dirts in cruciform formation
// NOPE this part would not work; environment-depending degrassing must be done by the "grass spread simulator"
/*val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorToInt()
val for_y_end = for_y_start + BlocksDrawer.tilesInVertical - 1
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorToInt()
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal - 1
for (y in for_y_start..for_y_end) {
for (x in for_x_start..for_x_end) {
// do not de-grass ones placed by player
var nogo = false
grassPlacedByPlayer.forEach {
if (x == it.posX && y == it.posY) nogo = true
}
val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorToInt()
val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal - 1
for (y in for_y_start..for_y_end) {
for (x in for_x_start..for_x_end) {
// do not de-grass ones placed by player
var nogo = false
grassPlacedByPlayer.forEach {
if (x == it.posX && y == it.posY) nogo = true
}
if (!nogo) {
val tile = world.getTileFromTerrain(x, y)
if (tile == Block.GRASS) {
if (world.getTileFromTerrain(x - 1, y) != Block.GRASS &&
world.getTileFromTerrain(x + 1, y) != Block.GRASS &&
world.getTileFromTerrain(x, y - 1) != Block.GRASS &&
world.getTileFromTerrain(x, y + 1) != Block.GRASS) {
world.setTileTerrain(x, y, Block.DIRT, true)
}
if (!nogo) {
val tile = world.getTileFromTerrain(x, y)
if (tile == Block.GRASS) {
if (world.getTileFromTerrain(x - 1, y) != Block.GRASS &&
world.getTileFromTerrain(x + 1, y) != Block.GRASS &&
world.getTileFromTerrain(x, y - 1) != Block.GRASS &&
world.getTileFromTerrain(x, y + 1) != Block.GRASS) {
world.setTileTerrain(x, y, Block.DIRT, true)
}
}
}
}*/
}
}*/
}
} }
fun growOrKillGrass() {
repeat(2) {
val rx = rng.nextInt(updateXFrom, updateXTo + 1)
val ry = rng.nextInt(updateYFrom, updateYTo + 1)
val tile = world.getTileFromTerrain(rx, ry)
// if the dirt tile has a grass and an air tile nearby, put grass to it
if (tile == Block.DIRT) {
val nearby = getNearbyTiles8(rx, ry)
if (nearby.any { !BlockCodex[it].isSolid } && nearby.any { it == Block.GRASS }) {
world.setTileTerrain(rx, ry, Block.GRASS, false)
}
}
// if the grass tile is confined, kill it
else if (tile == Block.GRASS) {
val nearby = getNearbyTiles8(rx, ry)
if (nearby.all { BlockCodex[it].isSolid }) {
world.setTileTerrain(rx, ry, Block.DIRT, false)
}
}
}
}
fun collideDroppedItems() {
@@ -587,6 +600,31 @@ object WorldSimulator {
)
}
private fun getNearbyTilesPos8(x: Int, y: Int): Array<Point2i> {
return arrayOf(
Point2i(x + 1, y),
Point2i(x + 1, y + 1),
Point2i(x, y + 1),
Point2i(x - 1, y + 1),
Point2i(x - 1, y),
Point2i(x - 1, y - 1),
Point2i(x, y - 1),
Point2i(x + 1, y - 1)
)
}
private fun getNearbyTiles(x: Int, y: Int): List<ItemID> {
return getNearbyTilesPos(x, y).map { world.getTileFromTerrain(it.x, it.y) }
}
private fun getNearbyTiles8(x: Int, y: Int): List<ItemID> {
return getNearbyTilesPos8(x, y).map { world.getTileFromTerrain(it.x, it.y) }
}
private fun getNearbyWalls(x: Int, y: Int): List<ItemID> {
return getNearbyTilesPos(x, y).map { world.getTileFromWall(it.x, it.y) }
}
private fun getNearbyWalls8(x: Int, y: Int): List<ItemID> {
return getNearbyTilesPos8(x, y).map { world.getTileFromWall(it.x, it.y) }
}
data class WireGraphCursor(
var x: Int,
var y: Int,