Windows How to check if keys are pressed in a sequence?

K

kingjohnc19

Guest
I want to make a cheat code that would increase the player's size. I tried doing this, but it didn't work. How could I make it work?
Code:
if (up_key) {
    if (up_key) {
        if (down_key) {
        if (down_key) {
        if (left_key) {
            if (right_key) {
                if (left_key) {
                    if (right_key) {
                        if (keyboard_check_pressed(ord("B"))) {
                            if (keyboard_check_pressed(ord("A"))) {
                                image_xscale += 20;
                                image_yscale += 20;
                               
                            }
                        }
                    }
                }
            }
        }
        }
        }
    }
}
 

Homunculus

Member
I don't want to sound harsh but... did you just randomly put some if conditions together and hope it somehow worked out?

More importantly, do you expect the cheat code to work when all of the required keys are pressed at the same time, or in a sequence (meaning, one after the other, like typing some text)? Seeing the number of required keys I'd say the latter is the only possible solution, keyboard have a limit to how many keys can be detected as being pressed at the same time. This kind of solution can not be checked in a single step, you'll have to keep track of the keys between multiple steps (possibly within time limit?)
 
K

kingjohnc19

Guest
I don't want to sound harsh but... did you just randomly put some if conditions together and hope it somehow worked out?

More importantly, do you expect the cheat code to work when all of the required keys are pressed at the same time, or in a sequence (meaning, one after the other, like typing some text)? Seeing the number of required keys I'd say the latter is the only possible solution, keyboard have a limit to how many keys can be detected as being pressed at the same time. This kind of solution can not be checked in a single step, you'll have to keep track of the keys between multiple steps (possibly within time limit?)
yeah, i basically just did what you said. I knew it wasn't going to work, but I tried it out anyways. how would i make a time limit for the keys? I'm pretty new to gamemaker, so I don't really know how to do that much.
 

Homunculus

Member
I can think of a few ways to approach this, none of them strikes me as particularly simple if you are a beginner.

I could try to come up with some code later if you want, but one approach could be:

- store the sequence of required keys for the cheat in an array
- keep a variable holding the position in the array of how much of the cheat code has been uninterruptdedly entered so far, starting at 0.
- check if vk_anykey has been pressed in the step event, and try to match keyboard_lastley to the current position in the array. If matched, increment the index, otherwise start over from position 0.
- if all of the code has been matched, apply the cheat and reset to 0

You could throw an alarm in there to make the cheat sequence invalid if too much time has passed since the last key.

Maybe there are simpler solutions, but I can’t think of any right now.
 
Last edited:
I'm going off of the top of my head here, so bare that in mind....(I will post it for now, and check whether it's sound as an actual process later)

I would look at doing this:

Set the cheat code as a string. Like this "ABEFG etc etc" Store a variable that contains the length of this string

Set an alarm for when the player starts entering the cheat code, and set a second string to nothing

This next step is probably a bit long winded, but do a switch statement with A to Z
switch (keyboard_key)
{case A: add A to second string; break;
case B: add B to second string; break;
etc etc
case Z: add Z to second string; break;}

(not quite sure how you could do the keyboard check in a switch statement, and it might come down to a repeated block of "if keyboard_check(ord('A')) add A to string" etc)

Each time the new key is added to the end of the second string

Test length of this second string after each key press - if its the same as the first, then compare the two strings. Because this length element is controlling the process it would mean that the player can't enter a wrong code, other than the content. As soon as the second string matches the length it will test it.

if string_1 == string_2 is a comparison that can be proven true with a string

If they match in length, content, and the alarm hasn't yet counted down - the cheat has been successfully entered, and gets activated.

If the alarm counts down before the length of the second string matches the first, then the process is reset.
 
Last edited:
If your cheat code is allowed to be a bunch of letters (and not arrow keys), this can be a LOT simpler.

'keyboard_string' is your friend :)

