feat: rework mobile button control sizes & joystick. Make size of every button and joystick configurable via configurator UI from settings!

This commit is contained in:
Vitaly Turovsky 2025-04-06 00:23:17 +03:00
commit 9b71ae1a24
2 changed files with 55 additions and 15 deletions

View file

@ -129,18 +129,18 @@ function getDefaultTouchControlsPositions () {
],
break: [
70,
60
57
],
jump: [
84,
60
57
],
} as Record<string, [number, number]>
}
function getTouchControlsSize () {
return {
joystick: 60,
joystick: 55,
action: 36,
break: 36,
jump: 36,

View file

@ -1,9 +1,10 @@
import { CSSProperties, PointerEvent, useEffect, useRef } from 'react'
import { CSSProperties, PointerEvent, useEffect, useRef, useState } from 'react'
import { proxy, ref, useSnapshot } from 'valtio'
import { contro } from '../controls'
import { options } from '../optionsStorage'
import PixelartIcon from './PixelartIcon'
import Button from './Button'
import Slider from './Slider'
export type ButtonName = 'action' | 'sneak' | 'break' | 'jump'
@ -54,8 +55,9 @@ const Z_INDEX_INTERACTIBLE = 8
export default ({ setupActive, closeButtonsSetup, foregroundGameActive }: Props) => {
const bot = window.bot as typeof __type_bot | undefined
const { touchControlsPositions, touchMovementType, touchInteractionType } = useSnapshot(options)
const { touchControlsPositions, touchMovementType, touchInteractionType, touchControlsSize } = useSnapshot(options)
const buttonsPositions = touchControlsPositions as ButtonsPositions
const [selectedButton, setSelectedButton] = useState<ButtonName | 'joystick' | null>(null)
const joystickOuter = useRef<HTMLDivElement>(null)
const joystickInner = useRef<HTMLDivElement>(null)
@ -143,19 +145,23 @@ export default ({ setupActive, closeButtonsSetup, foregroundGameActive }: Props)
left: `${buttonsPositions[name][0]}%`,
top: `${buttonsPositions[name][1]}%`,
borderRadius: '50%',
width: '32px',
height: '32px',
width: `${touchControlsSize[name]}px`,
height: `${touchControlsSize[name]}px`,
background: active ? 'rgba(0, 0, 0, 0.8)' : 'rgba(0, 0, 0, 0.5)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
transition: 'background 0.1s',
zIndex: Z_INDEX_INTERACTIBLE,
...(setupActive && selectedButton === name ? {
border: '2px solid white',
} : {}),
} satisfies CSSProperties,
onPointerDown (e: PType) {
const elem = e.currentTarget as HTMLElement
elem.setPointerCapture(e.pointerId)
if (setupActive) {
setSelectedButton(name)
setupPointer = { x: e.clientX, y: e.clientY }
} else {
holdDown[name]()
@ -188,33 +194,67 @@ export default ({ setupActive, closeButtonsSetup, foregroundGameActive }: Props)
if (!foregroundGameActive && !setupActive) return null
return <div>
{setupActive && (
<div style={{
position: 'fixed',
top: '0',
left: '50%',
transform: 'translateX(-50%)',
zIndex: Z_INDEX_INTERACTIBLE + 1,
}}>
<Slider
label={selectedButton ? `Size: ${selectedButton}` : 'Change button size'}
value={selectedButton ? touchControlsSize[selectedButton] : 32}
min={15}
max={100}
disabledReason={selectedButton ? undefined : 'Select a button first'}
updateValue={(value) => {
if (selectedButton) {
options.touchControlsSize[selectedButton] = value
}
}}
/>
</div>
)}
{touchMovementType === 'modern' && (
<div
className='movement_joystick_outer'
ref={joystickOuter}
style={{
display: pointer ? 'flex' : 'none',
display: pointer || setupActive ? 'flex' : 'none',
borderRadius: '50%',
width: 50,
height: 50,
width: touchControlsSize.joystick,
height: touchControlsSize.joystick,
border: '2px solid rgba(0, 0, 0, 0.5)',
backgroundColor: 'rgba(255, 255, div, 0.5)',
backgroundColor: 'rgba(255, 255, 255, 0.5)',
position: 'fixed',
justifyContent: 'center',
alignItems: 'center',
translate: '-50% -50%',
...pointer ? {
...(setupActive ? {
left: '20%',
top: '50%',
cursor: 'pointer',
...(selectedButton === 'joystick' ? {
border: '2px solid white',
} : {}),
} : pointer ? {
left: `${pointer.x / window.innerWidth * 100}%`,
top: `${pointer.y / window.innerHeight * 100}%`
} : {}
} : {}),
}}
onClick={() => {
if (setupActive) {
setSelectedButton('joystick')
}
}}
>
<div
className='movement_joystick_inner'
style={{
borderRadius: '50%',
width: 20,
height: 20,
width: touchControlsSize.joystick * 0.35,
height: touchControlsSize.joystick * 0.35,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
position: 'absolute',
}}