Log in
Please log in or register.
Pages: [1]
  Print  
Author Topic: TUTORIAL : Multiple Configurable Keys Support  (Read 2382 times)
lechuckgl
Jr. Member
**
Posts: 77


View Profile
« on: Wed, Jun 17, 2009 »

Well, I couldn not restrain myself..and while I should have been working, I did this: multiple keys support, configurable as you wish.

First of all, add these 2 new classes:

Code:
package com.adamatomic.flixel
{

public class FlxKeyControl
{
private var KEYS:Array = new Array();//array of keys

public var unknownKeyCallback:Function = null;



public function AddKey(keyCode:int, keyName:String):void
{
KEYS.push( new FlxKey(keyCode, keyName));
}

public function ResetKeys():void
{
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
k.kPressed = 0;
}
}

public function Pressed(name:String):Boolean
{
//look for key
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
if ( k.kName == name)
return k.kPressed > 0;
}
return false;//key does not exists
}

public function JustPressed(name:String):Boolean
{
//look for key
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
if ( k.kName == name)
return k.kPressed == 2;
}
return false;//key does not exists
}

public function JustReleased(name:String):Boolean
{
//look for key
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
if ( k.kName == name)
return k.kPressed == -1;
}
return false;//key does not exists
}

//-------
//mimic flixel key logic !


public function PressKey(code:int):void
{
var notFound:Boolean = true;//I will use this in the next release !!!

//look for key
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
if ( k.kCode == code)
{
notFound = false;
//found !
if(k.kPressed > 0)
k.kPressed = 1;
else
k.kPressed = 2;
}
}


if (unknownKeyCallback != null && notFound)
{
//unknown key and callbackfuncion ( maybe for a config screen )
unknownKeyCallback(code);
}


}


public function ReleaseKey(code:int):void
{

//look for key
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
if ( k.kCode == code)
{
//found !
if(k.kPressed > 0)
k.kPressed = -1;
else
k.kPressed = 0;
}
}


}

public function UpdateKeys():void
{
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;

if ( (k.kOldValue == -1) && (k.kPressed == -1))
k.kPressed = 0;
else if ( (k.kOldValue == 2) && (k.kPressed == 2))
k.kPressed = 1;

k.kOldValue = k.kPressed;
}

}

//-----------


}

}

Code:
package com.adamatomic.flixel
{

public class FlxKey
{
public var kCode:int;//key code
public var kPressed:int;//was pressed ?
public var kOldValue:int;//Flixel stuff...
public var kName:String;//name your key, ex: "PLAYER1_UP"

//CONSTRUCTOR
public function FlxKey(code:int, name:String)
{
kCode = code;
kName = name;

}

}

}

Make sure to add them in the flixel folder and name the files FlxKeyControl.as and FlxKey.as.

Then, open FlxG.as and:

1)Add the following attribute
Code:
static private var KEYCONTROL:FlxKeyControl = new FlxKeyControl();
and method:
Code:
static public function AddKey(keyCode:int, keyName:String):void { KEYCONTROL.AddKey(keyCode, keyName);}

2)Replace the following methods:

Code:
static public function resetKeys():void { KEYCONTROL.ResetKeys(); }
static public function setUnknownCallback(callBackFunction:Function):void { KEYCONTROL.unknownKeyCallback = callBackFunction; }
static public function unsetUnknownCallback():void { KEYCONTROL.unknownKeyCallback = null; }
static public function pressed(KeyName:String):Boolean { return KEYCONTROL.Pressed(KeyName); }
static public function justPressed(KeyName:String):Boolean { return KEYCONTROL.JustPressed(KeyName); }
static public function justReleased(KeyName:String):Boolean { return KEYCONTROL.JustReleased(KeyName); }

and

Code:
//@desc This function is only used by the FlxGame class to do important internal management stuff
static internal function pressKey(k:int):void
{
KEYCONTROL.PressKey(k);
}

//@desc This function is only used by the FlxGame class to do important internal management stuff
static internal function releaseKey(k:int):void
{
KEYCONTROL.ReleaseKey(k);
}

//@desc This function is only used by the FlxGame class to do important internal management stuff
static internal function updateKeys():void
{

KEYCONTROL.UpdateKeys();

//mouse handle untouched !
mouse.x = state.mouseX-scroll.x;
mouse.y = state.mouseY-scroll.y;
}

_keys and _oldKeys are not longer necessary, comment them or errase them


Now, open FlxGame.as and replace:

Code:
//@desc This function is only used by the FlxGame class to do important internal management stuff
private function onKeyUp(event:KeyboardEvent):void
{
var code:String = String.fromCharCode(event.charCode);

FlxG.releaseKey(event.keyCode);

//WATCH OUT SETTING THIS KEYS !!!
if ((code == '0') || (code == ')')) {
    FlxG.setMute(!FlxG.getMute());
    showSoundTray();
    } else if ((code == '-') || (code == '_')) {
    FlxG.setMute(false);
    FlxG.setMasterVolume(FlxG.getMasterVolume() - 0.1);
    showSoundTray();
    } else if ((code == '+') || (code == '=')) {
    FlxG.setMute(false);
    FlxG.setMasterVolume(FlxG.getMasterVolume() + 0.1);
    showSoundTray();
    } else if ((code == '1') || (code == '!') || (code == '~') || (code == '`')) {
    toggleConsole();
    }
}

//@desc This function is only used by the FlxGame class to do important internal management stuff
private function onKeyDown(event:KeyboardEvent):void
{
var code:String = String.fromCharCode(event.charCode);
FlxG.pressKey(event.keyCode);
}


