Re-define the keys.

Started by RetroJay, Thu 20/11/2014 05:30:09

Previous topic - Next topic

RetroJay

Hi all.

I hope someone can help me out here.
I have been scouring the forums and searching for a solution but, alas, have not found the answer.

The game I am working on is all controlled with the keyboard, I am using the built in 'KeyboardMovement' Module, AGS 3.2.1.
Everything is going well... However...

I would love for the player to be able to re-define the controls.
The keys that I would like for them to be able to change are the movement keys, these are set on the arrow keys, at the moment.
Also Examine and Use inventory item, I have these set on A and Z, for now.

Is there a way of accomplishing what I would like to do?
If anyone could give me a few pointers, it would be much appreciated.

Yours.
Jay.

Crimson Wizard

#1
Step One.

Make a variable of type eKeyCode per each control key.
Init them with default keys (arrows).
In on_key_press check for these variables instead of key constants.

Example:
Code: ags

eKeyCode KeyMoveUp;
eKeyCode KeyMoveDown;
eKeyCode KeyMoveLeft;
eKeyCode KeyMoveRight;

function game_start()
{
    KeyMoveUp = eKeyUpArrow;
    KeyMoveDown = eKeyDownArrow;
    KeyMoveLeft = eKeyLeftArrow;
    KeyMoveRight = eKeyRightArrow;
}

function on_key_press(eKeyCode keycode)
{
    <...>
    if (keycode == KeyMoveUp)
        ... move up
    else if (keycode == KeyMoveDown)
        ... move down
    etc
    <...>
}


Step Two.

I guess there are many different ways to implement keys setup, but the most primitive is to let player press them all in the order.
In the sake of experiment, make a GUI with a label, and print something like "Press a key for 'Left'" on the label, scan player's key press, then move to the next key until all keys are recorded.


Example:
Code: ags

int KeySetupStep;

void NextKeySetupStep()
{
    KeySetupStep++;

    if (KeySetupStep > 4)
    {
        // all keys were recorded
        gKeySetupGUI.Visible = false;
        return;
    }

    String hint = "Press a key for ";
    String cmd_name;
    if (KeySetupStep == 1)
        cmd_name = "Up";
    else if (KeySetupStep == 2)
        cmd_name = "Down";

    // other keys

    lblKeySetupHint.Text = hint.Append(cmd_name);
}

void StartKeySetup()
{
    gKeySetupGUI.Visible = true;
    KeySetupStep = 0;
    NextKeySetupStep();
}

void RecordSetupKey(eKeyCode keycode)
{
    if (KeySetupStep == 1)
        KeyMoveUp = keycode;
    else if (KeySetupStep == 2)
        KeyMoveDown = keycode;

    // other keys

    NextKeySetupStep();
}

function on_key_press(eKeyCode keycode)
{
    if (gKeySetupGUI.Visible)
    {
        RecordSetupKey(keycode);
        return; // do not do anything else this time
    }
    <... other code...>
}

// Start key setup by pressing some button in the menu
function DoKeySetupButton_OnClick(GUIControl *control, MouseButton button)
{
    StartKeySetup();
}


