Monday, October 22, 2012

Creating EasyKeyboard class: Part 4

In this part we will add the ability to add key hold listeners.

The key hold listeners will execute the handler function when a certain key is being held, every frame.

First create a new class file called HoldListener.as.

The class is simple, it has 3 public properties - keyCode, handler and flag. The constructor of the class receives these 3 values (as code, func and boolean) and applies them to the properties.

package com.kircode.EasyKeyboard 
{
/**
 * ...
 * @author Kirill Poletaev
 */
public class HoldListener 
{

public var keyCode:int;
public var handler:Function;
public var flag:Boolean;

public function HoldListener(code:int, func:Function, boolean:Boolean) 
{
keyCode = code;
handler = func;
flag = boolean;
}

}

}

Now return to EasyKeyboard.as and add a new method - addHoldListener(). Pass 2 values as parameters - keyCode and handler. Use the received values to create a HoldListener object, which is then pushed to the listeners array:

/**
 * Add hold event listener for a single key using a keycode.
 * @paramkeyCode Key code of the key.
 * @paramhandler Function to execute while the key is held every frame.
 */

public function addHoldListener(keyCode:int, handler:Function):void {
listeners.push(new HoldListener(keyCode, handler, false));
}

You may wonder, why are there only 2 properties passed to the method, while the HoldListener object has 3 properties. The answer is that the third property, which is a boolean, is a flag value that will be set to true when the specific key is pressed down, and to false when the key is released. This way, we can execute the handler every frame if the flag value is true.

We need to go to kDown and kUp functions and add if...statements there, which set the flag variable to true and false if the keycode matches and the type of the listener is HoldListener:

private function kDown(evt:KeyboardEvent):void {
for (var i:int = 0; i < listeners.length; i++) {
if (evt.keyCode == listeners[i].keyCode && listeners[i] is KeyListener && evt.altKey == listeners[i].alt && evt.ctrlKey == listeners[i].ctrl && evt.shiftKey == listeners[i].shift) {
if (listeners[i].handlerD) listeners[i].handlerD.call();
}
if (evt.keyCode == listeners[i].keyCode && listeners[i] is HoldListener) {
listeners[i].flag = true;
}
}
}

private function kUp(evt:KeyboardEvent):void {
for (var i:int = 0; i < listeners.length; i++) {
if (evt.keyCode == listeners[i].keyCode && listeners[i] is KeyListener && evt.altKey == listeners[i].alt && evt.ctrlKey == listeners[i].ctrl && evt.shiftKey == listeners[i].shift) {
if (listeners[i].handlerU) listeners[i].handlerU.call();
}
if (evt.keyCode == listeners[i].keyCode && listeners[i] is HoldListener) {
listeners[i].flag = false;
}
}
}

Now we can go to frame() function and add a loop here, which loops through all listeners, and if it's a HoldListener - the flag value is checked. If flag is true, call the handler.

private function frame(evt:Event):void {
for (var i:int = 0; i < listeners.length; i++) {
if (listeners[i] is HoldListener && listeners[i].flag) {
listeners[i].handler.call();
}
}
}

Full code so far:

package com.kircode.EasyKeyboard 
{
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;

/**
 * Utility for easy keyboard listener management.
 * @author Kirill Poletaev
 */
public class EasyKeyboard 
{
public var listeners:Array = [];
private var keyLabels:Array = ["0","1","2","3","4","5","6","7","Backspace","Tab","10","11","Center","Enter","14","15","Shift","Control","Alt","Pause","Caps Lock","21","22","23","24","25","26","27","28","29","30","31","Space","Page Up","Page Down","End","Home","Left","Up","Right","Down","41","42","43","44","Insert","Delete","47","0","1","2","3","4","5","6","7","8","9","58","59","60","61","62","63","64","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","Windows","Windows","Menu","94","95","Num 0","Num 1","Num 2","Num 3","Num 4","Num 5","Num 6","Num 7","Num 8","Num 9","Num *","Num +","108","Num -","Num .","Num /","F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12","124","125","126","127","128","129","130","131","132","133","134","135","136","137","138","139","140","141","142","143","Num Lock","Scroll Lock","146","147","148","149","150","151","152","153","154","155","156","157","158","159","160","161","162","163","164","165","166","167","168","169","170","171","172","173","174","175","176","177","178","179","180","181","182","183","184","185",";","+",",","-",".","/","~","193","194","195","196","197","198","199","200","201","202","203","204","205","206","207","208","209","210","211","212","213","214","215","216","217","218","[","\\","]","'","223","224","225","226","227","228","229","230","231","232","233","234","235","236","237","238","239","240","241","242","243","244","245","246","247","248","249","250","251","252","253","254","255"];
private var st:Stage;

public function EasyKeyboard(stage:Stage) 
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, kDown);
stage.addEventListener(KeyboardEvent.KEY_UP, kUp);
stage.addEventListener(Event.ENTER_FRAME, frame);
st = stage;
}