And finally comment FlxG.releaseKey(6); and FlxG.pressKey(6); inside onMouseUp and onMouseDown


To use this is pretty simple:

In the state constructor add a line:

FlxG.AddKey(KeyCode, KeyName);

where KeyCode is the key code number (d'uh  Roll Eyes ) and KeyName is any name you want for that key.

To check, use
pressed(KeyName), justPressed(KeyName) or justReleased(KeyName) as you wuold normally do...but now you use the name you setted for the key instead of a Flixel constant ( remember to save those names somewhere ).

Only problem: you loose kUp, kDown, kA, etc. etc. etc...but you can add as many keys as you want ( uhm, I think I'll have to add some security to avoid binding to Flixel function keys as +,-, etc. ).
Mouse support is "almost" untouched: you can no longer use pressed,justPressed or justReleased...but you still can use kMouse

You can test it here:

http://www.swfcabin.com/open/1245247090

Try any letter on my nickname Smiley


Hope I didn't miss anything. Yell me if I did  Cool


Oh, I almost forgot: what setUnknownCallback used for ? Set a callback function using this method, then, when an unknown keyis press, this function will be called, recieving the unknown's key code. Use it for a config screen. I still haven't tested it, but I think it should work.

I don't have to tell you what unsetUnknownCallback  does....  Grin
« Last Edit: Wed, Jun 17, 2009 by lechuckgl » Logged
lechuckgl
Jr. Member
**
Posts: 77


View Profile
« Reply #1 on: Thu, Jun 18, 2009 »

See it working: http://www.swfcabin.com/open/1245339135


I forgot something important I added just a minute ago: changing keys !

Add this in FlxKeyControl

Code:
public function ChangeKey(keyName:String, keyCode:int)
{
for (var i:uint = 0; i < KEYS.length; i++)
{
var k:FlxKey;
k = KEYS[i] as FlxKey;
if ( k.kName == keyName)
k.kCode = keyCode;
}
}

and this in FlxG

Code:
static public function ChangeKey(keyName:String, keyCode:int):void { KEYCONTROL.ChangeKey(keyName,keyCode );}

I don't think errasing key should be implemented...but at this point you should be able to do it yourseves if you want it   Grin

Here is an example:

Code:
package test
{
import com.adamatomic.flixel.FlxArray;
import com.adamatomic.flixel.FlxButton;
import com.adamatomic.flixel.FlxG;
import com.adamatomic.flixel.FlxSprite;
import com.adamatomic.flixel.FlxState;
import com.adamatomic.flixel.FlxText;

public class TestMenu extends FlxState
{
[Embed(source="../data/cursor.png")] private var ImgCursor:Class;
[Embed(source="../data/menu_hit.mp3")] private var SndHit:Class;

private var _t1:FlxText;

override public function TestMenu():void
{

this.add(new FlxText(FlxG.width/2-100,FlxG.height/2,200,80,"lechuckGL",0x3a5c39,null,32)) as FlxText;
FlxG.AddKey(76, "key1");
FlxG.setCursor(ImgCursor);
this.add(new FlxButton(102, FlxG.height / 3 + 138, new FlxSprite(null, 0, 0, false, false, 104, 15, 0xfff0147FA), onButton, new FlxSprite(null, 0, 0, false, false, 104, 15, 0xfff003EFF), new FlxText(25, 1, 100, 10, "CLICK HERE", 0xFFB90F), new FlxText(25, 1, 100, 10, "CONFIG", 0xFFD700))) as FlxButton;

_t1 = this.add(new FlxText(FlxG.width/2-50, FlxG.height / 2 + 30, 100, 80, "Press New Key", 0xf0147FA, null, 7)) as FlxText;
_t1.visible = false;
}

private function configKey( keyCode:int):void
{
FlxG.ChangeKey("key1", keyCode);
FlxG.unsetUnknownKeyCallback();
_t1.visible = false;
}

override public function update():void
{

if (FlxG.justPressed("key1")  )
{
FlxG.flash(Math.random()*40-20, 0.5);
FlxG.play(SndHit);
}
super.update();
}


private function onButton():void
{
FlxG.setUnknownKeyCallback(configKey);
_t1.visible = true;
}

}
}

Oh, I changed setUnknownCallback and unsetUnknownCallback to setUnknownKeyCallback and unsetUnknownKeyCallback , to avoid any confusions.
« Last Edit: Thu, Jun 18, 2009 by lechuckgl » Logged
PhantomTollbooth
Newbie
*
Posts: 15


View Profile
« Reply #2 on: Fri, Jun 19, 2009 »

Truly awesome... this is getting tacked onto my code sometime this weekend. This earns at least five points!
Logged
Adam Atomic
Administrator
Hero Member
*****
Posts: 724


hostest w/ the mostest


View Profile WWW
« Reply #3 on: Fri, Jun 19, 2009 »

added to help thread Smiley
Logged

joem
Newbie
*
Posts: 7


View Profile
« Reply #4 on: Sat, Jun 20, 2009 »

Wicked awesome! I did some stuff with keys before, but this totally destroys it.
Logged
Mr Dumle
Newbie
*
Posts: 16


View Profile
« Reply #5 on: Fri, Aug 7, 2009 »

Works like a charm! Thanks! You missed the function return type on that last one though.
Logged
Zielak
Newbie
*
Posts: 1


View Profile
« Reply #6 on: Sat, Sep 5, 2009 »

Great work (: I hope to create some kind of input box in the near future using this class.
Logged
Pages: [1]
  Print  
 
Jump to: