1 package ru.deadsoftware.cavedroid.game.render
3 import com.badlogic.gdx.graphics.g2d.SpriteBatch
4 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
5 import com.badlogic.gdx.math.Rectangle
6 import ru.deadsoftware.cavedroid.game.GameInput
7 import ru.deadsoftware.cavedroid.game.GameScope
8 import ru.deadsoftware.cavedroid.game.mobs.MobsController
9 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
10 import ru.deadsoftware.cavedroid.game.world.GameWorld
11 import ru.deadsoftware.cavedroid.misc.Assets
12 import ru.deadsoftware.cavedroid.misc.ControlMode
13 import ru.deadsoftware.cavedroid.misc.utils.px
14 import javax.inject.Inject
16 @GameScope
17 class HudRenderer @Inject constructor(
18 private val gameInput: GameInput,
19 private val gameWorld: GameWorld,
20 private val mobsController: MobsController,
21 ) : IGameRenderer {
23 override val renderLayer = RENDER_LAYER
25 private val cursorTexture get() = requireNotNull(Assets.textureRegions[CURSOR_KEY])
26 private val hotbarTexture get() = requireNotNull(Assets.textureRegions[HOTBAR_KEY])
27 private val hotbarSelectorTexture get() = requireNotNull(Assets.textureRegions[HOTBAR_SELECTOR_KEY])
28 private val wholeHeartTexture get() = requireNotNull(Assets.textureRegions[WHOLE_HEART_KEY])
29 private val halfHeartTexture get() = requireNotNull(Assets.textureRegions[HALF_HEART_KEY])
31 private fun drawCursor(spriteBatch: SpriteBatch, viewport: Rectangle) {
32 val cursorX = mobsController.player.cursorX
33 val cursorY = mobsController.player.cursorY
35 if (gameWorld.hasForeAt(cursorX, cursorY) ||
36 gameWorld.hasBackAt(cursorX, cursorY) ||
37 gameInput.controlMode == ControlMode.CURSOR
38 ) {
39 spriteBatch.draw(cursorTexture, cursorX.px - viewport.x, cursorY.px - viewport.y)
40 }
41 }
43 private fun drawHealth(spriteBatch: SpriteBatch, x: Float, y: Float) {
44 val player = mobsController.player
46 if (player.gameMode == 1) {
47 return
48 }
50 val wholeHeart = wholeHeartTexture
51 val wholeHearts = player.health / 2
53 for (i in 0..<wholeHearts) {
54 spriteBatch.draw(wholeHeart, x + i * wholeHeart.regionWidth, y)
55 }
57 if (player.health % 2 == 1) {
58 spriteBatch.draw(halfHeartTexture, x + wholeHearts * wholeHeart.regionWidth, y)
59 }
60 }
62 private fun drawHotbarItems(spriteBatch: SpriteBatch, hotbarX: Float) {
63 mobsController.player.inventory.asSequence()
64 .map(InventoryItem::item)
65 .forEachIndexed { index, item ->
66 if (item.isNone()) {
67 return@forEachIndexed
68 }
70 spriteBatch.draw(
71 /* region = */ item.sprite,
72 /* x = */ hotbarX + HotbarConfig.horizontalMargin
73 + index * (HotbarConfig.itemSeparatorWidth + HotbarConfig.itemSlotSpace),
74 /* y = */ HotbarConfig.verticalMargin,
75 )
76 }
77 }
79 private fun drawHotbarSelector(spriteBatch: SpriteBatch, hotbarX: Float) {
80 spriteBatch.draw(
81 /* region = */ hotbarSelectorTexture,
82 /* x = */ hotbarX - HotbarSelectorConfig.horizontalPadding
83 + mobsController.player.slot * (HotbarConfig.itemSeparatorWidth + HotbarConfig.itemSlotSpace),
84 /* y = */ -HotbarSelectorConfig.verticalPadding
85 )
86 }
88 private fun drawHotbar(spriteBatch: SpriteBatch, viewport: Rectangle) {
89 val hotbar = hotbarTexture
90 val hotbarX = viewport.width / 2 - hotbar.regionWidth / 2
92 spriteBatch.draw(hotbar, hotbarX, 0f)
93 drawHealth(spriteBatch, hotbarX, hotbarTexture.regionHeight.toFloat())
94 drawHotbarItems(spriteBatch, hotbarX)
95 drawHotbarSelector(spriteBatch, hotbarX)
96 }
98 override fun draw(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, viewport: Rectangle, delta: Float) {
99 drawCursor(spriteBatch, viewport)
100 drawHotbar(spriteBatch, viewport)
101 }
103 companion object {
104 private const val RENDER_LAYER = 100500
106 private const val CURSOR_KEY = "cursor"
107 private const val HOTBAR_KEY = "hotbar"
108 private const val HOTBAR_SELECTOR_KEY = "hotbar_selector"
109 private const val WHOLE_HEART_KEY = "heart_whole"
110 private const val HALF_HEART_KEY = "heart_half"
112 private data object HotbarConfig {
113 const val horizontalMargin = 3f
114 const val verticalMargin = 3f
115 const val itemSeparatorWidth = 4f
116 const val itemSlotSpace = 16f
117 }
119 private data object HotbarSelectorConfig {
120 const val horizontalPadding = 1f
121 const val verticalPadding = 1f
122 }
123 }
124 }