DEADSOFTWARE

Add joystick touch controls
[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 setPlayerDirectionToCursor() {
45 if (player.controlMode != Player.ControlMode.CURSOR) {
46 return
47 }
49 if (player.cursorX.px + 8 < player.x + player.width / 2) {
50 player.setDir(Mob.Direction.LEFT)
51 } else {
52 player.setDir(Mob.Direction.RIGHT)
53 }
54 }
56 private fun handleWalkTouch() {
57 player.cursorX = player.mapX + player.direction.basis
58 player.cursorY = player.upperMapY
60 for (i in 1..2) {
61 if (gameWorld.isCurrentBlockAutoselectable()) {
62 break
63 }
64 player.cursorY++
65 }
67 if (!gameWorld.isCurrentBlockAutoselectable()) {
68 player.cursorX -= player.direction.basis
69 }
70 }
72 private fun getPlayerHeadRotation(mouseWorldX: Float, mouseWorldY: Float): Float {
73 val h = mouseWorldX - player.x
74 val v = mouseWorldY - player.y
76 return MathUtils.atan(v / h) * MathUtils.radDeg
77 }
79 private fun handleMouse(action: MouseInputAction) {
80 val worldX = action.screenX + action.cameraViewport.x
81 val worldY = action.screenY + action.cameraViewport.y
83 // when worldX < 0, need to subtract 1 to avoid negative zero
84 // val fixCycledWorld = if (worldX < 0) 1 else 0
86 player.cursorX = worldX.bl - 0
87 player.cursorY = worldY.bl
89 player.headRotation = getPlayerHeadRotation(worldX, worldY)
90 }
92 private fun getCreativeTooltip(action: MouseInputAction): String? {
93 val creativeTexture = creativeInventoryTexture
94 val xOnGrid = (action.screenX - (action.cameraViewport.width / 2 - creativeTexture.regionWidth / 2 +
95 GameWindowsConfigs.Creative.itemsGridMarginLeft)) /
96 GameWindowsConfigs.Creative.itemsGridColWidth
97 val yOnGrid = (action.screenY - (action.cameraViewport.height / 2 - creativeTexture.regionHeight / 2 +
98 GameWindowsConfigs.Creative.itemsGridMarginTop)) /
99 GameWindowsConfigs.Creative.itemsGridRowHeight
101 if (xOnGrid < 0 || xOnGrid >= GameWindowsConfigs.Creative.itemsInRow ||
102 yOnGrid < 0 || yOnGrid >= GameWindowsConfigs.Creative.itemsInCol) {
103 return null
106 val itemIndex = (gameWindowsManager.creativeScrollAmount * GameWindowsConfigs.Creative.itemsInRow +
107 (xOnGrid.toInt() + yOnGrid.toInt() * GameWindowsConfigs.Creative.itemsInRow))
108 val item = gameItemsHolder.getItemFromCreativeInventory(itemIndex)
110 return item.params.name
113 override fun checkConditions(action: MouseInputAction): Boolean {
114 return action.actionKey is MouseInputActionKey.None
117 override fun handle(action: MouseInputAction) {
118 val pastCursorX = player.cursorX
119 val pastCursorY = player.cursorY
121 when {
122 player.controlMode == Player.ControlMode.WALK && mainConfig.isTouch -> handleWalkTouch()
123 !mainConfig.isTouch -> handleMouse(action)
126 player.checkCursorBounds(gameWorld)
127 setPlayerDirectionToCursor()
129 if (player.cursorX != pastCursorX || player.cursorY != pastCursorY) {
130 player.blockDamage = 0f
133 if (gameWindowsManager.getCurrentWindow() == GameUiWindow.CREATIVE_INVENTORY) {
134 tooltipManager.showMouseTooltip(getCreativeTooltip(action).orEmpty())
138 companion object {
139 private const val SURVIVAL_CURSOR_RANGE = 4