DEADSOFTWARE

6a4b5a4eb968101d134eeeefa7aa9b9e290b51bd
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / input / handler / mouse / CursorMouseInputHandler.kt
1 package ru.deadsoftware.cavedroid.game.input.handler.mouse
3 import com.badlogic.gdx.math.MathUtils
4 import ru.deadsoftware.cavedroid.MainConfig
5 import ru.deadsoftware.cavedroid.game.GameItemsHolder
6 import ru.deadsoftware.cavedroid.game.GameScope
7 import ru.deadsoftware.cavedroid.game.GameUiWindow
8 import ru.deadsoftware.cavedroid.game.input.IGameInputHandler
9 import ru.deadsoftware.cavedroid.game.input.action.MouseInputAction
10 import ru.deadsoftware.cavedroid.game.input.action.keys.MouseInputActionKey
11 import ru.deadsoftware.cavedroid.game.mobs.Mob
12 import ru.deadsoftware.cavedroid.game.mobs.MobsController
13 import ru.deadsoftware.cavedroid.game.mobs.player.Player
14 import ru.deadsoftware.cavedroid.game.model.block.Block
15 import ru.deadsoftware.cavedroid.game.ui.TooltipManager
16 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsConfigs
17 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
18 import ru.deadsoftware.cavedroid.game.world.GameWorld
19 import ru.deadsoftware.cavedroid.misc.Assets
20 import ru.deadsoftware.cavedroid.misc.utils.bl
21 import ru.deadsoftware.cavedroid.misc.utils.px
22 import javax.inject.Inject
24 @GameScope
25 class CursorMouseInputHandler @Inject constructor(
26 private val mainConfig: MainConfig,
27 private val mobsController: MobsController,
28 private val gameWorld: GameWorld,
29 private val gameWindowsManager: GameWindowsManager,
30 private val gameItemsHolder: GameItemsHolder,
31 private val tooltipManager: TooltipManager,
32 ) : IGameInputHandler<MouseInputAction> {
34 private val player get() = mobsController.player
36 private val creativeInventoryTexture get() = requireNotNull(Assets.textureRegions["creative"])
38 private val Block.isAutoselectable
39 get() = !isNone() && params.hasCollision
41 private fun GameWorld.isCurrentBlockAutoselectable() =
42 getForeMap(player.cursorX, player.cursorY).isAutoselectable
44 private fun checkCursorBounds() {
45 if (player.gameMode == 0) {
46 val minCursorX = player.mapX - SURVIVAL_CURSOR_RANGE
47 val maxCursorX = player.mapX + SURVIVAL_CURSOR_RANGE
48 val minCursorY = player.middleMapY - SURVIVAL_CURSOR_RANGE
49 val maxCursorY = player.middleMapY + SURVIVAL_CURSOR_RANGE
51 player.cursorX = MathUtils.clamp(player.cursorX, minCursorX, maxCursorX)
52 player.cursorY = MathUtils.clamp(player.cursorY, minCursorY, maxCursorY)
53 }
55 player.cursorY = MathUtils.clamp(player.cursorY, 0, gameWorld.height - 1)
56 }
58 private fun setPlayerDirectionToCursor() {
59 if (player.controlMode != Player.ControlMode.CURSOR) {
60 return
61 }
63 if (player.cursorX.px + 8 < player.x + player.width / 2) {
64 player.setDir(Mob.Direction.LEFT)
65 } else {
66 player.setDir(Mob.Direction.RIGHT)
67 }
68 }
70 private fun handleWalkTouch() {
71 player.cursorX = player.mapX + player.direction.basis
72 player.cursorY = player.upperMapY
74 for (i in 1..2) {
75 if (gameWorld.isCurrentBlockAutoselectable()) {
76 break
77 }
78 player.cursorY++
79 }
81 if (!gameWorld.isCurrentBlockAutoselectable()) {
82 player.cursorX -= player.direction.basis
83 }
84 }
86 private fun getPlayerHeadRotation(mouseWorldX: Float, mouseWorldY: Float): Float {
87 val h = mouseWorldX - player.x
88 val v = mouseWorldY - player.y
90 return MathUtils.atan(v / h) * MathUtils.radDeg
91 }
93 private fun handleMouse(action: MouseInputAction) {
94 val worldX = action.screenX + action.cameraViewport.x
95 val worldY = action.screenY + action.cameraViewport.y
97 // when worldX < 0, need to subtract 1 to avoid negative zero
98 // val fixCycledWorld = if (worldX < 0) 1 else 0
100 player.cursorX = worldX.bl - 0
101 player.cursorY = worldY.bl
103 player.headRotation = getPlayerHeadRotation(worldX, worldY)
106 private fun getCreativeTooltip(action: MouseInputAction): String? {
107 val creativeTexture = creativeInventoryTexture
108 val xOnGrid = (action.screenX - (action.cameraViewport.width / 2 - creativeTexture.regionWidth / 2 +
109 GameWindowsConfigs.Creative.itemsGridMarginLeft)) /
110 GameWindowsConfigs.Creative.itemsGridColWidth
111 val yOnGrid = (action.screenY - (action.cameraViewport.height / 2 - creativeTexture.regionHeight / 2 +
112 GameWindowsConfigs.Creative.itemsGridMarginTop)) /
113 GameWindowsConfigs.Creative.itemsGridRowHeight
115 if (xOnGrid < 0 || xOnGrid >= GameWindowsConfigs.Creative.itemsInRow ||
116 yOnGrid < 0 || yOnGrid >= GameWindowsConfigs.Creative.itemsInCol) {
117 return null
120 val itemIndex = (gameWindowsManager.creativeScrollAmount * GameWindowsConfigs.Creative.itemsInRow +
121 (xOnGrid.toInt() + yOnGrid.toInt() * GameWindowsConfigs.Creative.itemsInRow))
122 val item = gameItemsHolder.getItemFromCreativeInventory(itemIndex)
124 return item.params.name
127 override fun checkConditions(action: MouseInputAction): Boolean {
128 return action.actionKey is MouseInputActionKey.None
131 override fun handle(action: MouseInputAction) {
132 val pastCursorX = player.cursorX
133 val pastCursorY = player.cursorY
135 when {
136 player.controlMode == Player.ControlMode.WALK && mainConfig.isTouch -> handleWalkTouch()
137 !mainConfig.isTouch -> handleMouse(action)
140 checkCursorBounds()
141 setPlayerDirectionToCursor()
143 if (player.cursorX != pastCursorX || player.cursorY != pastCursorY) {
144 player.blockDamage = 0f
147 if (gameWindowsManager.getCurrentWindow() == GameUiWindow.CREATIVE_INVENTORY) {
148 tooltipManager.showMouseTooltip(getCreativeTooltip(action).orEmpty())
152 companion object {
153 private const val SURVIVAL_CURSOR_RANGE = 4