207 lines
3.9 KiB
Go
207 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
)
|
|
|
|
// Dir represents a direction.
|
|
type Dir int
|
|
|
|
// represents the valid directions
|
|
const (
|
|
DirUp Dir = iota
|
|
DirRight
|
|
DirDown
|
|
DirLeft
|
|
)
|
|
|
|
type mouseState int
|
|
|
|
const (
|
|
mouseStateNone mouseState = iota
|
|
mouseStatePressing
|
|
mouseStateSettled
|
|
)
|
|
|
|
type touchState int
|
|
|
|
const (
|
|
touchStateNone touchState = iota
|
|
touchStatePressing
|
|
touchStateSettled
|
|
touchStateInvalid
|
|
)
|
|
|
|
// String returns a string representing the direction.
|
|
func (d Dir) String() string {
|
|
switch d {
|
|
case DirUp:
|
|
return "Up"
|
|
case DirRight:
|
|
return "Right"
|
|
case DirDown:
|
|
return "Down"
|
|
case DirLeft:
|
|
return "Left"
|
|
}
|
|
panic("not reach")
|
|
}
|
|
|
|
// Vector returns a [-1, 1] value for each axis.
|
|
func (d Dir) Vector() (x, y int) {
|
|
switch d {
|
|
case DirUp:
|
|
return 0, -1
|
|
case DirRight:
|
|
return 1, 0
|
|
case DirDown:
|
|
return 0, 1
|
|
case DirLeft:
|
|
return -1, 0
|
|
}
|
|
panic("not reach")
|
|
}
|
|
|
|
// Input represents the current key states.
|
|
type Input struct {
|
|
mouseState mouseState
|
|
mouseInitPosX int
|
|
mouseInitPosY int
|
|
mouseDir Dir
|
|
|
|
touches []ebiten.TouchID
|
|
touchState touchState
|
|
touchID ebiten.TouchID
|
|
touchInitPosX int
|
|
touchInitPosY int
|
|
touchLastPosX int
|
|
touchLastPosY int
|
|
touchDir Dir
|
|
}
|
|
|
|
// NewInput generates a new Input object.
|
|
func NewInput() *Input {
|
|
return &Input{}
|
|
}
|
|
|
|
func abs(x int) int {
|
|
if x < 0 {
|
|
return -x
|
|
}
|
|
return x
|
|
}
|
|
|
|
func vecToDir(dx, dy int) (Dir, bool) {
|
|
if abs(dx) < 4 && abs(dy) < 4 {
|
|
return 0, false
|
|
}
|
|
if abs(dx) < abs(dy) {
|
|
if dy < 0 {
|
|
return DirUp, true
|
|
}
|
|
return DirDown, true
|
|
}
|
|
if dx < 0 {
|
|
return DirLeft, true
|
|
}
|
|
return DirRight, true
|
|
}
|
|
|
|
// Update updates the current input states.
|
|
func (i *Input) Update() {
|
|
switch i.mouseState {
|
|
case mouseStateNone:
|
|
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
|
x, y := ebiten.CursorPosition()
|
|
i.mouseInitPosX = x
|
|
i.mouseInitPosY = y
|
|
i.mouseState = mouseStatePressing
|
|
}
|
|
case mouseStatePressing:
|
|
if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
|
x, y := ebiten.CursorPosition()
|
|
dx := x - i.mouseInitPosX
|
|
dy := y - i.mouseInitPosY
|
|
d, ok := vecToDir(dx, dy)
|
|
if !ok {
|
|
i.mouseState = mouseStateNone
|
|
break
|
|
}
|
|
i.mouseDir = d
|
|
i.mouseState = mouseStateSettled
|
|
}
|
|
case mouseStateSettled:
|
|
i.mouseState = mouseStateNone
|
|
}
|
|
|
|
i.touches = ebiten.AppendTouchIDs(i.touches[:0])
|
|
switch i.touchState {
|
|
case touchStateNone:
|
|
if len(i.touches) == 1 {
|
|
i.touchID = i.touches[0]
|
|
x, y := ebiten.TouchPosition(i.touches[0])
|
|
i.touchInitPosX = x
|
|
i.touchInitPosY = y
|
|
i.touchLastPosX = x
|
|
i.touchLastPosX = y
|
|
i.touchState = touchStatePressing
|
|
}
|
|
case touchStatePressing:
|
|
if len(i.touches) >= 2 {
|
|
break
|
|
}
|
|
if len(i.touches) == 1 {
|
|
if i.touches[0] != i.touchID {
|
|
i.touchState = touchStateInvalid
|
|
} else {
|
|
x, y := ebiten.TouchPosition(i.touches[0])
|
|
i.touchLastPosX = x
|
|
i.touchLastPosY = y
|
|
}
|
|
break
|
|
}
|
|
if len(i.touches) == 0 {
|
|
dx := i.touchLastPosX - i.touchInitPosX
|
|
dy := i.touchLastPosY - i.touchInitPosY
|
|
d, ok := vecToDir(dx, dy)
|
|
if !ok {
|
|
i.touchState = touchStateNone
|
|
break
|
|
}
|
|
i.touchDir = d
|
|
i.touchState = touchStateSettled
|
|
}
|
|
case touchStateSettled:
|
|
i.touchState = touchStateNone
|
|
case touchStateInvalid:
|
|
if len(i.touches) == 0 {
|
|
i.touchState = touchStateNone
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dir returns a currently pressed direction.
|
|
// Dir returns false if no direction key is pressed.
|
|
func (i *Input) Dir() (Dir, bool) {
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowUp) {
|
|
return DirUp, true
|
|
}
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowLeft) {
|
|
return DirLeft, true
|
|
}
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowRight) {
|
|
return DirRight, true
|
|
}
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyArrowDown) {
|
|
return DirDown, true
|
|
}
|
|
if i.mouseState == mouseStateSettled {
|
|
return i.mouseDir, true
|
|
}
|
|
if i.touchState == touchStateSettled {
|
|
return i.touchDir, true
|
|
}
|
|
return 0, false
|
|
}
|