Here is how I did it:
In my case I have eight keys to map. First you need to make a button animation to go in your options menu. Draw an array of buttons with labels on them for what they are. This is one frame of the animation. Then copy this frame multiple times, so that you have one frame for each button, plus one more frame. The first frame leave as it is. For all the other frames, modify one button so it looks pressed. Make sure these go in a logical order, starting with the top-left button and moving across to the right, moving back to the left and dropping down a line when you get to the end, just as you would write. In my case the buttons also have a slot to put a text which will say what key that function is currently assigned to. As an example I have included the first two frames of my animation below.
Create an actor for these buttons, in my case called 'Controls'. DO NOT receive events when out of vision - unless you want to.
Create a variable to hold the stored key information. Make it an integer, array of size one more than the number of buttons. Put it in a save group so the user doesn't have to always chose the controls. In my case I have cntrl[9] (Global, Integer, save in CONFIG)
Because the array has nine slots they will be numbered 0-8. This corresponds to the frame numbers of Controls. The zero slot is used to save wether the saved file exists, for when the game loads.
For accessing the controls, create some constants. Put these statements somewhere in Global Code. Mine looked like this:
- Code: Select all
// for controlsav
#define JSET 1
#define USET 2
#define SSET 3
#define PSET 4
#define LSET 5
#define DSET 6
#define RSET 7
#define MSET 8
Now you will need two functions for remapping the keys. Add this somewhere in Global Code:
- Code: Select all
////////// KeyFuncts //////////
//use this to assign to the configured keys.
void setKeys()
{
//this bit sets the keys to something completely different, to avoid confusion.
remapKey(KEY_c, 404);
remapKey(KEY_UP, 404);
remapKey(KEY_x, 404);
remapKey(KEY_p, 404);
remapKey(KEY_LEFT, 404);
remapKey(KEY_DOWN, 404);
remapKey(KEY_RIGHT, 404);
remapKey(KEY_m, 404);
//this bit remaps the functions to the configured keys.
remapKey(cntrl[JSET], KEY_c);
remapKey(cntrl[USET], KEY_UP);
remapKey(cntrl[SSET], KEY_x);
remapKey(cntrl[PSET], KEY_p);
remapKey(cntrl[LSET], KEY_LEFT);
remapKey(cntrl[DSET], KEY_DOWN);
remapKey(cntrl[RSET], KEY_RIGHT);
remapKey(cntrl[MSET], KEY_m);
}
//use this to reset all the keys to their normal position.
void resetKeys()
{
int i;
for (i = 0; i < 439; i ++)
{
remapKey(i, i);
}
}
Now you have to do something with the Controls actor. Put this on Create Actor Event
- Code: Select all
ChangeAnimationDirection("Event Actor", STOPPED);
CollisionState("Event Actor", DISABLE);
EventDisable("Event Actor", EVENTALL);
//check if file exists
cntrl[0] = 0;
loadVars("conf.shd", "CONFIG");//load file: change to your location and save group
if (cntrl[0] == 0)//if the file doesn't exist, enter default values for controls.
{
cntrl[JSET] = KEY_c;
cntrl[USET] = KEY_UP;
cntrl[SSET] = KEY_x;
cntrl[PSET] = KEY_p;
cntrl[LSET] = KEY_LEFT;
cntrl[DSET] = KEY_DOWN;
cntrl[RSET] = KEY_RIGHT;
cntrl[MSET] = KEY_m;
}
setKeys();
Create a global integer to stor which key is being changed. I called it 'assign'.
In Draw Actor for Controls, put
- Code: Select all
animpos = assign;
This makes it display the appropriate depressed button.
Add a Key Down event, any key:
- Code: Select all
if (assign)//if we are waiting to assign a key.
{
cntrl[assign] = getLastKey();//set the desired control
assign = 0;//stop assigning
}
Now the fun part - Mouse Button down (left button) You will need to change some of these numbers based on the size of your buttons.
- Code: Select all
//basically, this bit is to find which button was clicked, based on the mouse's x and y coordinates.
char pos;
screen_to_actor(&xmouse, &ymouse); xmouse += 268; ymouse += 107;
pos = (int)(xmouse / 134.5) + (4 * (int)(ymouse / 105.5)) + 1;
if (pos == assign)//if you clicked an already depressed button, deselect it.
{
assign = 0;
}
else//otherwise, select it
{
assign = pos;
}
You will need to use resetKeys() when you open the controls menu and when you want to type anything. Otherwise, things will be confused. When you want to use the controls again, use setKeys.
To make the button display the currently assigned key, create a text actor, not repeating events when out of vision, and on Draw Actor use strcpy to set text to the desired key. In my case I made each button have a separate actor, but you could just clone an array of them. Then you'd use:
- Code: Select all
strcpy(text, getKeyText(cntrl[cloneindex + 1]));
I hope that helps and that I didn't forget anything. If you have any problems, just ask. Just try to understand most of what's happening, or at least the concept, and that way you'll learn, and be able to think for yourself in future. I've tried to comment the code a fair bit, but if you have questions, then ask.