DEADSOFTWARE

Prettier world + ores
authorfredboy <fredboy@protonmail.com>
Tue, 23 Apr 2024 21:00:38 +0000 (04:00 +0700)
committerfredboy <fredboy@protonmail.com>
Tue, 23 Apr 2024 21:05:43 +0000 (04:05 +0700)
27 files changed:
android/assets/json/game_items.json
android/assets/textures/blocks/grass_snowed.png [new file with mode: 0644]
android/assets/textures/blocks/leaves_birch.png [deleted file]
android/assets/textures/blocks/leaves_oak.png
android/assets/textures/blocks/leaves_spruce.png [deleted file]
core/src/ru/deadsoftware/cavedroid/game/actions/UpdateBlockActionsModule.kt
core/src/ru/deadsoftware/cavedroid/game/actions/UseItemActionsModule.kt
core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSnowedGrassAction.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseEmptyBucketAction.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseLavaBucketAction.kt
core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseWaterBucketAction.kt
core/src/ru/deadsoftware/cavedroid/game/debug/DebugInfoStringsProvider.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/SelectCreativeInventoryItemMouseInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java
core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt
core/src/ru/deadsoftware/cavedroid/game/model/block/CommonBlockParams.kt
core/src/ru/deadsoftware/cavedroid/game/model/dto/BlockDto.kt
core/src/ru/deadsoftware/cavedroid/game/model/item/InventoryItem.kt
core/src/ru/deadsoftware/cavedroid/game/model/mapper/BlockMapper.kt
core/src/ru/deadsoftware/cavedroid/game/model/world/Biome.kt
core/src/ru/deadsoftware/cavedroid/game/model/world/generator/WorldGeneratorConfig.kt
core/src/ru/deadsoftware/cavedroid/game/render/DropsRenderer.kt
core/src/ru/deadsoftware/cavedroid/game/render/windows/AbstractWindowRenderer.kt
core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java
core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt
core/src/ru/deadsoftware/cavedroid/misc/utils/RenderingUtils.kt
core/src/ru/deadsoftware/cavedroid/misc/utils/SpriteUtils.kt

index be444541df17b151ebc9e24604b62d471076caf8..6db046714ee2056a90bfddb8210dc5b6f08e6750 100644 (file)
       "tool_level": 0,
       "tool_type": "shovel"
     },
+    "grass_snowed": {
+      "hp": 54,
+      "drop": "dirt",
+      "texture": "grass_snowed",
+      "tool_level": 0,
+      "tool_type": "shovel"
+    },
     "dirt": {
       "hp": 45,
       "drop": "dirt",
@@ -48,7 +55,7 @@
       "block_required": true,
       "drop": "sapling_oak",
       "texture": "sapling_oak",
-      "hp": 1
+      "hp": 0
     },
     "bedrock": {
       "drop": "bedrock",
       "tool_level": 1,
       "tool_type": "pickaxe"
     },
+    "diamond_ore": {
+      "hp": 900,
+      "drop": "diamond",
+      "texture": "diamond_ore",
+      "tool_level": 3,
+      "tool_type": "pickaxe"
+    },
+    "diamond_block": {
+      "hp": 1500,
+      "drop": "diamond_block",
+      "texture": "diamond_block",
+      "tool_level": 3,
+      "tool_type": "pickaxe"
+    },
     "log_oak": {
       "hp": 180,
       "drop": "log_oak",
     },
     "leaves_oak": {
       "hp": 21,
-      "transparent": true,
       "drop": "leaves_oak",
       "texture": "leaves_oak",
       "tool_level": 1,
-      "tool_type": "shears"
+      "tool_type": "shears",
+      "tint": "#5AC557"
     },
     "sponge": {
       "hp": 54,
       "drop": "tallgrass",
       "texture": "tallgrass",
       "tool_level": 1,
-      "tool_type": "shears"
+      "tool_type": "shears",
+      "tint": "#5AC557",
+      "hp": 0
     },
     "deadbush": {
       "collision": false,
       "drop": "deadbush",
       "texture": "deadbush",
       "tool_level": 1,
-      "tool_type": "shears"
+      "tool_type": "shears",
+      "hp": 0
     },
     "bricks": {
       "hp": 600,
       "transparent": true,
       "block_required": true,
       "drop": "dandelion",
-      "texture": "dandelion"
+      "texture": "dandelion",
+      "hp": 0
     },
     "rose": {
       "collision": false,
       "transparent": true,
       "block_required": true,
       "drop": "rose",
-      "texture": "rose"
+      "texture": "rose",
+      "hp": 0
     },
     "mushroom_brown": {
       "collision": false,
       "transparent": true,
       "block_required": true,
       "drop": "mushroom_brown",
-      "texture": "mushroom_brown"
+      "texture": "mushroom_brown",
+      "hp": 0
     },
     "mushroom_red": {
       "collision": false,
       "transparent": true,
       "block_required": true,
       "drop": "mushroom_red",
-      "texture": "mushroom_red"
+      "texture": "mushroom_red",
+      "hp": 0
     },
     "wool_colored_white": {
       "hp": 75,
       "damage": 4
     },
     "obsidian": {
-      "hp": 1500,
+      "hp": 15000,
       "drop": "obsidian",
       "texture": "obsidian",
       "tool_level": 4,
       "type": "block",
       "texture": "coal_ore"
     },