These are quick samples, the code may be organized differently. For instance, you may want to make an array of keys, instead of separate variables, and address elements of this array with integer constants (created as enum, or #define); also put key names in array too.
But this will give you some start.

RetroJay

Hi Crimson Wizard.

That looks... interesting.:P
I will definitely try this out, tonight.

Looking at your script I assume that all of this will be scripted within 'Global Script', yes?
I will let you know how thing go.

Thank you for your time.

Yours.
Jay.


RetroJay

#3
Hi Crimson Wizard.

I decided to attempt your code and...
I seem to be having problems with this section of script, from your first piece of code. ???
When I tried this I did set all of my keys up.

Code: ags
function on_key_press(eKeyCode keycode)
{
   <...>
if (keycode == KeyMoveUp)
    ... move up
else if (keycode == KeyMoveDown)
    ... move down
    etc
    <...>
}



Where you have '... move up/down'. Am I supposed to put more lines of code there?
If so, then what? :-[ :-[ :-[

without this section my game plays and when I press the R key to redefine keys my GUI shows and asks me to press buttons for Up, Down, Left and Right.
Then the GUI closes and my game starts but the keys I have selected do nothing, the arrow keys still control my character.

Edit:-
I though that I would show you how my 'On_Key_Press' script is, at the moment.
Code: ags
function on_key_press(eKeyCode keycode) {
  // called when a key is pressed. keycode holds the key's ASCII code.

  if (gKeySetupGUI.Visible) {
    RecordSetupKey(keycode);
    return; // do not do anything else this time
  }


  // THE S KEY (START GAME - FROM OPTION SCREEN).
  // --------------------------------------------
  if (IsKeyPressed(eKeyS) && gMansion_Map.Visible == false && gQuit_Dialog.Visible == false) {
    if (cDan.Room == 2){
      ResetRoom(3);
      ResetRoom(4);
      cDan.ChangeRoom(3, 624, 400, eDirectionLeft); // Pressing the S key starts game from the Options Screen.
    }
  }


  // THE L KEY (RESTORE CHECKPOINT).
  //--------------------------------
  if (IsKeyPressed(eKeyL) && gMansion_Map.Visible == false && gQuit_Dialog.Visible == false) {
    RestoreCheckpoint(); // Pressing the L key restores the Saved Checkpoint.
  }


  // THE Q KEY (SHOWS THE QUIT DIALOG) AND PRESSING KEYS Y=YES AND N=NO.
  //--------------------------------------------------------------------
  if (IsKeyPressed(eKeyQ) && gMansion_Map.Visible == false) {
    gQuit_Dialog.Visible = true;
  }
  
  if (gQuit_Dialog.Visible == true) {
    if (cDan.Room == 2) {
      if (IsKeyPressed(eKeyY)) {
        QuitGame(0);
      }
    }
  }
  
  if (gQuit_Dialog.Visible == true) {
    if (cDan.Room == 2) {
      if (IsKeyPressed(eKeyN)) {
        gQuit_Dialog.Visible = false;
      }
    }
  }
  
  if (gQuit_Dialog.Visible == true) {
    if (cDan.Room == 3 || cDan.Room == 4) {
      if (IsKeyPressed(eKeyY)) {
        RestartGame();
      }
    }
  }
  
  if (gQuit_Dialog.Visible == true) {
    if (cDan.Room == 3 || cDan.Room == 4) {
      if (IsKeyPressed(eKeyN)) {
        gQuit_Dialog.Visible = false;
      }
    }
  }
  
  
  // THE R KEY (REDIFINE PLAYING KEYS).
  //-----------------------------------
  if (IsKeyPressed(eKeyR) && gMansion_Map.Visible == false && gQuit_Dialog.Visible == false) {
    StartKeySetup();
  }
  

  // THE P KEY (MANSION PLANS).
  //---------------------------
  if (keycode == eKeyP) { // Pressing the P key (in game) show the Mansion Plans Screen.
    if (gQuit_Dialog.Visible == false) {
      if (gMansion_Map.Visible == true) gMansion_Map.Visible = false;
      else gMansion_Map.Visible = true;
      if (gInventory.Visible == true) gInventory.Visible = false;
      else gInventory.Visible = true;
      if (cDan.Room == 2) { // However, If the P key is pressed on the Options Screen...
        gMansion_Map.Visible = false; // The Mansion Plans are not shown...
        gInventory.Visible = false; // Neither is the Inventory Screen.
      }
    }
  }
  

  // THE M KEY (STOP OR START MUSIC).
  //---------------------------------
  if (IsKeyPressed(eKeyM)) {
    if (Game.IsAudioPlaying(eAudioTypeMusic)) {
      aThe_Builder.Stop();
    }
    else {
      if (IsKeyPressed(eKeyM)) {
        aThe_Builder.Play();
      }
    }
  }
    
  if (IsGamePaused()) keycode = 0; // game paused, so don't react to keypresses.
}  
// END OF 'ON_KEY_PRESS' SCRIPT.
// -----------------------------


Thank you for your help.

Yours.
Jay.

Crimson Wizard

#4
Quote from: RetroJay on Thu 20/11/2014 11:20:22
Where you have '... move up/down'. Am I supposed to put more lines of code there?
Yes, you are :)

Quote from: RetroJay on Thu 20/11/2014 11:20:22
If so, then what? :-[ :-[ :-[
You said you are using KeyboardMovement module. You may just edit the "on_key_press" code there, replacing the use of key constants with variables.
If you do, you will also have to move variable declaration to that module.


EDIT: BTW KeyboardMovement module alredy has all variables declared!
Code: ags

// keycodes as variables for future key customization functions (static variables?):
int KeyboardMovement_KeyDown = 380; // down arrow
int KeyboardMovement_KeyLeft = 375; // left arrow
int KeyboardMovement_KeyRight = 377; // right arrow
int KeyboardMovement_KeyUp = 372; // up arrow
int KeyboardMovement_KeyDownRight = 381; // PgDn (numpad)
int KeyboardMovement_KeyUpRight = 373; // PgUp (numpad)
int KeyboardMovement_KeyDownLeft = 379; // End (numpad)
int KeyboardMovement_KeyUpLeft = 371; // Home (numpad)
int KeyboardMovement_KeyStop = 376; // 5 (numpad)


Just use these.

RetroJay

Hi Crimson Wizard.

I really do appreciate your help on this matter...However.
This, I'm afraid, has beaten me.>:(

I haven't got a clue what I'm doing nor do I understand what you are talking about.(sorry to be so dim).(laugh)
People will just have to use the keys I tell them to and like it.;)

Yours.
Jay.

Crimson Wizard

#6
RetroJay, you give up way too early!!

As I wrote above, KeyboardMovement module already has everything set up.
All you need is to export its key variables and use them in your redefine code, which, as you said, is already working.

in KeyboardMovement.ash:
Code: ags

import int KeyboardMovement_KeyDown;
import int KeyboardMovement_KeyLeft;
import int KeyboardMovement_KeyRight;
import int KeyboardMovement_KeyUp;
import int KeyboardMovement_KeyDownRight;
import int KeyboardMovement_KeyUpRight;
import int KeyboardMovement_KeyDownLeft;
import int KeyboardMovement_KeyUpLeft;
import int KeyboardMovement_KeyStop;

in KeyboardMovement.asc, beyond line 35:
Code: ags

export KeyboardMovement_KeyDown;
export KeyboardMovement_KeyLeft;
export KeyboardMovement_KeyRight;
export KeyboardMovement_KeyUp;
export KeyboardMovement_KeyDownRight;
export KeyboardMovement_KeyUpRight;
export KeyboardMovement_KeyDownLeft;
export KeyboardMovement_KeyUpLeft;
export KeyboardMovement_KeyStop;


In GlobalScript, where you redefine keys, use the variables from KeyboardMovement module:
Code: ags

void RecordSetupKey(eKeyCode keycode)
{
    if (KeySetupStep == 1)
        KeyboardMovement_KeyUp = keycode;
    else if (KeySetupStep == 2)
        KeyboardMovement_KeyDown = keycode;
    ... etc
    // other keys
 
    NextKeySetupStep();
}

RetroJay

Hi Crimson Wizard.

Ha...Haa!

I see it all now, some of it.
That works like a charm.;-D

Thank you ever so much for your help and patience.(roll)
I really do appreciate it.

All I want to do now is see if I can find a way of excluding some keys, Menu Keys, from being re-definable.
I will have a play and see if I can work that out myself before I trouble you again for your expertise.;)

Yours.
Jay.


Vincent

I'm out of topic here
But this Module is just AMAZING

http://www.adventuregamestudio.co.uk/forums/index.php?topic=42843.msg568552#msg568552


Quote from: Khris on Thu 10/02/2011 20:51:43
Key binding commands

KeyboardMovement.SetKey(eKMKey key, eKeyCode k);
Assigns ASCII code k to movement key key.
Example:  KeyboardMovement.SetKey(eKMKeyLeft, eKeyLeftArrow);


SMF spam blocked by CleanTalk