From 060595c8f929b1eba81653c5154f948fb12190ff Mon Sep 17 00:00:00 2001 From: fredboy Date: Tue, 23 Apr 2024 00:42:10 +0700 Subject: [PATCH] Add survival inventory --- android/assets/inventory.png | Bin 0 -> 5731 bytes android/assets/json/texture_regions.json | 6 + .../cavedroid/game/GameInput.java | 22 ++-- .../cavedroid/game/mobs/Player.java | 8 +- .../cavedroid/game/render/HudRenderer.kt | 3 +- .../cavedroid/game/render/WindowsRenderer.kt | 3 + .../render/windows/AbstractWindowRenderer.kt | 50 ++++++++ .../render/windows/CreativeWindowRenderer.kt | 78 ++++-------- .../render/windows/SurvivalWindowRenderer.kt | 119 ++++++++++++++++++ 9 files changed, 224 insertions(+), 65 deletions(-) create mode 100644 android/assets/inventory.png create mode 100644 core/src/ru/deadsoftware/cavedroid/game/render/windows/AbstractWindowRenderer.kt create mode 100644 core/src/ru/deadsoftware/cavedroid/game/render/windows/SurvivalWindowRenderer.kt diff --git a/android/assets/inventory.png b/android/assets/inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..8bc6cf79da0b8de3269d0966e7da39f8827580e1 GIT binary patch literal 5731 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