private function frame(evt:Event):void {
for (var i:int = 0; i < listeners.length; i++) {
if (listeners[i] is HoldListener && listeners[i].flag) {
listeners[i].handler.call();
}
}
}

/**
 * Add event listener for a single key using a keycode.
 * @paramkeyCode Key code of the key.
 * @paramhandlerDown Function to be called when the key is pressed down.
 * @paramhandlerUp Function to be called when the key is released.
 * @paramalt Used in combination with the alt key.
 * @paramctrl Used in combination with the ctrl key.
 * @paramshift Used in combination with the shift key.
 */

public function addListener(keyCode:int, handlerDown:Function = null, handlerUp:Function = null, alt:Boolean = false, ctrl:Boolean = false, shift:Boolean = false):void {
listeners.push(new KeyListener(keyCode, handlerDown, handlerUp, alt, ctrl, shift));
}

/**
 * Add hold event listener for a single key using a keycode.
 * @paramkeyCode Key code of the key.
 * @paramhandler Function to execute while the key is held every frame.
 */

public function addHoldListener(keyCode:int, handler:Function):void {
listeners.push(new HoldListener(keyCode, handler, false));
}

/**
 * Add event listener for a single key using key string value.
 * @paramkeyName String name of the key.
 * @paramhandlerDown Function to be called when the key is pressed down.
 * @paramhandlerUp Function to be called when the key is released.
 * @paramalt Used in combination with the alt key.
 * @paramctrl Used in combination with the ctrl key.
 * @paramshift Used in combination with the shift key.
 */

public function addEasyListener(keyName:String, handlerDown:Function = null, handlerUp:Function = null, alt:Boolean = false, ctrl:Boolean = false, shift:Boolean = false):void {
var code:int = -1;
for (var i:int = 0; i < keyLabels.length; i++) {
if (keyLabels[i] == keyName) {
code = i;
break;
}
}
if (code == -1) {
throw new Error('Incorrect key string value specified - no "' + keyName + '" key found.');
return;
}
addListener(code, handlerDown, handlerUp, alt, ctrl, shift);
}

private function kDown(evt:KeyboardEvent):void {
for (var i:int = 0; i < listeners.length; i++) {
if (evt.keyCode == listeners[i].keyCode && listeners[i] is KeyListener && evt.altKey == listeners[i].alt && evt.ctrlKey == listeners[i].ctrl && evt.shiftKey == listeners[i].shift) {
if (listeners[i].handlerD) listeners[i].handlerD.call();
}
if (evt.keyCode == listeners[i].keyCode && listeners[i] is HoldListener) {
listeners[i].flag = true;
}
}
}

private function kUp(evt:KeyboardEvent):void {
for (var i:int = 0; i < listeners.length; i++) {
if (evt.keyCode == listeners[i].keyCode && listeners[i] is KeyListener && evt.altKey == listeners[i].alt && evt.ctrlKey == listeners[i].ctrl && evt.shiftKey == listeners[i].shift) {
if (listeners[i].handlerU) listeners[i].handlerU.call();
}
if (evt.keyCode == listeners[i].keyCode && listeners[i] is HoldListener) {
listeners[i].flag = false;
}
}
}

}

}

Now in main.as you can use this code to test out the new feature:

keyboard = new EasyKeyboard(stage);
keyboard.addHoldListener(65, function() { trace("A is being held!"); } );

This type of event listening is often used in games, when a character needs to be moved on the screen as long as a key is held.

Thanks for reading!

No comments:

Post a Comment