Skip to content

Commit

Permalink
client/Joystick: Move both joysticks with touch.
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin Harris committed Jun 27, 2020
1 parent 36667aa commit 91af1e2
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 16 deletions.
4 changes: 2 additions & 2 deletions website-client/src/components/Controller/Controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Controller extends React.Component<{
</ControllerButton>
</div>
</div>
<Joystick
<Joystick name='l'
sendCommand={sendCommand}
x={controllerState?.leftStick?.horizontalValue || 0}
y={controllerState?.leftStick?.verticalValue || 0}
Expand Down Expand Up @@ -163,7 +163,7 @@ class Controller extends React.Component<{
},
]}
/>
<Joystick
<Joystick name = 'r'
sendCommand={sendCommand}
x={controllerState?.rightStick?.horizontalValue || 0}
y={controllerState?.rightStick?.verticalValue || 0}
Expand Down
118 changes: 104 additions & 14 deletions website-client/src/components/Controller/Joystick/Joystick.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createStyles, withStyles } from '@material-ui/core'
import React from 'react'
import { SendCommand } from '../../../key-binding/KeyBinding'

const styles = () => createStyles({
joystickHolder: {
Expand All @@ -23,25 +24,114 @@ const styles = () => createStyles({
}
})

const Joystick: React.FunctionComponent<any> = (props: any) => {
const { classes } = props
let joystickHolderClassList = classes.joystickHolder
let joystickClassList = classes.joystick
const movedThreshold = 0.15
if (props.pressed) {
joystickHolderClassList += " " + classes.pressed

class Joystick extends React.Component<{
name: string,
sendCommand: SendCommand,
x: number, y: number,
pressed: boolean,
classes: any,
}> {
prevX: number = 0
prevY: number = 0
prevH: number = 0
prevV: number = 0

constructor(props: any) {
super(props)

this.onDrag = this.onDrag.bind(this)
this.onSelect = this.onSelect.bind(this)
this.onUnselect = this.onUnselect.bind(this)
this.preventScroll = this.preventScroll.bind(this)
}
if (Math.abs(props.x) > movedThreshold || Math.abs(props.y) > movedThreshold) {
joystickClassList += " " + classes.pressed

private preventScroll(e: any) {
e.preventDefault()
}

const styles = {
transform: `translate(${props.x * 15}px, ${props.y * 15}px)`,
private onSelect(e: React.TouchEvent<HTMLDivElement> | React.DragEvent<HTMLDivElement>) {
let x, y
if (e.type.includes('drag')) {
const event = e as React.DragEvent<HTMLDivElement>
x = event.clientX
y = event.clientY

} else {
const event = e as React.TouchEvent<HTMLDivElement>

const touch = event.targetTouches[0]
x = touch.clientX
y = touch.clientY
}
this.prevX = x
this.prevY = y

document.addEventListener('touchmove', this.preventScroll, { passive: false })
e.preventDefault()
}
return <div className={joystickHolderClassList}>
<div className={joystickClassList} style={styles}>

private onDrag(e: React.TouchEvent<HTMLDivElement> | React.DragEvent<HTMLDivElement>) {
let x, y
if (e.type.includes('drag')) {
const event = e as React.DragEvent<HTMLDivElement>
x = event.clientX
y = event.clientY

} else {
const event = e as React.TouchEvent<HTMLDivElement>

const touch = event.targetTouches[0]
x = touch.clientX
y = touch.clientY
}
const scale = 16
const threshold = 0.01
const h = Math.min(Math.max((x - this.prevX) / scale, -1), 1)
const v = Math.min(Math.max((y - this.prevY) / scale, -1), 1)
if (Math.abs(h - this.prevH) > threshold || Math.abs(v - this.prevV) > threshold) {
// console.log(`${x - this.prevX} => ${h}, ${y - this.prevY} => ${v}`)
// TODO Pass the updated controller state. so that multiple buttons can be highlighted.
this.props.sendCommand(`s ${this.props.name} hv ${h.toFixed(3)} ${v.toFixed(3)}`)
}
this.prevH = h
this.prevV = v
// e.preventDefault()
}

private onUnselect(e: React.TouchEvent<HTMLDivElement> | React.DragEvent<HTMLDivElement>) {
this.props.sendCommand(`s ${this.props.name} center`)
document.removeEventListener('touchmove', this.preventScroll)
e.preventDefault()
}

render(): React.ReactNode {
const { classes, x, y } = this.props
let joystickHolderClassList = classes.joystickHolder
let joystickClassList = classes.joystick
const movedThreshold = 0.15
if (this.props.pressed) {
joystickHolderClassList += " " + classes.pressed
}
if (Math.abs(x) > movedThreshold || Math.abs(y) > movedThreshold) {
joystickClassList += " " + classes.pressed
}

const styles = {
transform: `translate(${x * 15}px, ${y * 15}px)`,
}

return <div className={joystickHolderClassList}>
<div className={joystickClassList} style={styles}
onDragStart={this.onSelect}
onTouchStart={this.onSelect}
onDrag={this.onDrag}
onTouchMove={this.onDrag}
onDragEnd={this.onUnselect}
onTouchEnd={this.onUnselect}>
</div>
</div>
</div>
}
}

export default withStyles(styles)(Joystick)

0 comments on commit 91af1e2

Please sign in to comment.