Для начала посмотрим на самый простой способ реализации взаимодействия с клавиатурой:
var key:Array = [];
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
stage.addEventListener(Event.ENTER_FRAME, update);
function keyDownHandler(event:KeyboardEvent):void {
key[event.keyCode] = true;
}
function keyUpHandler(event:KeyboardEvent):void {
key[event.keyCode] = false;
}
function update(event:Event):void {
if (key[Keyboard.LEFT]) {
// Move the player to the left
trace("walk left");
}
if (key[Keyboard.RIGHT]) {
// Move the player to the right
trace("walk right");
}
}
Все прекрасно работает - у нас есть два слушателя событий клавиатуры, которые создают новый элемент массива key или обращаются к существующему элементу массива key по индексу кода нажатой или отпущенной клавиши, и передают ему значение в виде булевого TRUE/FALSE в зависимости от того, была нажата клавиша или отпущена.
Такой способ подходит для большинства случаев, но иногда нужно получить событие нажатой клавиши только один раз, в самом начале нажатия. К примеру мы делаем платформер и при нажатии клавиши прыжка персонаж должен прыгнуть один раз, а не прыгать постоянно, пока клавиша прыжка нажата. Или нам нужно при нажатии определенной клавиши показывать экран паузы и прятать его при повторном нажатии. Также можно вспомнить стандартное press space в экране пройденного уровня.
Для того чтобы реализовать подобный функционал нам нужно знать текущее и прошлое состояние нужной нам клавиши.
Сначала вынесем весь код по обработке событий клавиатуры в отдельный класс Input с глобальным доступом и реализуем старый функционал. Также мы поменяем массив на фиксированый вектор и добавим новый метод isDown для получения значения нажатой клавиши.
package {
import flash.display.*;
import flash.events.*;
public class Input {
private static var pressed:Vector. = new Vector.(256, true);
public static function init(stage:Stage) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
private static function keyDownHandler(event:KeyboardEvent):void {
pressed[event.keyCode] = true;
}
private static function keyUpHandler(event:KeyboardEvent):void {
pressed[event.keyCode] = false;
}
public static function isDown(key:uint):Boolean {
return pressed[key];
}
}
}
В самом начале Input нужно инициализировать с ссылкой на stage и затем его можно использовать в любом месте вашего приложения.
Input.init(stage);
stage.addEventListener(Event.ENTER_FRAME, update);
function update(event:Event):void {
if (Input.isDown(Keyboard.LEFT)) {
// Move the player to the left
trace("walk left");
}
if (Input.isDown(Keyboard.RIGHT)) {
// Move the player to the right
trace("walk right");
}
}
Теперь можно внедрить новый функционал. Нам понадобится еще один вектор и два новых метода. Метод isPressed будет проверять текущее и прошлое состояние нужной нам клавиши. Метод update будет записывать прошлое состояние нажатых клавиш в вектор released.
package {
import flash.display.*;
import flash.events.*;
public class Input {
private static var pressed:Vector. = new Vector.(256, true);
private static var released:Vector. = new Vector.(256, true);
public static function init(stage:Stage) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
}
private static function keyDownHandler(event:KeyboardEvent):void {
pressed[event.keyCode] = true;
}
private static function keyUpHandler(event:KeyboardEvent):void {
pressed[event.keyCode] = false;
}
public static function isDown(key:uint):Boolean {
return pressed[key];
}
public static function isPressed(key:uint):Boolean {
return released[key] && pressed[key];
}
public static function update():void {
for (var i:int = 0; i < 256; i++) {
released[i] = !pressed[i];
}
}
public static function dispose():void {
for (var i:int = 0; i < 256; i++) {
pressed[i] = false;
}
}
}
}
Теперь можно протестировать результат. Главное отличие это то что нужно не забыть использовать метод update класса Input, чтобы записать прошлое состояние нажатых клавиш.
Input.init(stage);
stage.addEventListener(Event.ENTER_FRAME, update);
function update(event:Event):void {
if (Input.isPressed(Keyboard.UP)) {
// Player jump
trace("jump");
}
if (Input.isDown(Keyboard.LEFT)) {
// Move the player to the left
trace("walk left");
}
if (Input.isDown(Keyboard.RIGHT)) {
// Move the player to the right
trace("walk right");
}
Input.update();
}
Также, чтобы не импортировать flash.ui.Keyboard, можно добавить константы представляющие клавиши. Сами константы можно взять, например, из пакета net.flashpunk.utils.Key движка FlashPunk.