Hello there,

I am currently busy with a tutorial on how to make a Tournament Fighter game but sadly I'm stuck.

I know how to make a Combo System and I already have ideas on how to make code more generic for every possible fighter within your game. Yet I can't get my head around receiving Inputs as a String.

With everything that I've tried, I only got as far as having an "integer" or weird long text describing in debug code what it needs to be.

What I want is an actual LETTER or WORD that is pressed, after which it can be stored within an Array which is then sent to a Dictionary as a KEY for the corresponding COMBO.

Here is a list of things that I've tried to get to the thing I want: func _input(event): if(Input.is_action_just_pressed("AnyKey")): usedKeys.append(event)

func _input(event): if(Input.is_action_just_pressed("AnyKey")): usedKeys.append(event.as_text)

I tried entering the InputMap after a press was done and using that to get the correct input inside my array

And there are some other things that I have done to make this work. But became stuck again looping back to the issues I had before.

I also searched around the Internet for a definitive answer and did spot a forum post, which sadly would make my code no longer generic.

PS: I do know about the video of PigDev but it became really complicated after a short while

Don't mix input() event handler and Input singleton. The former is based on callback while latter depends on event polling, typically used each frame from process() callback. These two things are kind of mutually exclusive. Mixing them only causes confusion.

Event object that is passed to handler knows everything about the actual event. It's just a matter of properly querying it.

func _input(event):
	if event is InputEventKey:
		if event.pressed:
			var character: String = OS.get_scancode_string(event.scancode)
			print("Pressed " + character)

You can get the action name like this:

func _input(event):
	var action = null
	for input in InputMap.get_actions():
		if InputMap.event_is_action(event, input):
			action = input
			
	if action:
		print(action)

And the last part (instead of just checking if action is not null) should probably use a match statement. Or instead of using InputMap.get_actions() you can create an array with the string action names you want to track (otherwise you get the default Godot actions like "ui_accept" and others you might not want).

Thank you @xyz & @cybereality for helping me out on this one =) I've tested both and both perform the actions I want (cheer emoji)

But now I would like some advice on both: One allows me the exact letter on the keyboard but seems to have a drawback that I need to make an if tree for only allowing the set inputs.

The other keeps getting updated but has the whole list of possible moves already stored within the InputMap (which I can set by myself).

I did notice that I can do the following for checking the "allowed inputs":

export (Dictionary) var move_list which allows me to set all possible inputs.

Which path is best to use?

PS: Again thanks, I've been looking for a while for solving this one

@xyz & @cybereality

I came up with a solution to prevent relying on a whole if-elif tree:

extends KinematicBody2D
var allowedInputs = {
	0 : "A",
	1 : "D",
	2 : "W",
	3 : "S",
	4 : "L",
	5 : "P",
}

func _input(event):
	if(event is InputEventKey):
		if(event.pressed):
			var character: String = OS.get_scancode_string(event.scancode)
			for input in allowedInputs.size():
				if(character == allowedInputs[input]):
					print("Pressed " + character)

I am using the code of XYZ and applying a for loop to it. This will try to figure out if the current character is the same as some allowed input within the dictionary.

If the character is the same as an element within the dictionary I'll display it in my Output tab.

One last Issue: This gets updated as long as I have one button-down. What I mean is that as long as an allowed button is pressed, it will keep throwing it out. Isn't there a way to only display it once like what the is_action_just_pressed does?

You could simplify that:

const ALLOWED_INPUTS: Array = ["A", "D", "W", "S", "L", "P"]

and replace:

            for input in allowedInputs.size():
                if(character == allowedInputs[input]):

with:

            if ALLOWED_INPUTS.has(character):

Keyboard event object has echo property/flag that signifies the event is repeated key press caused by holding the key. So you need to check it and ignore the event if its value is true.

To check if a character belongs to a group of allowed characters you can use an Array as @DaveTheCoder suggested or even a plain string as shown below:

func _input(event):
	if event is InputEventKey:
		if event.pressed and not event.echo:
			var character = OS.get_scancode_string(event.scancode)
			if "ABCDEFGH".find(character) >= 0:
				print("Pressed " + character)

Btw it's good to get into habit of browsing class reference pages in Godot docs. Especially for classes that are often used such as InputEvent or String. You may discover plenty of useful properties and methods that can help you quickly solve common problems.

Yes!

Thanks this helped a ton, I'll surely keep that in mind in the future.

a year later