Hey everyone. Today I’m going to share with you a simple, yet effective implementation of a Key Input Queue in RM2k/3, which is a basic data structure that is capable of storing the order in which keys are pressed. As a practical use for this Key Input Queue, I’ll be using it to show you how to create a cheat code system. (For example, press up, down, shift, enter, left, right in-game for max health.) As a prerequisite, all you really need is a little knowledge on key input processing. Sound interesting? Read on!
The data structure itself can be interpreted as a stream of numbers describing which keys were pressed. The right-most digit in this “string” of numbers is the most recently pressed key, the next digit to the left (the tens digit) would be the key pressed before that, and so on. For example, note the string “1511.” Remembering that 1 is the value of down and 5 is the value of enter, this queue translates to pressing
down, down, enter, down.
How do we store that value in a variable? The naive approach would be to have two variables: one for the key input, and one to store the queue. By multiplying the queue by ten and then adding to that queue what was stored into the key input variable, we could have a nice input queue.
Well, sort of. One problem with that is the issue of data limitations in RM2k/3. In RM2k3, your variables can only be a max of seven digits, so after only a few key presses, your queue variable will max out at 9,999,999. In RM2k the problem is even worse, because the max value for variables is only six digits.
The workaround is to use the modulus operator, and it’s a quite nice workaround because it gives us some control over the length of our queues. For example, say you really only needed to store the last two key presses in a two digit variable. If that’s the case, we can simply mod the queue by 100 before applying the multiplication and addition to the queue.
For now, we have a max length of seven digits (by using mod 1,000,000) for the queue using this little snippet of code in a parallel process event:
QUOTE:<> Key Input Processing [#0001: KeyPress] (Wait Until Key Pressed)
<> Variable Oper: [#0002: CheatQueue] Mod, 1000000
<> Variable Oper: [#0002: CheatQueue] *, 10
<> Variable Oper: [#0002: CheatQueue] +, Var[#0001]’s Value
<>
After getting the queue, you can compare it to any numbers you’d like. If a match is found, you can apply whatever cheats you’d like (max money, all items, all skills, infinite stamina, whatever). It would also be a good idea to reset the queue to zero and play a nifty sound effect as a confirmation that the user put in the correct code.
For most applications, a queue consisting of the last seven keys pressed will do the trick. By using standard keys* (Directions, Enter, Shift) we have 6^7 (over 250,000) different key combinations. As long as you avoid common queues as your cheat codes, your players probably aren’t going to accidentally enter a cheat code. Anything less might be pushing it, but that still doesn’t mean a few more keys added onto a second queue is out of the question.
*
I omitted the Escape/Cancel key because often this calls your menu, and your parallel process events can’t execute while you’re in the menu. While cheats can work in this situation still, it’s a little awkward closing the menu to apply codes because the cancel you used to close the menu won’t be added to the queue.
Adding a second variable to store an additional seven keys to the queue is not a bad idea. With it, you’d be given the possibility to have cheat codes up to 14 different key presses at once, which is now over 78,000,000 different key possibilities. That means, on average, you’re over 300,000 times as unlikely to accidentally enter a cheat code by randomly pressing keys. Even if you are feeling like being really spammy, and you can press ten keys a second in such a way that you won’t repeat a previous combination you’ve tried, it’d still take over eight hours to guess a good cheat code. How is it done? It’s actually not too bad.
We’ll divide the queue into two variables: an upper half and a lower half. Before we modify the lower half (which is just what we had before), we’ll store the last (most significant) digit in a temp value and add that to the upper half, making sure we follow the same rules for the upper half (mod 1,000,000* it and multiplying it by 10) before we add in that temp value.
*
Again, we can change this to a smaller value if we want a smaller queue
Here is our finalized code, which checks if
enter, shift, enter, shift, enter, shift, up, up, down, down, left, left, right, right is pressed, and if so, it gives the player maximum money:
QUOTE:<> Key Input Proc: [0001:KeyInput] (Wait ‘til Key Pressed)
<>Variable Oper: [0003:UpperHalfQueue] Mod, 1000000
<>Variable Oper: [0003:UpperHalfQueue] *, 10
<>Variable Oper: [0004:Temp] Set, [0002:LowerHalfQueue]’s value
<>Variable Oper: [0004:Temp] /, 1000000
<>Variable Oper: [0003:UpperHalfQueue] +, [0004:Temp]
<>Variable Oper: [0002:LowerHalfQueue] Mod, 1000000
<>Variable Oper: [0002:LowerHalfQueue] *, 10
<>Variable Oper: [0002:LowerHalfQueue] +, [0001:KeyInput]
<>Branch if Var [0002:LowerHalfQueue] is 4112233
<>Branch if Var [0003:UpperHalfQueue] is 5757574
<>Play Sound: chicken
<>Change Money: 999999 Add
<>Variable Oper: [0002-0003] Set, 0
<>
:End
<>
:End
<>
I admit, this is a bit long-winded. Fourteen different keys pressed typically isn’t something I wouldn’t memorize as a cheat code, unless it was at least somewhat easy to remember. So experiment and find that right balance that works well for you. (I think this advice can extend beyond gamemaking as well. :P) Have some fun with this one, and feel free to contact me if you have any questions.