+    "diamond_ore": {
+      "name": "Diamond Ore",
+      "type": "block",
+      "texture": "diamond_ore"
+    },
     "log_oak": {
       "name": "Wood",
       "type": "block",
       "type": "block",
       "texture": "iron_block"
     },
+    "diamond_block": {
+      "name": "Diamond Block",
+      "type": "block",
+      "texture": "diamond_block"
+    },
     "stone_slab": {
       "name": "Stone Slab",
       "type": "slab",
       "type": "bucket",
       "texture": "bucket_empty",
       "origin_x": 0.25,
-      "action_key": "use_empty_bucket"
+      "action_key": "use_empty_bucket",
+      "max_stack": 1
     },
     "bucket_water": {
       "name": "Water Bucket",
       "type": "bucket",
       "texture": "bucket_water",
       "origin_x": 0.25,
-      "action_key": "use_water_bucket"
+      "action_key": "use_water_bucket",
+      "max_stack": 1
     },
     "bucket_lava": {
       "name": "Lava Bucket",
       "type": "bucket",
       "texture": "bucket_lava",
       "origin_x": 0.25,
-      "action_key": "use_lava_bucket"
+      "action_key": "use_lava_bucket",
+      "max_stack": 1
     }
   }
 }
diff --git a/android/assets/textures/blocks/grass_snowed.png b/android/assets/textures/blocks/grass_snowed.png
new file mode 100644 (file)
index 0000000..730996d
Binary files /dev/null and b/android/assets/textures/blocks/grass_snowed.png differ
diff --git a/android/assets/textures/blocks/leaves_birch.png b/android/assets/textures/blocks/leaves_birch.png
deleted file mode 100644 (file)
index 3fa5139..0000000
Binary files a/android/assets/textures/blocks/leaves_birch.png and /dev/null differ
index c2a54ee5e827094223e85d93d5bb957793f79a8e..d9027521b78eaa34aac1ff2d3e3c46f98617c7c2 100644 (file)
Binary files a/android/assets/textures/blocks/leaves_oak.png and b/android/assets/textures/blocks/leaves_oak.png differ
diff --git a/android/assets/textures/blocks/leaves_spruce.png b/android/assets/textures/blocks/leaves_spruce.png
deleted file mode 100644 (file)
index cdcd782..0000000
Binary files a/android/assets/textures/blocks/leaves_spruce.png and /dev/null differ
index be841273c873ed9878133a341d692a39e8144db7..5dcfe0e72a80c987a6ac3227190855570d89e804 100644 (file)
@@ -41,4 +41,12 @@ class UpdateBlockActionsModule {
     fun bindUpdateGrassAction(action: UpdateGrassAction): IUpdateBlockAction {
         return action;
     }
+
+    @Binds
+    @IntoMap
+    @StringKey(UpdateSnowedGrassAction.BLOCK_KEY)
+    @GameScope
+    fun bindUpdateSnowedGrassAction(action: UpdateSnowedGrassAction): IUpdateBlockAction {
+        return action;
+    }
 }
\ No newline at end of file
index aeb64f07459a966917b08ea3ba7a24ff92f7149e..0206d5f82fe9c0fb61511d45e662a7dd1e8456ec 100644 (file)
@@ -26,4 +26,12 @@ class UseItemActionsModule {
         return action
     }
 