4t{Fe~k6{^+cDzaW6)C9H7BnkS0B;y+S z0PDW$Bea6U>jjyxo&gqi5UR!MoCdTbnfPqK)lEL~|G4kQAHvKIBI;5&9|a{SvrTW* z$gBLj>7j7?9_?Zl=gX5U#6lr#3XessCs*@sGLFg^W(Ba6Cu2BL(cr%wY>03S*Hg#|BMp z-GZeWGa)9>*2l093+}e$ufO#z;$6kofwgA~3lZA=?lnQ$+>i7XVG*LQ2=d4-l_PJi z)b^4bw364%e@Do4ztpE`qzv+xw@KSeyX4qFKU&HQI~6U%O}_X{oW@H*GiDLx-0P-z zF1`<#Yw2hQTFel1bSJQ2mrdjm8^k(iQ0?yeH(L$XOuZX(i(uThaL`}BM95;u#ayvB zeNobrb0kg8XJMfGuPV4`bdmtZW<7aUusGkqS qbU)0tM!@@KH`mB*B>&*RU7EK% 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 literal 0 HcmV?d00001 diff --git a/android/assets/json/texture_regions.json b/android/assets/json/texture_regions.json index 01507d4..2b73d8f 100644 --- a/android/assets/json/texture_regions.json +++ b/android/assets/json/texture_regions.json @@ -49,6 +49,12 @@ "h": 15 } }, + "inventory": { + "survival": { + "w": 176, + "h": 166 + } + }, "buttons": { "button_0": { "w": 200, diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameInput.java b/core/src/ru/deadsoftware/cavedroid/game/GameInput.java index a45e704..85fd63b 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameInput.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameInput.java @@ -282,13 +282,24 @@ public class GameInput { mMainConfig.getWidth() / 2 + (float) hotbar.getRegionWidth() / 2).contains(x); } + private void openInventory() { + switch (mPlayer.gameMode) { + case 0: + mMainConfig.setGameUiWindow(GameUiWindow.SURVIVAL_INVENTORY); + break; + case 1: + mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY); + break; + } + } + private void holdMB() { if (mTouchDownBtn == Input.Buttons.RIGHT) { useItem(mPlayer.cursorX, mPlayer.cursorY, mPlayer.inventory[mPlayer.slot].getItem(), true); mTouchedDown = false; } else { if (insideHotbar(mTouchDownX, mTouchDownY)) { - mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY); + openInventory(); mTouchedDown = false; } } @@ -315,14 +326,7 @@ public class GameInput { case Input.Keys.E: if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) { - switch (mPlayer.gameMode) { - case 0: - //TODO survival inv - break; - case 1: - mMainConfig.setGameUiWindow(GameUiWindow.CREATIVE_INVENTORY); - break; - } + openInventory(); } else { mMainConfig.setGameUiWindow(GameUiWindow.NONE); } diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java b/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java index b1896e4..a93141a 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java @@ -38,8 +38,8 @@ public class Player extends Mob { public Player(GameItemsHolder gameItemsHolder) { super(0, 0, 4, 30, randomDir(), Type.MOB, MAX_HEALTH); - inventory = new InventoryItem[9]; - for (int i = 0; i < 9; i++) { + inventory = new InventoryItem[36]; + for (int i = 0; i < inventory.length; i++) { inventory[i] = gameItemsHolder.getFallbackItem().toInventoryItem(); } swim = false; @@ -136,6 +136,8 @@ public class Player extends Mob { @Override public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) { + updateAnimation(delta); + if (gameMode == 1) { return; } @@ -285,8 +287,6 @@ public class Player extends Mob { @Override public void draw(SpriteBatch spriteBatch, float x, float y, float delta) { - updateAnimation(delta); - final Sprite backHand = Assets.playerSprite[1][2]; final Sprite backLeg = Assets.playerSprite[1][3]; final Sprite frontLeg = Assets.playerSprite[0][3]; diff --git a/core/src/ru/deadsoftware/cavedroid/game/render/HudRenderer.kt b/core/src/ru/deadsoftware/cavedroid/game/render/HudRenderer.kt index 7bbb876..b631902 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/render/HudRenderer.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/render/HudRenderer.kt @@ -60,7 +60,7 @@ class HudRenderer @Inject constructor( } private fun drawHotbarItems(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, hotbarX: Float) { - mobsController.player.inventory + mobsController.player.inventory.asSequence().take(HotbarConfig.hotbarCells) .forEachIndexed { index, item -> if (item.item.isNone()) { return@forEachIndexed @@ -114,6 +114,7 @@ class HudRenderer @Inject constructor( const val verticalMargin = 3f const val itemSeparatorWidth = 4f const val itemSlotSpace = 16f + const val hotbarCells = 9 } private data object HotbarSelectorConfig { diff --git a/core/src/ru/deadsoftware/cavedroid/game/render/WindowsRenderer.kt b/core/src/ru/deadsoftware/cavedroid/game/render/WindowsRenderer.kt index 12fcd39..10c211a 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/render/WindowsRenderer.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/render/WindowsRenderer.kt @@ -8,12 +8,14 @@ import ru.deadsoftware.cavedroid.MainConfig import ru.deadsoftware.cavedroid.game.GameScope import ru.deadsoftware.cavedroid.game.GameUiWindow import ru.deadsoftware.cavedroid.game.render.windows.CreativeWindowRenderer +import ru.deadsoftware.cavedroid.game.render.windows.SurvivalWindowRenderer import javax.inject.Inject @GameScope class WindowsRenderer @Inject constructor( private val mainConfig: MainConfig, private val creativeWindowRenderer: CreativeWindowRenderer, + private val survivalWindowRenderer: SurvivalWindowRenderer, ) : IGameRenderer { override val renderLayer get() = RENDER_LAYER @@ -21,6 +23,7 @@ class WindowsRenderer @Inject constructor( override fun draw(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, viewport: Rectangle, delta: Float) { when (mainConfig.gameUiWindow) { GameUiWindow.CREATIVE_INVENTORY -> creativeWindowRenderer.draw(spriteBatch, shapeRenderer, viewport, delta) + GameUiWindow.SURVIVAL_INVENTORY -> survivalWindowRenderer.draw(spriteBatch, shapeRenderer, viewport, delta) GameUiWindow.NONE -> return else -> Gdx.app.error(TAG, "Cannot draw window: ${mainConfig.gameUiWindow.name}") } diff --git a/core/src/ru/deadsoftware/cavedroid/game/render/windows/AbstractWindowRenderer.kt b/core/src/ru/deadsoftware/cavedroid/game/render/windows/AbstractWindowRenderer.kt new file mode 100644 index 0000000..52935fe --- /dev/null +++ b/core/src/ru/deadsoftware/cavedroid/game/render/windows/AbstractWindowRenderer.kt @@ -0,0 +1,50 @@ +package ru.deadsoftware.cavedroid.game.render.windows + +import com.badlogic.gdx.Gdx +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 + +abstract class AbstractWindowRenderer { + + protected inline fun drawItemsGrid( + spriteBatch: SpriteBatch, + shapeRenderer: ShapeRenderer, + gridX: Float, + gridY: Float, + items: Iterable, + itemsInRow: Int, + cellWidth: Float, + cellHeight: Float + ) { + if (T::class != Item::class && T::class != InventoryItem::class) { + Gdx.app.log(_TAG, "Trying to draw items grid of not items") + return + } + + items.forEachIndexed { index, element -> + val item = element as? Item + val inventoryItem = element as? InventoryItem + + if (item == null && inventoryItem == null) { + throw IllegalStateException("This should be unreachable") + } + + if (item?.isNone() == true || inventoryItem?.item?.isNone() == true) { + return@forEachIndexed + } + + val itemX = gridX + (index % itemsInRow) * cellWidth + val itemY = gridY + (index / itemsInRow) * cellHeight + + inventoryItem?.draw(spriteBatch, shapeRenderer, itemX, itemY) + ?: item?.let { spriteBatch.draw(it.sprite, itemX, itemY) } + } + } + + companion object { + protected const val _TAG = "AbstractWindowRenderer" + } + +} \ No newline at end of file diff --git a/core/src/ru/deadsoftware/cavedroid/game/render/windows/CreativeWindowRenderer.kt b/core/src/ru/deadsoftware/cavedroid/game/render/windows/CreativeWindowRenderer.kt index d9423ff..ef62996 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/render/windows/CreativeWindowRenderer.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/render/windows/CreativeWindowRenderer.kt @@ -13,6 +13,7 @@ import ru.deadsoftware.cavedroid.game.render.IGameRenderer import ru.deadsoftware.cavedroid.game.render.WindowsRenderer import ru.deadsoftware.cavedroid.misc.Assets import javax.inject.Inject +import kotlin.math.min @GameScope class CreativeWindowRenderer @Inject constructor( @@ -20,56 +21,15 @@ class CreativeWindowRenderer @Inject constructor( private val gameInput: GameInput, private val gameItemsHolder: GameItemsHolder, private val mobsController: MobsController, -) : IGameRenderer { +) : AbstractWindowRenderer(), IGameRenderer { override val renderLayer get() = WindowsRenderer.RENDER_LAYER private val creativeWindowTexture get() = requireNotNull(Assets.textureRegions[CREATIVE_WINDOW_KEY]) private val scrollIndicatorTexture get() = requireNotNull(Assets.textureRegions[SCROLL_INDICATOR_KEY]) - private fun drawItemsGrid(spriteBatch: SpriteBatch, gridX: Float, gridY: Float) { - val allItems = gameItemsHolder.getAllItems() - val startIndex = gameInput.creativeScroll * CreativeWindowConfig.itemsInRow - val endIndex = startIndex + CreativeWindowConfig.itemsOnPage - - for (i in startIndex.. - if (item.item.isNone()) { - return@forEachIndexed - } - - val itemX = inventoryX + index * CreativeWindowConfig.itemsGridColWidth - - item.draw(spriteBatch, shapeRenderer, itemX, inventoryY) - } - } - private fun drawCreative(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, viewport: Rectangle) { + override fun draw(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, viewport: Rectangle, delta: Float) { val creativeWindow = creativeWindowTexture val windowX = viewport.width / 2 - creativeWindow.regionWidth / 2 @@ -84,24 +44,38 @@ class CreativeWindowRenderer @Inject constructor( + (gameInput.creativeScroll * oneScrollAmount) ) + val allItems = gameItemsHolder.getAllItems() + val startIndex = gameInput.creativeScroll * CreativeWindowConfig.itemsInRow + val endIndex = min(startIndex + CreativeWindowConfig.itemsOnPage, allItems.size) + val items = sequence { + for (i in startIndex..