GameMaker: Studio

GameMaker: Studio

39 个评价
Guide to Cheat Codes (and Other Sequential Input)
由 M.S.T.O.P. 制作
This guide will teach you 3 methods to incorporate cheats codes and other types of sequential keyboard input into your game.
Note: Requires knowledge of GML.
   
奖励
收藏
已收藏
取消收藏
Dialog Prompt Method
Pros:
  • You can use any keyboard-typeable character in your codes
  • The player has a nice interface in which they can input the codes

Cons:
  • Can't use special keys (e.g. arrows keys) as part of codes
  • Not very discreet

This is probably the most foolproof way to input cheat codes. This method will bring up an input dialog using get_string_async, check the input against a code list and then do the desired effect if there is a match.

First, you need to decide which event will bring up the prompt. For this example, let's say the prompt appears whenever you click an object, so in that object's Left Pressed event, put in:

/// Prompt for code { my_id = get_string_async("What's the code?",""); }

Every asynchronous dialog will generate a data map assigned to the variable async_load containing the details of that particular dialog (i.e. the input string, whether OK was clicked or not). The variable my_id will store the dialog box's id number which will be used in the next step.

Next, in the object's Dialog event (it's grouped under Asynchronous), put in:

/// Check code { who = ds_map_find_value(async_load, "id"); // Who brought up the dialog? if (who == my_id) // Is it the code prompt? { if (ds_map_find_value(async_load, "status")) // Did the user click "OK"? { // Check input against each code if (ds_map_find_value(async_load, "result") == "cass") { // Do stuff here // Yay $250! } else if (ds_map_find_value(async_load, "result") == "iamacheat") { // Do other stuff here // Yay $500,000! } } } }

Put as many else if block as necessary, or consider using switch...case statements if the code list gets long.
Keyboard History Method
Pros:
  • You can use any keyboard-typeable character in your codes
  • The input method is hidden away from the player
  • Simple to code

Cons:
  • Can't use special keys (e.g. arrows keys) as part of codes
  • All codes must be the same length

This method uses the built-in variable keyboard_string, which keeps track of what has been typed while the game is in focus, to detect codes.

In an object's <any key> Event, put in:

/// Check for code { // Truncate keyboard_string to last 5 characters if necessary if (string_length(keyboard_string) > 5) keyboard_string = string_copy(keyboard_string, 2, 6); // check for codes if (keyboard_string == "12345") { //Do stuff // That's the stupidest combination I've ever heard in my life! // That's the kind of thing an idiot would have on his luggage! } else if (keyboard_string == "!@#$%") { // Do other stuff // Hey, do you kiss your mother with that mouth? } }

Put in more else if blocks (or cases if using switch...case) for more codes.

The truncation step ensures that keyboard_string only keeps the last n characters typed in history. So if your codes are 10 characters long, the lines would be:

// Truncate keyboard_string to last 10 characters if necessary if (string_length(keyboard_string) > 10) keyboard_string = string_copy(keyboard_string, 2, 11);

Or in general:

// Truncate keyboard_string to last n characters if necessary if (string_length(keyboard_string) > n) keyboard_string = string_copy(keyboard_string, 2, n+1);
Keycode Method
Pros:
  • You can use special keys (e.g. arrow keys) as part of codes
  • The input method is hidden away from the player

Cons:
  • Can't use characters that require modifier keys (e.g. "!", "%", "&")
  • Harder to code

This method uses keycodes to detect which keys have been hit. It uses stacks to keep track how far along the code sequence the player is and does stuff when the code is complete.

For this example, the two codes used will be two variations of the Konami code: Up, Up, Down, Down, Left, Right, Left, Right, B, A which will give 30 lives; and Up, Up, Down, Down, L, R, L, R, B, A which will give full power. Each code will have two stacks: a working copy stack that will be used to keep track of the code sequence and a master stack that will only be used to reset the working stack if the wrong sequence is entered.

In an object's Create event, put in the following:

/// Prepare code stacks { // Init stacks livesStack = ds_stack_create(); livesCopy = ds_stack_create(); powerStack = ds_stack_create(); powerCopy = ds_stack_create(); // Push keycodes into master stacks in reverse order ds_stack_push(livesStack,ord('A')); ds_stack_push(livesStack,ord('B')); ds_stack_push(livesStack,vk_right); ds_stack_push(livesStack,vk_left); ds_stack_push(livesStack,vk_right); ds_stack_push(livesStack,vk_left); ds_stack_push(livesStack,vk_down); ds_stack_push(livesStack,vk_down); ds_stack_push(livesStack,vk_up); ds_stack_push(livesStack,vk_up); ds_stack_push(powerStack,ord('A')); ds_stack_push(powerStack,ord('B')); ds_stack_push(powerStack,ord('R')); ds_stack_push(powerStack,ord('L')); ds_stack_push(powerStack,ord('R')); ds_stack_push(powerStack,ord('L')); ds_stack_push(powerStack,vk_down); ds_stack_push(powerStack,vk_down); ds_stack_push(powerStack,vk_up); ds_stack_push(powerStack,vk_up); // Copy master stacks to working stacks ds_stack_copy(livesCopy,livesStack); ds_stack_copy(powerCopy,powerStack); }

Remember that you have to push the keycodes in reverse order because that's how stacks work.

In the object's <any key> Event, put the following in:

/// Check for code { if (!ds_stack_empty(powerCopy)) // Is the working stack not empty? { if (keyboard_key == ds_stack_top(powerCopy)) // Is the last key pressed correct? { ds_stack_pop(powerCopy); // Pop the keycode off the working stack if (ds_stack_empty(powerCopy)) // Is the working stack empty? { // Code complete! // You get full power! // Optional: reset the working stack for multiple activations ds_stack_copy(powerCopy,powerStack); } } else // Oops, wrong key { // If not already done, reset the working stack by copying the master over it if (ds_stack_size(powerCopy) < ds_stack_size(powerStack)) ds_stack_copy(powerCopy,powerStack); } } // Now do the same thing for the other code if (!ds_stack_empty(livesCopy)) { if (keyboard_key == ds_stack_top(livesCopy)) { ds_stack_pop(livesCopy); if (ds_stack_empty(livesCopy)) { // Code complete! // You get 30 lives! ds_stack_copy(livesCopy,livesStack); } } else { if (ds_stack_size(livesCopy) < ds_stack_size(livesStack)) ds_stack_copy(livesCopy,livesStack); } } }

If you have a long list of codes, you should put the stacks into an array and then use a for loop to iterate through them.

You can also use queues instead of stacks, you would then need to queue the keycodes in normal order.
8 条留言
sarasimo 2024 年 8 月 27 日 上午 11:48 
Very helpful thanks. Found the stack method quite versatile
frumple 2017 年 2 月 15 日 下午 4:05 
Arrays start at 0.

Personally, i don't see the difference in shorter or longer code, and using stacks will not make much of a dent in memory usage. Putting either code in the step event is a bigger issue, and should be avoided. It will execute all the if checks every step, which would mean 60 or 30 checks per second. Better to use the key pressed event as that will not run every step.
Daniel 2017 年 2 月 2 日 上午 10:58 
Piemelmoes's code looks a lot cleaner and better, I never thought of using arrays like that, I've never actually used them in game maker at all, can you not simply write them like C++? code[12] = {vk_up, vk_up, vk_down.....}?Also, you are wasting code[0], or are arrays starting at 1 in game maker?
Dumb 2017 年 1 月 6 日 上午 12:11 
So could something like this be implemented for, say, special moves in a fighting game? Not sure how I'd be able to do this on a per-character basis.
TheouAegis 2016 年 7 月 11 日 下午 10:25 
I'm with Piemelmoes on this. It's easier and faster to just store all the inputs to an array and then just read through the array. Takes less memory as well, since you just need 1 array instead of 2 stacks.
Lan Party Rens 2014 年 8 月 24 日 上午 1:11 
In your ceate event, place this:

current_code=1
code[1]=vk_up
code[2]=vk_up
code[3]=vk_down
code[4]=vk_down
code[5]=vk_left
code[6]=vk_right
code[7]=vk_left
code[8]=vk_right
code[9]=mb_left
code[10]=mb_left
code[11]=mb_left

In your step event, place this:

if current_code<12
{
if keyboard_check_pressed(code[current_code])
{
current_code+=1
}
if mouse_check_button_pressed(code[current_code])
{
current_code+=1
}
}
if current_code=12
{
show_message("You've entered the code!") //Place any reward you want here
}
Lan Party Rens 2014 年 8 月 24 日 上午 1:02 
Dude, your keycode method is way too long. I've got an 11 keys long keycode done entirely with a third the size of your code. I'll post it here, one sec.
Wealthy Kabir 2014 年 4 月 14 日 上午 5:40 
It's a shame you cant do the konnami code with the arror keys. This guide helped me a lot, thanks.