+    @Binds
+    @IntoMap
+    @StringKey(UseEmptyBucketAction.ACTION_KEY)
+    @GameScope
+    fun bindUseEmptyBucketAction(action: UseEmptyBucketAction): IUseItemAction {
+        return action
+    }
+
 }
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSnowedGrassAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSnowedGrassAction.kt
new file mode 100644 (file)
index 0000000..8b7f0e3
--- /dev/null
@@ -0,0 +1,24 @@
+package ru.deadsoftware.cavedroid.game.actions.updateblock
+
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.world.GameWorld
+import javax.inject.Inject
+
+@GameScope
+class UpdateSnowedGrassAction @Inject constructor(
+    private val gameWorld: GameWorld,
+    private val mGameItemsHolder: GameItemsHolder,
+) : IUpdateBlockAction {
+
+    override fun update(x: Int, y: Int) {
+        val blockOnTop = gameWorld.getForeMap(x, y - 1)
+        if (blockOnTop.collision || blockOnTop.isFluid()) {
+            gameWorld.setForeMap(x, y, mGameItemsHolder.getBlock("dirt"))
+        }
+    }
+
+    companion object {
+        const val BLOCK_KEY = "grass_snowed"
+    }
+}
\ No newline at end of file
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseEmptyBucketAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseEmptyBucketAction.kt
new file mode 100644 (file)
index 0000000..9f7c9f4
--- /dev/null
@@ -0,0 +1,37 @@
+package ru.deadsoftware.cavedroid.game.actions.useitem
+
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.mobs.MobsController
+import ru.deadsoftware.cavedroid.game.model.block.Block
+import ru.deadsoftware.cavedroid.game.model.item.Item
+import ru.deadsoftware.cavedroid.game.world.GameWorld
+import javax.inject.Inject
+
+@GameScope
+class UseEmptyBucketAction @Inject constructor(
+    private val gameWorld: GameWorld,
+    private val mobsController: MobsController,
+    private val gameItemsHolder: GameItemsHolder,
+) : IUseItemAction {
+
+    override fun perform(item: Item.Usable, x: Int, y: Int) {
+        val foregroundBlock = gameWorld.getForeMap(x, y)
+        if (!foregroundBlock.isFluid()) {
+            return
+        }
+        gameWorld.resetForeMap(x, y)
+
+        val filled = when (foregroundBlock) {
+            is Block.Lava -> gameItemsHolder.getItem("bucket_lava")
+            is Block.Water -> gameItemsHolder.getItem("bucket_water")
+            else -> throw IllegalStateException("unknown fluid")
+        }
+
+        mobsController.player.setCurrentInventorySlotItem(filled)
+    }
+
+    companion object {
+        const val ACTION_KEY = "use_empty_bucket"
+    }
+}
index 7f834ae1e8c411aa551902ecc03026809d9f377f..965961711ee2ec08b44bf07961d8124322be7ea5 100644 (file)
@@ -16,7 +16,10 @@ class UseLavaBucketAction @Inject constructor(
 
     override fun perform(item: Item.Usable, x: Int, y: Int) {
         gameWorld.placeToForeground(x, y, gameItemsHolder.getBlock("lava"))
-        mobsController.player.setCurrentInventorySlotItem(gameItemsHolder.getItem("bucket_empty"))
+
+        if (mobsController.player.gameMode != 1) {
+            mobsController.player.setCurrentInventorySlotItem(gameItemsHolder.getItem("bucket_empty"))
+        }
     }
 
     companion object {
index 596d5872950fcde8343f45e27e61c4a862a4537a..15e08fc77bd78962ec8fd6ccfd389a917cd66699 100644 (file)
@@ -16,7 +16,9 @@ class UseWaterBucketAction @Inject constructor(
 
     override fun perform(item: Item.Usable, x: Int, y: Int) {
         gameWorld.placeToForeground(x, y, gameItemsHolder.getBlock("water"))
-        mobsController.player.setCurrentInventorySlotItem(gameItemsHolder.getItem("bucket_empty"))
+        if (mobsController.player.gameMode != 1) {
+            mobsController.player.setCurrentInventorySlotItem(gameItemsHolder.getItem("bucket_empty"))
+        }
     }
 
     companion object {
index 3a0ef06610c8434ae377b4b5a07fd98ad0a24ebc..c8147d1987ce8cb7abe2bb05e1990b0d315c2ce6 100644 (file)
@@ -20,7 +20,7 @@ class DebugInfoStringsProvider @Inject constructor(
         return listOf(
             "FPS: ${Gdx.graphics.framesPerSecond}",
             "X: ${player.mapX}",
-            "Y: ${player.upperMapY}",
+            "Y: ${gameWorld.height - player.upperMapY}",
             "CurX: ${player.cursorX}",
             "CurY: ${player.cursorY}",
             "Velocity: ${player.velocity}",
index 5e6402731670b079ba6c294ee271c036ab28022a..ddd71c4418cbae9603214f0c8985b84083564f13 100644 (file)
@@ -50,7 +50,7 @@ class SelectCreativeInventoryItemMouseInputHandler @Inject constructor(
             destination = mobsController.player.inventory,
             destinationOffset = 1,
             startIndex = 0,
-            endIndex = mobsController.player.inventory.size - 2
+            endIndex = mobsController.player.inventory.size - 1
         )
 
         val item = gameItemsHolder.getItemFromCreativeInventory(itemIndex)
index 83f3257d86b027c21bb03e4fcb29d6ed8e18d81f..b369f1ccc7f37613d9b90ec0d863a5530a7a7563 100644 (file)
@@ -36,6 +36,9 @@ public class Player extends Mob {
     public int cursorX = 0;
     public int cursorY = 0;
 
+    @CheckForNull
+    private Vector2 spawnPoint = null;
+
     public ControlMode controlMode = ControlMode.WALK;
 
     public enum ControlMode {
@@ -107,18 +110,30 @@ public class Player extends Mob {
     }
 
     private Vector2 getSpawnPoint(GameWorld gameWorld, GameItemsHolder itemsHolder) {
-        int y;
-        for (y = 0; y < gameWorld.getHeight(); y++) {
-            if (y == gameWorld.getHeight() - 1) {
-                y = 60;
-                gameWorld.setForeMap(0, y, itemsHolder.getBlock("grass"));
+        if (spawnPoint != null) {
+            return spawnPoint;
+        }
+
+        int y, x = gameWorld.getWidth() / 2;
+        for (y = 0; y <= gameWorld.getWorldConfig().getSeaLevel(); y++) {
+            if (y == gameWorld.getWorldConfig().getSeaLevel()) {
+                for (x = 0; x < gameWorld.getWidth(); x++) {
+                    if (gameWorld.getForeMap(x, y).getParams().getHasCollision()) {
+                        break;
+                    }
+                    if (x == gameWorld.getWidth() - 1) {
+                        gameWorld.setForeMap(x, y, itemsHolder.getBlock("grass"));
+                        break;
+                    }
+                }
                 break;
             }
-            if (gameWorld.hasForeAt(0, y) && gameWorld.getForeMap(0, y).hasCollision()) {
+            if (gameWorld.hasForeAt(x, y) && gameWorld.getForeMap(x, y).hasCollision()) {
                 break;
             }
         }
-        return new Vector2(8 - getWidth() / 2, (float) y * 16 - getHeight());
+        spawnPoint = new Vector2(x * 16 + 8 - getWidth() / 2, (float) y * 16 - getHeight());
+        return spawnPoint;
     }
 
     public void setDir(Direction dir) {
@@ -247,6 +262,9 @@ public class Player extends Mob {
         final Sprite sprite = item.getSprite();
         final boolean smallSprite = !item.isTool() || item.isShears();
 
+        final float originalWidth = sprite.getWidth();
+        final float originalHeight = sprite.getHeight();
+
         if (smallSprite) {
             sprite.setSize(Drop.DROP_SIZE, Drop.DROP_SIZE);
         }
@@ -275,12 +293,15 @@ public class Player extends Mob {
             SpriteUtilsKt.applyOrigin(sprite, spriteOrigin);
         }
 
-        SpriteUtilsKt.drawSprite(spriteBatch, sprite, itemX, itemY, -handMultiplier * rotate);
+        sprite.setRotation(-handMultiplier * rotate);
+        sprite.setPosition(itemX, itemY);
+        sprite.draw(spriteBatch);
 
         // dont forget to reset
         sprite.setFlip(false, sprite.isFlipY());
         sprite.setRotation(0);
         sprite.setOriginCenter();
+        sprite.setSize(originalWidth, originalHeight);
         if (item.isTool()) {
             sprite.rotate90(looksRight());
         }
index 9669a5378c5f84dbafd7be4a58bc801522f2a3d7..76c6ac580c0df1a6604c447e3f1c0e930496f456 100644 (file)
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.math.Rectangle
 import com.badlogic.gdx.utils.TimeUtils
 import ru.deadsoftware.cavedroid.game.model.item.Item
+import ru.deadsoftware.cavedroid.misc.utils.colorFromHexString
 import kotlin.contracts.ExperimentalContracts
 import kotlin.contracts.contract
 
@@ -56,7 +57,10 @@ sealed class Block {
                 val width = 16 - params.spriteMargins.left - params.spriteMargins.right
                 val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
                 Sprite(params.texture, params.spriteMargins.left, 16 * y + params.spriteMargins.top, width, height)
-                    .apply { flip(false, true) }
+                    .apply {
+                        flip(false, true)
+                        params.tint?.let { tint -> color = colorFromHexString(tint) }
+                    }
             }
         }
     }
@@ -66,7 +70,10 @@ sealed class Block {
             val width = 16 - params.spriteMargins.left - params.spriteMargins.right
             val height = 16 - params.spriteMargins.top - params.spriteMargins.bottom
             Sprite(tex, params.spriteMargins.left, params.spriteMargins.top, width, height)
-                .apply { flip(false, true) }
+                .apply {
+                    flip(false, true)
+                    params.tint?.let { tint -> color = colorFromHexString(tint) }
+                }
         }
     }
 
index 202b191bf21d9859fb56d44642d8d5dc043e4655..e98f1be893ae3071f7be4c54226bd767e21f8c0c 100644 (file)
@@ -19,4 +19,5 @@ data class CommonBlockParams(
     val toolLevel: Int,
     val toolType: Class<out Item.Tool>?,
     val damage: Int,
+    val tint: String?,
 )
index b8c63268825acc07430df7e9bfaee7aa5c7b10fe..c6065b70c008586345df38c1ec323b759653a224 100644 (file)
@@ -31,4 +31,5 @@ data class BlockDto(
     @SerialName("tool_level") val toolLevel: Int = 0,
     @SerialName("tool_type") val toolType: String? = null,
     @SerialName("damage") val damage: Int = 0,
+    @SerialName("tint") val tint: String? = null,
 )
index 89186595d360ee3f2642306baefeb893ab94e223..6cb2a9d85bf5232fb8e7b37750c336f7e0aa0f38 100644 (file)
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
 import ru.deadsoftware.cavedroid.game.GameItemsHolder
 import ru.deadsoftware.cavedroid.misc.Assets
+import ru.deadsoftware.cavedroid.misc.utils.drawSprite
 import ru.deadsoftware.cavedroid.misc.utils.drawString
 import ru.deadsoftware.cavedroid.misc.utils.px
 import java.io.Serializable
@@ -54,7 +55,7 @@ class InventoryItem @JvmOverloads constructor(
         }
 
         val sprite = item.sprite
-        spriteBatch.draw(sprite, x, y)
+        spriteBatch.drawSprite(sprite, x, y)
 
         if (amount < 2) {
             return
index e97659a953a83e8b69dbb0bc90e0df9c188f504f..85d8cb722d457511ba96d4f46c10e81e994a0e38 100644 (file)
@@ -55,6 +55,7 @@ class BlockMapper @Inject constructor(
             toolLevel = dto.toolLevel,
             toolType = mapToolType(dto),
             damage = dto.damage,
+            tint = dto.tint,
         )
     }
 
index e2d3d7d68634f51478efeb837dda4c35941c03f2..ee214bd783a27a8c5c4f84551991aebdea1f6fb1 100644 (file)
@@ -2,5 +2,6 @@ package ru.deadsoftware.cavedroid.game.model.world
 
 enum class Biome {
     PLAINS,
-    DESERT
+    DESERT,
+    WINTER
 }
\ No newline at end of file
index 19a7c2d56719d485a7b2ff7c774658be2a9625ca..64da3fe5db30dce581edcd0ebe46fb2c8d690e7a 100644 (file)
@@ -15,20 +15,17 @@ data class WorldGeneratorConfig(
 ) {
 
     companion object {
-        private const val DEFAULT_WIDTH = 1024
-        private const val DEFAULT_HEIGHT = 256
-        private const val DEFAULT_MIN_BIOME_SIZE = 64
 
         fun getDefault(): WorldGeneratorConfig {
             return WorldGeneratorConfig(
-                width = DEFAULT_WIDTH,
-                height = DEFAULT_HEIGHT,
+                width = 1024,
+                height = 256,
                 seed = TimeUtils.millis(),
-                minSurfaceHeight = DEFAULT_HEIGHT / 4,
-                maxSurfaceHeight = DEFAULT_HEIGHT * 3 / 4,
+                maxSurfaceHeight = 208,
+                minSurfaceHeight = 128,
                 biomes = Biome.entries.toList(),
-                minBiomeSize = DEFAULT_MIN_BIOME_SIZE,
-                seaLevel = DEFAULT_HEIGHT / 2,
+                minBiomeSize = 64,
+                seaLevel = 192,
             )
         }
 
index efc7aa1ab1eef078d879754f301d562937863711..a17bd613002ddb1922151bb6d3df31b92f92c969 100644 (file)
@@ -22,11 +22,12 @@ class DropsRenderer @Inject constructor(
     override fun draw(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, viewport: Rectangle, delta: Float) {
         dropController.forEach { drop ->
             drop.cycledInsideWorld(viewport, gameWorld.width.px)?.let { dropRect ->
-                drop.item.sprite.setSize(dropRect.width, dropRect.height)
                 spriteBatch.drawSprite(
                     sprite = drop.item.sprite,
                     x = dropRect.x - viewport.x,
                     y = dropRect.y - viewport.y,
+                    width = dropRect.width,
+                    height = dropRect.height,
                 )
             }
         }
index 52935fe40117bbabe29853f37043da92e61ba75c..57cf81bb1025b40eca3fb501e98d4eb9031b9897 100644 (file)
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
 import ru.deadsoftware.cavedroid.game.model.item.Item
+import ru.deadsoftware.cavedroid.misc.utils.drawSprite
 
 abstract class AbstractWindowRenderer {
 
@@ -39,7 +40,7 @@ abstract class AbstractWindowRenderer {
             val itemY = gridY + (index / itemsInRow) * cellHeight
 
             inventoryItem?.draw(spriteBatch, shapeRenderer, itemX, itemY)
-                ?: item?.let { spriteBatch.draw(it.sprite, itemX, itemY) }
+                ?: item?.let { spriteBatch.drawSprite(it.sprite, itemX, itemY) }
         }
     }
 
index f8a5cc970e1749d34eb8abeb7f0f7acacb8df382..f2fd27dd486fa4a3425bd5edce078769350deb19 100644 (file)
@@ -26,6 +26,8 @@ public class GameWorld {
     private final Block[][] mForeMap;
     private final Block[][] mBackMap;
 
+    private final WorldGeneratorConfig mWorldConfig =  WorldGeneratorConfig.Companion.getDefault();
+
     @Inject
     public GameWorld(DropController dropController,
                      MobsController mobsController,
@@ -39,10 +41,9 @@ public class GameWorld {
         boolean isNewGame = foreMap == null || backMap == null;
 
         if (isNewGame) {
-            final WorldGeneratorConfig config = WorldGeneratorConfig.Companion.getDefault();
-            mWidth = config.getWidth();
-            mHeight = config.getHeight();
-            Pair<Block[][], Block[][]> maps = new GameWorldGenerator(config, mGameItemsHolder).generate();
+            mWidth = mWorldConfig.getWidth();
+            mHeight = mWorldConfig.getHeight();
+            Pair<Block[][], Block[][]> maps = new GameWorldGenerator(mWorldConfig, mGameItemsHolder).generate();
             mForeMap = maps.getFirst();
             mBackMap = maps.getSecond();
             mMobsController.getPlayer().respawn(this, mGameItemsHolder);
@@ -200,7 +201,9 @@ public class GameWorld {
         placeToForeground(x, y, mGameItemsHolder.getFallbackBlock());
     }
 
-
+    public WorldGeneratorConfig getWorldConfig() {
+        return mWorldConfig;
+    }
 
     public void destroyBackMap(int x, int y) {
         Block block = getBackMap(x, y);
index b984c4dbacfd0e25002201701f8d332c0df7fcac..e00a0ea4dd2cd3397b632650b69b635cdc1ec24f 100644 (file)
@@ -1,5 +1,6 @@
 package ru.deadsoftware.cavedroid.game.world
 
+import com.google.common.primitives.Ints.min
 import ru.deadsoftware.cavedroid.game.GameItemsHolder
 import ru.deadsoftware.cavedroid.game.model.block.Block
 import ru.deadsoftware.cavedroid.game.model.world.Biome
@@ -21,11 +22,14 @@ class GameWorldGenerator(
     private val heights by lazy { generateHeights() }
     private val biomesMap by lazy { generateBiomes() }
 
+    private val plainsPlants = listOf("dandelion", "rose", "tallgrass")
+    private val mushrooms = listOf("mushroom_brown", "mushroom_red",)
+
     private fun generateHeights(): IntArray {
         val surfaceHeightRange = config.minSurfaceHeight .. config.maxSurfaceHeight
         val result = IntArray(config.width)
 
-        result[0] = (config.minSurfaceHeight + config.maxSurfaceHeight) / 2
+        result[0] = surfaceHeightRange.random(random)
 
         for (x in 1 ..< config.width) {
             val previous = result[x - 1]
@@ -59,6 +63,35 @@ class GameWorldGenerator(
         return xSequence.associateWith { config.biomes.random(random) }
     }
 
+    private fun winterBiome(x: Int) {
+        assert(x in 0 ..< config.width) { "x not in range of world width" }
+
+        val surfaceHeight = heights[x]
+
+        val grass = gameItemsHolder.getBlock("grass_snowed")
+        val bedrock = gameItemsHolder.getBlock("bedrock")
+        val dirt = gameItemsHolder.getBlock("dirt")
+        val stone = gameItemsHolder.getBlock("stone")
+
+        foreMap[x][surfaceHeight] = grass
+        foreMap[x][config.height - 1] = bedrock
+        backMap[x][surfaceHeight] = grass
+        backMap[x][config.height - 1] = bedrock
+
+        for (y in min(surfaceHeight + 1, config.seaLevel) ..< config.height - 1) {
+            if (y <= surfaceHeight) {
+                backMap[x][y] = dirt
+                continue
+            }
+
+            foreMap[x][y] = when {
+                y < surfaceHeight + random.nextInt(5, 8) -> dirt
+                else -> stone
+            }
+            backMap[x][y] = foreMap[x][y]
+        }
+    }
+
     private fun plainsBiome(x: Int) {
         assert(x in 0 ..< config.width) { "x not in range of world width" }
 
@@ -74,13 +107,27 @@ class GameWorldGenerator(
         backMap[x][surfaceHeight] = grass
         backMap[x][config.height - 1] = bedrock
 
-        for (y in surfaceHeight + 1 ..< config.height - 1) {
+        for (y in min(surfaceHeight + 1, config.seaLevel) ..< config.height - 1) {
+            if (y <= surfaceHeight) {
+                backMap[x][y] = dirt
+                continue
+            }
+
             foreMap[x][y] = when {
                 y < surfaceHeight + random.nextInt(5, 8) -> dirt
                 else -> stone
             }
             backMap[x][y] = foreMap[x][y]
         }
+
+        val plant = random.nextInt(100)
+        if (surfaceHeight < config.seaLevel) {
+            if (plant < 10) {
+                generateOak(x)
+            } else if (plant < 40) {
+                generateTallGrass(x)
+            }
+        }
     }
 
     private fun desertBiome(x: Int) {
@@ -99,7 +146,12 @@ class GameWorldGenerator(
         backMap[x][surfaceHeight] = sand
         backMap[x][config.height - 1] = bedrock
 
-        for (y in surfaceHeight + 1 ..< config.height - 1) {
+        for (y in min(surfaceHeight + 1, config.seaLevel) ..< config.height - 1) {
+            if (y <= surfaceHeight) {
+                backMap[x][y] = sand
+                continue
+            }
+
             foreMap[x][y] = when {
                 y < surfaceHeight + random.nextInt(5, 8) -> sand
                 y < surfaceHeight + random.nextInt(0, 2) -> sandstone
@@ -108,8 +160,13 @@ class GameWorldGenerator(
             backMap[x][y] = foreMap[x][y]
         }
 
-        if (surfaceHeight < config.seaLevel && random.nextInt(100) < 5) {
-            generateCactus(x)
+        val plant = random.nextInt(100)
+        if (surfaceHeight < config.seaLevel) {
+            if (plant < 5) {
+                generateCactus(x)
+            } else if (plant < 10) {
+                generateDeadBush(x)
+            }
         }
     }
 
@@ -137,6 +194,77 @@ class GameWorldGenerator(
         }
     }
 
+    private fun generateOak(x: Int) {
+        val log = gameItemsHolder.getBlock("log_oak")
+        val leaves = gameItemsHolder.getBlock("leaves_oak")
+        val h = heights[x] - 1
+        val treeH = random.nextInt(5, 7)
+        val height = max(0, h - treeH)
+
+        val top = height - 1
+        if (top >= 0) {
+            foreMap[x][top] = leaves
+            backMap[x][top] = leaves
+        }
+
+        for (x1 in max(0, x - 1) .. min(config.width - 1, x + 1)) {
+            for (y in height .. height + treeH - 4) {
+                foreMap[x1][y] = leaves
+                backMap[x1][y] = leaves
+            }
+            if (random.nextInt(15) < 3) {
+                foreMap[x1][heights[x1] - 1] = gameItemsHolder.getBlock(mushrooms.random(random))
+            }
+        }
+
+        for (y in h downTo height) {
+            backMap[x][y] = log
+        }
+    }
+
+    private fun generateTallGrass(x: Int) {
+        val tallGrass = gameItemsHolder.getBlock(plainsPlants.random(random))
+        val h = heights[x] - 1
+        if (h > 0) {
+            foreMap[x][h] = tallGrass
+        }
+    }
+
+    private fun generateDeadBush(x: Int) {
+        val bush = gameItemsHolder.getBlock("deadbush")
+        val h = heights[x] - 1
+        if (h > 0) {
+            foreMap[x][h] = bush
+        }
+    }
+
+    private fun generateOres(x : Int) {
+        val stone = gameItemsHolder.getBlock("stone")
+        val coal = gameItemsHolder.getBlock("coal_ore")
+        val iron = gameItemsHolder.getBlock("iron_ore")
+        val gold = gameItemsHolder.getBlock("gold_ore")
+        val diamond = gameItemsHolder.getBlock("diamond_ore")
+        val lapis = gameItemsHolder.getBlock("lapis_ore")
+
+        for (y in heights[x] ..< config.height) {
+            val res = random.nextInt(10000)
+
+            val h = config.height - y
+            val block = when {
+                res in 0..<25 && h < 16 -> diamond
+                res in 25 ..< 50 && h < 32 -> gold
+                res in 50 ..< 250 && h < 64 -> iron
+                res in 250 ..< 450 && h < 128 -> coal
+                res in 450 ..< (450 + (25 - (abs(h - 16) * (25 / 16)))) -> lapis
+                else -> null
+            }
+
+            if (block != null && foreMap[x][y] == stone) {
+                foreMap[x][y] = block
+            }
+        }
+    }
+
     /**
      * Generate world
      */
@@ -149,7 +277,10 @@ class GameWorldGenerator(
             when (biome) {
                 Biome.PLAINS -> plainsBiome(x)
                 Biome.DESERT -> desertBiome(x)
+                Biome.WINTER -> winterBiome(x)
             }
+
+            generateOres(x)
         }
 
         fillWater()
index d197229578bfb8a92e989eb228b05a2bf05f0c69..24813acc853fe54ef5421c046a55c48cfede0b39 100644 (file)
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.GlyphLayout
 import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.math.Rectangle
 import ru.deadsoftware.cavedroid.misc.Assets
+import java.awt.Color as JavaColor
 
 private fun Rectangle.shifted(shift: Float) = Rectangle(x + shift, y, width, height)
 
@@ -50,3 +51,8 @@ fun SpriteBatch.drawString(str: String, x: Float, y: Float, color: Color = Color
     Assets.minecraftFont.color = color
     return Assets.minecraftFont.draw(this, str, x, y)
 }
+
+fun colorFromHexString(hex: String): Color {
+    val rgba = (JavaColor.decode(hex).rgb shl 8) or (0xFF)
+    return Color(rgba)
+}
index fd186e5a400e558a338895c01ebc45f20a34e97c..7b75e3893be9f6a49b7e588aa67eb565738e62ad 100644 (file)
@@ -11,11 +11,17 @@ fun SpriteBatch.drawSprite(
     sprite: Sprite,
     x: Float,
     y: Float,
-    rotation: Float = 0f
+    rotation: Float = 0f,
+    width: Float = sprite.regionWidth.toFloat(),
+    height: Float = sprite.regionHeight.toFloat(),
 ) {
-    sprite.rotation = rotation
     sprite.setPosition(x, y)
+    sprite.setSize(width, height)
+    sprite.rotation = rotation
     sprite.draw(this)
+
+    sprite.setSize(sprite.regionWidth.toFloat(), sprite.regionHeight.toFloat())
+    sprite.rotation = 0f
 }
 
 fun Sprite.applyOrigin(origin: SpriteOrigin) {