Hello, I need help to check the last pressed key, for example if the character is going to the right, if I press the left key, it should register the last key pressed so go the the left, and vice versa.
I made 4 variables, one for left, right, up and down with a base value of 0.
At the moment I’ve created 2 functions, one for the right and one for the left, and called them in the physic process.
But the “last key pressed check” works in one way only, and depends on where I called the functions in the physic process, in my case if the right direction function is called above the left one, the check works only for the left direction and not for the right (so, if I’m going to the right and press the left key, it goes to the left cause that is the last registered input, but not vice versa), same thing but swapped if I call the left function above the right one (I don’t know if I’m explaining myself correctly, english is not my first language).
Here’s the left and right functions code, I know it’s kind of a ugly code, but note that I’m a beginner with very little programming experience.
func _physics_process(delta):
right_dir()
left_dir()
move_and_slide()
func left_dir():
if Input.is_action_pressed("left") and left == 0:
left = -1
right = 0
if left == -1:
velocity.x = speed * left
if Input.is_action_just_released("left") and left == -1:
left = 0
velocity.x = speed * left
func right_dir():
if Input.is_action_pressed("right") and right == 0:
right = 1
left = 0
if right == 1:
velocity.x = speed * right
if Input.is_action_just_released("right") and right == 1:
right = 0
velocity.x = speed * right
Thanks in advance to whoever will try to help me : )
Note: if it’s not clear check my reply to FreakyGoose
This is a good use case of Input.get_axis instructions of having different lines of code for left and right and dealing with button press priorities.
func _physics_process(delta):
##If you only need to get the horizontal direction
var input_direction: float
input_direction = Input.get_axis("Left","Right")
velocity.x = input_direction * speed
##if you also need to get the vertical direction
var input_direction: Vector2
input_direction = Vector2(Input.get_axis("Left","Right"), Input.get_axis("Up","Down")).normalized()
velocity = input_direction * speed
move_and_slide()
Thank you for the response, but I’ve already tried this kind of method, and it’s exactly why I wanted to try and create my own one.
The fact that this method does not make the character move when two conflicting keys are pressed at the same time (I want the script to register the last pressed key and make the character move in that direction, even when pressing both vertical or horizontal keys, or in diagonal) until all the keys are released.
If you have a solution for my case please help me, and thank you for the reply
: )
# Stands still on game start, set to -1 or 1 if you want a default start direction.
var dir : int = 0 # -1 is left, 1 is right
func _input(event: InputEvent) -> void:
if event.is_action_pressed("left"):
dir = -1
if event.is_action_pressed("right"):
dir = 1
func _physics_process(delta: float) -> void:
velocity.x = speed * dir # stands still if "dir" is zero and apply speed in to left and right using "dir"
No need for any additional functions or more than one variable.
Just a tip as well.
I made 4 variables, one for left, right, up and down with a base value of 0.
Instead of creating four variables for each direction which would require 3x the amount of code(if not more) to check each variable. You should instead just make one integer variable. Call it dir or something. Assign this variable to the values:
0 = Up
1 = Right
2 = Down
3 = Left
Using this, you just have to check or assign one variable’s value instead of four, then checking each value and all the possible combinations. To easily check this, you can use a match statement which would look like this:
match dir:
0: # Up
# Code to execute
1: # Right
# Code to execute
2: # Down
# Code to execute
3: # Left
# Code to execute
Thank you for the reply! I realized that I was making it a lot harder than it is, I tried this and modified it a bit for my needs, I created 2 variables, one for the x direction and one for the y direction, here’s the code and then I’ll explain what still isn’t working for me:
extends CharacterBody2D
@export var speed = 100
var dir_x := 0
var dir_y := 0
func _input(event):
if event.is_action_pressed("left"):
dir_x = -1
if event.is_action_released("left"):
dir_x = 0
if event.is_action_pressed("right"):
dir_x = 1
if event.is_action_released("right"):
dir_x = 0
func _physics_process(delta):
velocity = velocity.normalized() * speed
velocity.x = speed * dir_x
#velocity.y = speed * dir_y, I'll use it later
move_and_slide()
The fact is that whenever I press both left and right directional keys, if I let go one of them the character stops instead of still going in the pressed key direction.
So for example if I start with the right key, then add the left key, the left input in that exact moment is “stronger” than the right input, and if I let go one of the two keys the character suddenly stops instead of still moving to the left if I let go the right key or moving to the right if I let go the left key.
Hope it’s clear and thank you so much for the help! : )
Great, glad it worked out! The reason it stops is because you added the is_action_released() part in which you reset the dir_x to 0. dir_x should always be -1 or 1 and by resetting it, you’re doing velocity.x = speed * 0 which results in 0 velocity(standstill). Just use this:
func _input(event):
if event.is_action_pressed("left"):
dir_x = -1
if event.is_action_pressed("right"):
dir_x = 1
If I understand it correctly you want to move at all times and when you press two opposing directions, you want to keep moving in the direction of the first initial keystroke. Please correct me if I’m wrong. I’ll setup a test project and see what would work. I just want to test it out before suggesting something. I’ll get back to you in a bit
Hmm, sorry I think I haven’t explained myself correctly.
So:
I want the character to be still at the start of the game and when no key or all 4 directional keys are pressed.
The script should constantly update the strongest x and y input, which is when you press (or let go the current “strongest” input key) a different key than the one you’re pressing to move in the current character x or y direction.
So, if you press the left and up key the character should go in north-west direction, but if you update the input, for example by pressing the down key while still holding the up key, the character should move in south-west direction, and if you let go the down key while still holding the up key since before, the new strongest y input should be north again… and so on with every other x or y or diagonal directions.
Thank you for the help and I hope I’ve been exhaustive this time!
Edit: Also, if I let go the old strongest input key nothing should happen.
Alright, my bad but I want to get it right before suggesting more changes. I have to say that I’m still a bit iffy on exactly what you mean by strongest input since keystrokes are binary(0 or 1), do you mean the newest?
But I think I get it. If you’re pressing opposing keys on Y, you want it to remember the last X direction, move in the newest pressed Y direction + last known X?
Like you said:
Pressing Up and Left = NW direction
Let go of left(?) and still holding Up
Now pressing the opposing Down(since Up is still pressed) = remembering the Left input and and moving the newest Down input
Yes, by the “strongest” input I mean the newest, I don’t want the code to remember the last X or Y input, I want it to change direction based on the latest Input key pressed, both in the Y and X axes.
Let me give you another, hopefully clearer example:
In the X axis, if you start by going to the left, and then press the right key while also still holding down the left key, the newest input will be the right direction, Now, with both keys held down and the new directional input being right, if you let go of the left key nothing happens since the newest input is right, but if you let go of the right key while still holding down the left key since before, the newest input becomes left again, same thing should apply for the Y axis and for diagonal movement.
I want the character to stop only when NO key is pressed, so if you press all 4, the game should still be able to register the newest X and Y inputs. (It’s a bit tricky to explain, but for example if you start with north-west, and then press the south east keys, so down and right, the new direction should be south east, and if you let go of the down key, the new direction will be north east, since the newest Y input is north again). This is just an example and should work like this for every direction, I know that almost no one would press all 4 directional keys at once, but I want it this way cause I’m a perfectionist lol… I promise that it’s simpler than it seems, I guess
Hope it’s clear now, sorry if I’m taking so much of your time haha thank you
No worries, it’s hard to describe and convey these specific nuances in text as well as understanding them when reading.
Okay, so I’m 99.99% sure now what you mean. You simply don’t want opposing inputs to cancel each other out. Instead of standing still if you press left and right, you want to move in the direction of the newest keypress.
I had to make some changes and I fixed some small issues. Most notably, when applying movement to velocity(velocity.x = speed * norm_dir * delta). I added delta to the line. In case you didn’t know, if you don’t multiply by delta. The player will move slower/faster if you’re running the game at lower/higher FPS. This fixes that and makes the speed unified no matter the FPS. However, doing so requires a much higher speed because delta is usually a very low number.
Also you had:
func _physics_process(delta):
velocity = velocity.normalized() * speed
velocity.x = speed * dir_x
#velocity.y = speed * dir_y, I'll use it later
The first line where you use normalize() is redundant since you override it in the next line. You should use normalize in the last line of the function or after you change the velocity the last time so it normalizes the final value.
extends CharacterBody2D
@export var speed = 30000 # Change to a value that fits your game
var dir := Vector2.ZERO
func _input(event: InputEvent) -> void:
# LEFT
if event.is_action_pressed("left"):
dir.x = -1
if event.is_action_released("left"):
dir.x = 1 if Input.is_action_pressed("right") else 0
# RIGHT
if event.is_action_pressed("right"):
dir.x = 1
if event.is_action_released("right"):
dir.x = -1 if Input.is_action_pressed("left") else 0
# UP
if event.is_action_pressed("up"):
dir.y = -1
if event.is_action_released("up"):
dir.y = 1 if Input.is_action_pressed("down") else 0
# DOWN
if event.is_action_pressed("down"):
dir.y = 1
if event.is_action_released("down"):
dir.y = -1 if Input.is_action_pressed("up") else 0
func _physics_process(delta) -> void:
if Input.is_action_pressed("left") and Input.is_action_pressed("right") and Input.is_action_pressed("up") and Input.is_action_pressed("down"):
velocity = Vector2.ZERO
# Add more cases you want to cancel out movement in an "elif" here
else: # No cancel out conditions met > apply movement
var norm_dir : Vector2 = dir.normalized() # Normalize the final vector
velocity = Vector2(speed * norm_dir.x * delta, speed * norm_dir.y * delta)
move_and_slide()
Yes!! This kinda works, but just one thing, once you replace one directional input, if you’re still holding the old key and let go off the new key, I want the old direction to become the new one again.
With this script for example if you go left and then go right while still holding the left key, if you let go the right key while still holding the left key since the start, the character doesn’t start moving left again but instead stops, same thing for all conflicting directions. If you could help me fixing this I’d be very grateful, thank you so much : )
Edit: The problem also happens when I let go of the older input key, so if you go right, then press left while still holding the right key, if you let go of the right key the character stops.
Great! Glad we’re finally getting somewhere. The issue you’re describing is a bit odd, it works for me. Let me know if these are the actions that you’re having issues with:
I had this game where I wanted the player to move only in the direction of the last pressed key. If two keys where pressed, for example, up and left, (in that order) the player would move left. If after that the user releases the left key and holds the other, the player would move in that direction. It somehow works like a stack. If that is what you want for your game, this is the code that I used:
if Input.is_action_just_pressed("MoveUp"):
actionStack.append(Vector2i.UP)
if Input.is_action_just_pressed("MoveDown"):
actionStack.append(Vector2i.DOWN)
if Input.is_action_just_pressed("MoveLeft"):
actionStack.append(Vector2i.LEFT)
if Input.is_action_just_pressed("MoveRight"):
actionStack.append(Vector2i.RIGHT)
if Input.is_action_just_released("MoveUp"):
actionStack.erase(Vector2i.UP)
if Input.is_action_just_released("MoveDown"):
actionStack.erase(Vector2i.DOWN)
if Input.is_action_just_released("MoveLeft"):
actionStack.erase(Vector2i.LEFT)
if Input.is_action_just_released("MoveRight"):
actionStack.erase(Vector2i.RIGHT)
#Check the actionStack and move according to the last added action
if actionStack.size() == 0:
velocity = Vector2.ZERO
else:
velocity.x = actionStack[actionStack.size()-1].x * SPEED
velocity.y = actionStack[actionStack.size()-1].y * SPEED
actionStack is an array declared as a node’s variable
Summarizing, the codes does this: first, register the pressed keys and add them to the actionStack. Then, register the released keys and delete them. Finally, use the direction at the last position of the actionStack (which will be the direction of the last pressed key)
Edit:
I just read this:
In my code, the player only stays still if no keys are pressed. To keep the player still you will have to replace this line: if actionStack.size() == 0:
with this line: if actionStack.size() == 0 or actionStack.size() == 4:
Also, in my game, the player can’t move diagonally, but I think that the concept can be extrapolated for diagonal movement
Oh thank you for replying, but since I don’t really know how part of the code works, I’m not sure if I could work on it, since I prefer creating my own version of a code rather than copy-pasting someone else’s one and calling it a day, because I want to actually learn from it.
Yet thank you so much for your help, I appreciate it : )
And btw, I corrected myself and I actually only want my character to stay still when no keys are pressed too
Ah no wait, I’m actually really dumb lmao, I just realized that in the “action release” part I’ve put event.is_action_pressed("right) instead of Input.(etc), btw now it works for the most part, just one last thing:
When moving diagonally I can only change my X direction and not the Y direction if I start with one Y key (so, for example if I start by moving in north east direction, I can only adjust my direction in the X axis when holding both keys, and in the Y axis I have to let go of the up key first before changing direction), if you notice something else that I’ve missed please tell me.
If you’ve changed all the ternary if/else(that’s what the x = 1 if y == true else 2 are called) from event.is_action... to Input.is_action..., that should work. At least it does for me. I can’t see any issues other issues you’ve not addressed.
Try copying the code directly and see, there might be something my eyes can’t see as well. Try that if it still doesn’t work,
The only think I could htink of would be that you might have some old code that left somewhere that might interfere?
You are very welcome. I’m glad I could help. I needed help with these things when I started and got it here so I’m just trying to pay it forward
The code works just like yours, the thing is that when you’re moving diagonally (for example W and D pressed simultaneously) you can’t change your Y direction by pressing S while still holding down the W key (along with the D key obv), as I can see in the video you have to let go of the key to change the Y direction in diagonal movement.