Try something like:
  • Whenever you press enter (in cheat mode), the system checks the keyboard string.
  • It needs to parse through each character, so if you're not comfortable with that, you'll want to look up a tutorial on string manipulation. But essentially, you're just looping through each character, seeing if it matches the first character in your sequence. If it does, you read the next character, and if it's the second character in the sequence, you keep going until it's a complete match.
  • Once you've got a match, they're an official cheater.
This is how I handle all of my debugging events. Whenever I press "~" in-game, it checks the keyboard string for saved terms. If I write in, say, "fullscreen" and press tilde, it goes into fullscreen :D
 

Homunculus

Member
@SupernaturalCow in this scenario just using string_pos and checking for a result that is > 0 would be enough, no need to loop through each character.

I agree though, having only letters simplifies the problem a lot.
 
@Catan Yeah, either works. The up-side of checking the string is that you don't have to run the check every single key press - just when you press enter or whatever.
 
Dunno about the other suggestions, but I'll post my final crack at this....

create event
Code:
cheat_string = "abcdefghi"; // obviously can be whatever you want, but it seems that (as is) you will have to stick to lower case for letters
cur_string = undefined;
cheat_string_length = string_length(cheat_string);
is_the_same = false;
the event where you test this:
Code:
if keyboard_check_released(vk_anykey) // see's if any key (at all) is being released - note that it is not checking for any particular key, just that a release has been registered
{if cur_string == undefined
{cur_string = keyboard_lastchar}
else
{cur_string = string(cur_string) + keyboard_lastchar;
if string_length(cur_string) == cheat_string_length
{if cur_string == cheat_string
{is_the_same = true;}
else
{is_the_same = false;
cur_string = undefined;}}}}
That isn't everything, at least in the sense that I'll leave it up to you to figure out when (and how) this code is run, if you want one alarm for the whole process, or per key entry.

Basically it is:
1)
Setting the variable 'cheat _string' (a string that will be compared to later) in the create event

2)
Setting a second variable (cur_string) to undefined

3)
Setting 'cheat_string_length' to hold how many characters 'cheat_string' has

4)
Setting a variable 'is_the_same' to false (though this isn't really necessary, as you could just include what you want to happen in specific code blocks later)

5)
In the step event it see's if any key is pressed, and if cur_string is undefined.

If it is - it sets cur_string to a string of the last key pressed (keyboard_lastchar function)

If it's not undefined (a key press has already been added to it, and so the undefined value is not true anymore) then the string from keyboard_lastchar function is added onto the end.

The length of cur_string is then compared to the length of cheat_string.

If it is the same length, then the content of both strings is compared.

If they are both the same, then is_the_same is set to true (at this point you would end the alarm, and do whatever to show the cheat process has been successfully activated)

If it is not the same, then cur_string is set to undefined and the process can start again (reset the alarm timer etc)


So that this is all timed you would just have the alarm resetting a control variable (as you don't want a check for any key being pressed throughout ever step of your game)

start (whatever way you instigate this)
can_do_cheat = true;

event:
if can_do_cheat
{do above}

alarm:
can_do_cheat = false;
 
Actually, I just thought of a much simpler solution. No arrays, no alarms, no character iteration, and only a few limitations.

Code:
var _code_str = "KONAMI",  // This code must be all letters (doesn't have to be caps).
    _code_str_len = string_length(_code_str),
    ;
if keyboard_check_pressed(ord("I")) {  // This letter must be the last letter of your code.
    var _input_str = keyboard_string,
        _input_str_len = string_length(keyboard_string),
        _check_str = string_copy(_input_str, _input_str_len-_code_str_len, _code_str_len),
        ;
    if (_code_str == _check_str) {
        image_xscale += 20;
        image_yscale += 20;
        power_level = 9000.1;
        keyboard_string = "";  // May as well clear the string now.
    }
}
Now, don't get me wrong, @Catan 's solution is much more future-proof and has better longevity in a bigger project, but if you just want to get a simple solution up and running, this is going to do just that.

EDIT: I didn't see @the_dude_abides post until after I posted this. That works too.
 
Top