+3 votes

Hello there!

Is there a simple way to handle consecutive keys, like for cheat codes ?

Thank you.

in Engine by (15 points)

I have never seen anything in the documentation to support that but it should be easy enough to build in theory. In your routine that processes input simply add a function to buffer the input

psudo code:
if input="a":
      bufferandcheck("a")
      do the rest

func bufferandcheck(char):
      buffer = buffer.substring(bufferlength-1) + char
      if buffer.contains("cheat"):
            Cheat()

Thanks mrLogan, that's a neat solution and it can easily handle multiple cheat codes.

Are there any tutorials or other resources where I can find a more detailed explanation of this bufferandcheck function–or the elements therein? Or would you mine explaining it in more detail?

I'm new to coding, and I'm working on a skateboard game. I'm using the basic NES A,B, and directional buttons. I need to make sequential inputs like Tony Hawk Pro Skater. So for instance, a kickflip would be :

A,B, <--

But I also have tricks that will require simultaneous button presses as well. Would I accomplish that with input.isactionpressed, or input.isactionjust_pressed? Or otherwise?

Any assistance or guidance is appreciated. Thanks.

1 Answer

+3 votes

While it's not a particularly elegant solution, here is a "Cheat Code Detector" class I created for my game. It has an exportable function which lists all the cheat codes a player can type, and emits a signal when the player types one.

class_name CheatCodeDetector
extends Node
"""
Detects when the player enters cheat codes.
When the player types a key, this class checks whether the user finished typing a cheat code. If a cheat code was
typed, this class emits a signal which can be used to activate the cheat code. Any gameplay effects and sound effects
are the responsibility of the class receiving the signal.
"""

# Signal emitted when a cheat is entered.
signal cheat_detected

# The maximum length of cheat codes. Entered keys are stored in a buffer, and we don't want the buffer to grow to a
# ridiculous size.
const MAX_LENGTH := 32

# Dictionary of key scancodes used in cheat codes, and their alphanumeric representation.
const CODE_KEYS := {
    KEY_SPACE:" ", KEY_APOSTROPHE:"'", KEY_COMMA:",", KEY_MINUS:"-", KEY_PERIOD:".", KEY_SLASH:"/",
    KEY_0:"0", KEY_1:"1", KEY_2:"2", KEY_3:"3", KEY_4:"4", KEY_5:"5", KEY_6:"6", KEY_7:"7", KEY_8:"8", KEY_9:"9",
    KEY_SEMICOLON:";", KEY_EQUAL:"=",

    KEY_A:"a", KEY_B:"b", KEY_C:"c", KEY_D:"d", KEY_E:"e", KEY_F:"f", KEY_G:"g", KEY_H:"h", KEY_I:"i",
    KEY_J:"j", KEY_K:"k", KEY_L:"l", KEY_M:"m", KEY_N:"n", KEY_O:"o", KEY_P:"p", KEY_Q:"q", KEY_R:"r",
    KEY_S:"s", KEY_T:"t", KEY_U:"u", KEY_V:"v", KEY_W:"w", KEY_X:"x", KEY_Y:"y", KEY_Z:"z",

    KEY_BRACELEFT:"[", KEY_BACKSLASH:"\\", KEY_BRACERIGHT:"]", KEY_QUOTELEFT:"`"
}
# List of cheat codes. Cheat codes should be lower-case, and should not be contained within one another or the shorter
# cheat code will take precedence.
export (Array, String) var codes := []
# Buffer of key strings which were previously pressed.
var _previous_keypresses: String = ""
"""
Processes an input event, delegating to the appropriate 'key_pressed', 'key_just_pressed', 'key_released',
'key_just_released' functions.
"""
func _input(event: InputEvent) -> void:
    if event is InputEventKey and event.scancode in CODE_KEYS:
        var key_string: String = CODE_KEYS[event.scancode]
        if event.pressed and not event.is_echo():
            _key_just_pressed(key_string)
"""
Called for the first frame when a key is pressed.

Parameters:
    'key_string': An single-character alphanumeric representation of the pressed key
"""
func _key_just_pressed(key_string: String) -> void:
    _previous_keypresses += key_string
    # remove the oldest keypresses so the buffer doesn't grow infinitely
    _previous_keypresses = _previous_keypresses.right(_previous_keypresses.length() - MAX_LENGTH)
    for code in codes:
        if code == _previous_keypresses.right(_previous_keypresses.length() - code.length()):
            # Clear the keypress buffer, otherwise a keypress could count towards two different cheats
            _previous_keypresses = ""
            emit_signal("cheat_detected", code)
by (140 points)

that worked pretty nice, thx ;)

This is perfect!! Really, really useful, thank you so much for sharing!

Wow awesome, I'm glad you were able to use it!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.