Я впервые пишу игру на холсте html5. Для начала я решил создать приведенный ниже класс, чтобы я мог проверять входные данные в каждом цикле обновления. Класс может обнаруживать события нажатия клавиш / мыши вниз / вверх и отслеживать положение мыши. Я планирую добавить прокрутку мыши, если понадобится, позже.
Все мнения / предложения приветствуются!
Объяснение
После инициализации класс будет прослушивать события нажатия клавиш / мыши вверх / вниз и записывать их в state имущество. state имеет формат {[inputname]: {[press], [trigger], [release]}}. Это записи Date.now() при последнем нажатии / срабатывании / отпускании входа. press обновляется только при первом нажатии кнопки. trigger обновляется каждый раз, когда вызывается нажатие клавиши мыши / клавиши (обратите внимание, что только события нажатия клавиши повторяются, когда клавиша уже нажата). state также магазины mousePosition: {x, y}.
Ключи объекта, представляющие каждую кнопку, имеют формат `mouse${[MouseEvent.button]}` или `key${[KeyboardEvent.code]}`. Я храню часто используемые ключи как статические, но намерение состоит в том, чтобы позволить пользователям настраивать свои собственные элементы управления, поэтому для установки значений по умолчанию необходимы только «часто используемые» ключи.
использование
Инициализировать с помощью
new Input(target).targetэто часть DOM, которую вы хотите прослушивать для ввода (по умолчаниюdocument).Чтобы проверить ввод, используйте
check(...)а такжеmousePosition()методы.checkпринимает 3 аргумента —hash,type,buttonStateи возвращает логическое значение.hashэто входное представление, как указано выше.typeявляетсяInput.STARTилиInput.CURRENT.STARTпроверяет, был ли вход нажат / запущен / отпущен, начиная с этого кадра.CURRENTпросто проверяет, нажата / отпущена ли в данный момент ввод (примечаниеCURRENTнажатие такое же, какCURRENTсрабатывает).buttonStateявляетсяInput.PRESS,Input.TRIGGERилиInput.RELEASE— в каком бы состоянии вы ни проверяли вход.Например. чтобы проверить, вызвал ли этот кадр нажатие клавиши возврата, вызовите
.check(Input.KEYENTER, Input.START, Input.TRIGGER).После проверки входов,
doneCheck()нужно вызывать каждый кадр. Внутри класс отслеживаетDate.now()каждый раз его вызывают. Таким образом можно избежать двойной обработки входных данных.
Код
class Input {
static START = 0
static CURRENT = 1
static PRESS = 0
static TRIGGER = 1
static RELEASE = 2
static MOUSE = 'mouse'
static KEY = 'key'
static MOUSELEFT = `${Input.MOUSE}${0}`
static MOUSEMIDDLE = `${Input.MOUSE}${1}`
static MOUSERIGHT = `${Input.MOUSE}${2}`
static KEYDOWN = `${Input.KEY}${'ArrowDown'}`
static KEYLEFT = `${Input.KEY}${'ArrowLeft'}`
static KEYRIGHT = `${Input.KEY}${'ArrowRight'}`
static KEYUP = `${Input.KEY}${'ArrowUp'}`
static KEYENTER = `${Input.KEY}${'Enter'}`
static KEYSPACE = `${Input.KEY}${'Space'}`
constructor(target = document) {
this.doneCheck()
this.state = {mousePosition: {}}
Object.entries({
'keydown': e => this.press(e, Input.KEY, e.code),
'keyup': e => this.release(e, Input.KEY, e.code),
'mousedown': e => this.press(e, Input.MOUSE, e.button),
'mouseup': e => this.release(e, Input.MOUSE, e.button),
'mousemove': e => this.mouseMove(e, e.x, e.y),
}).forEach(([eventType, func]) => target.addEventListener(eventType, e => func(e)))
}
//Input
press(e, type, input) {
const hash = `${type}${input}`
this.state[hash] = this.state[hash] || {[Input.PRESS]: 0, [Input.TRIGGER]: 0, [Input.RELEASE]: 0}
this.state[hash][Input.TRIGGER] = Date.now()
if (this.state[hash][Input.RELEASE] >= this.state[hash][Input.PRESS]) this.state[hash][Input.PRESS] = this.state[hash][Input.TRIGGER]
}
release(e, type, input) {
const hash = `${type}${input}`
this.state[hash] = this.state[hash] || {[Input.PRESS]: 0, [Input.TRIGGER]: 0, [Input.RELEASE]: 0}
this.state[hash][Input.RELEASE] = Date.now()
}
mouseMove(e, x, y) {
this.state.mousePosition.x = x
this.state.mousePosition.y = y
}
//Check
check(
hash,
type = Input.START, //START, CURRENT
buttonState = Input.PRESS, //PRESS, TRIGGER, RELEASE
) {
return (type === Input.START && this.state[hash] && this.checked < this.state[hash][buttonState]) ||
(type === Input.CURRENT && (buttonState === Input.PRESS) === (this.state[hash] && this.state[hash][Input.RELEASE] < this.state[hash][Input.PRESS]))
}
doneCheck() {
this.checked = Date.now()
}
mousePosition() {
return this.state.mousePosition
}
}
Как это может выглядеть при использовании:

