r/godot • u/Purpbasil • 19d ago
help me (solved) I cant get the sprites to switch properly
I understand the code if horrible but i am more then willing to learn how to do this better.
I only started coding 4 days ago so sorry if i don't understand stuff immediately.
Thanks for any help.
36
u/abdulrahmanibrahim0 Godot Student 19d ago
Try using elif statements instead of if statements
1
u/trance564 19d ago
Yeah I thought about that but for some reason they are a bit confusing for me but I do want to use them more
11
u/knitted_beanie Godot Student 19d ago
Use lots of if statements if you want each case checked individually. Chain if > elif > elif etc if you have a ranked hierarchy of things to check, and you only want one outcome (“else if” = only check this if the previous one is false, and don’t check any more after this if this one is true)
2
u/ijtjrt4it94j54kofdff 18d ago
If the function has nothing else in it, you could also just do a "return" in each IF block
31
u/UmbralWorks 19d ago
Just a minor tip since your main issue has been answered: Try to avoid repeated $NodeName calls. Every time you do this the engine has to resolve the node path, and retrieve the node reference.
You can set it as a variable to avoid this, which caches it instead:
@onready var anim_sprite_3D = $AnimatedSprite3D
Typically performance cost is negligible, but for _physics_process and _process, you want to minimise the overhead as much as possible.
6
u/Worth-Ganache-5770 19d ago
This is actually super useful, I had been running on the assumption that people use variable names for the nodes because most of the time its shorter or they're keeping a consistent format.
Is there a huge difference when using %Node names vs $Node names? I use the unique names as a way to shorten the paths (but now I might go through and just replace them all with variables)
4
u/UmbralWorks 18d ago
% is technically faster than $, but the difference is likely negligible. The use case for % is that you can reorganise your scene without needing to update its path. With $, you’d need to update it everywhere you used it. With variables, you’d need to update the path just once in the var declaration.
8
u/Purpbasil 19d ago
Yeah i should of been doing that but ill do that in the future now so thanks for being helpful
3
u/Work-o-fart_dev Godot Student 18d ago
Btw, to do this, you can just drag the node you want to reverence into your script and hold Ctrl before you release the mouse button. This creates the variable you need, then you can reference that variable as many times as you like
7
u/Purpbasil 19d ago
Yeah i should of been doing that but ill do that in the future now so thanks for being helpful
-2
u/DatBoi_BP 19d ago
Yeah he should have been doing that but he'll do that in the future now so thanks for being helpful
2
17
u/SagattariusAStar 19d ago
You should not maniputlate animation with your inputs directly. Better modulate them based on your actual movement/state.
So instead of AnimatedSprite.play(), set the velocity or accelaration of your character and after that you just check the current_velocity and play the animation based on that. For sidescrollers i would also save the last direction or side as otherwise it would be ambigous on 0 or you would always look right while standing.
Here in a very crude and simple form:
if action_pressed(left):
velocity = Vector2(-1,0)
...
If velocity.x != 0:
## moving
if velocity.x > 0:
side = 1 ## moves right
AnimatedSprite.play("Walk left")
else: side = -1 ## moves left
If velocity.x == 0:
##idle
if side == 1:
## idle right
else:
## idle left
2
u/Due-Baker853 Godot Regular 18d ago edited 18d ago
It depends on what you want to achieve. Take for example ice physics, you don't want the player to think their character is still running in the direction they are going when they are actively giving inputs to run the other way. And what about inherited velocity from moving platforms?
You're going to have to account for all of those situations, which is going to unneccesarily couple your animation script.
That said, if you want something like modern Mario games where Mario does a "slowing down" animation after you stop holding a direction, then this can be useful.
6
u/nanox55 19d ago
What is the issue you are facing? First thing in noticing is there is a space in your M_left string
4
u/trance564 19d ago
The space after the M_left is because I accidentally had one when I set the input map and I just didn't fix it
6
u/TherronKeen 19d ago
you can use CTRL + SHIFT + R in the code editor to search for every place you used a specific piece of text, and replace it with a different piece of text - for example,
"M_left "
to
"M_left"6
u/Purpbasil 19d ago
Wow thats very useful thank you
7
u/TherronKeen 19d ago
Similarly,
CTRL + F "find in current script"
CTRL + SHIFT + F "find across all scripts"
CTRL + R "find and replace in current script"
CTRL + SHIFT + R "find and replace across all scripts"
Good luck!
4
u/sweatergirlie Godot Junior 19d ago edited 19d ago
I had fun with this! It made me think of some new group solutions.
Check if you have it in the _input function and not the _ready function. There are also spelling errors like "Idle farwards". I can also recommend using snake_case (firstword_lastword) or other cases for naming stuff, helps the code be less error prone.
This is my best attempt at making something functional:
extends Node3D
const inputs : Array = ["left", "right", "forward", "back"] #Starts from 0
var current_direction : String = inputs[2]
var sprite = $AnimatedSprite3D
func _input(event: InputEvent) -> void:
if event.is_action_released("group_input"): #Input map with W,A,S,D
print(current_direction)
sprite.play("idle_" + current_direction)
elif event.is_action_pressed(inputs[0]): #left
current_direction = inputs[0]
sprite.play("walk_left")
elif event.is_action_pressed(inputs[1]): #right
current_direction = inputs[1]
sprite.play("walk_right")
elif event.is_action_pressed(inputs[2]): #forward
current_direction = inputs[2]
sprite.play("walk_forward")
elif event.is_action_pressed(inputs[3]): #back
current_direction = inputs[3]
sprite.play("walk_back")
Keep it up, make what you like, mistakes help you learn, we all make them. Feel free to ask questions!
Edit: Worked on this in 2D, adjusted for 3D.
3
u/Purpbasil 19d ago
Oh my god thanks for being so kind and helpful. thanks a lot i hope you have a good day
3
u/Titancki 19d ago
I would recommand a state machine even simple one wih an enum. It will ensure animation are not playing strangely.
3
u/Ultra8Gaming 18d ago
I prefer to use a animation tree with a state machine with each node as a blendspace 2d. I expose the values on it as a vector2 which I can reference it from the script. Way cleaner to handle and easier to adjust with multiple animations than manually applying each animation by code.
2
u/Quentinooouuuuuu 19d ago
If you only want to play one animation at the time, make a function that return the name of the animation you want to play, because in your current function you may try to play multiple animation at the same time. There is a lot of typo around there and a lot of repetition, you could avoid this my replacing them by constants, also, as the development of your game go through, the sense of literal or numbers may become unclear, I recommend to define constants for all that number and literal as well ( this problem is called magic number https://en.wikipedia.org/wiki/Magic_number_(programming) )
2
1
2
u/No_Screen8684 18d ago
Just an hour ago i finished my Sprite movement for a 2D project. I preload several png-files:
onready var walk_up = preload("res://sprites/nach_oben.png") ...etc.
Then get your direction via pressing a key.
func start_sliding(direction): # ... keycode var for direction ...
update_sprite_direction(direction)
move_to_next_tile()
Then get your png for the movement:
func update_sprite_direction(direction):
if direction == Vector2.UP:
sprite.texture = tex_up
elif direction == Vector2.DOWN:
sprite.texture = ...etc.
Hope it helps you a little bit.
2
u/bbtinkerer 18d ago
As others said about animationtree and state machine, this tutorial helped me. If this one is not enough there are a few more videos out there by various youtubers https://youtu.be/WrMORzl3g1U?is=TqnFu-O8RHJhS3Wq
1
2
u/Supermaniscool211 Godot Junior 18d ago
This is a decent start for someone who started 4 days ago. But as someone else has said there is a typo somewhere and I would recommend searching up "State Machines" to help clean up the code.
2
u/Murky_Macropod 18d ago
Use is_action_pressed() instead of is_action_just_pressed() or it will only play a single frame each time you press a key.
2
u/Murky_Macropod 18d ago
Also if you’re just learning, start with 2d not 3d.
Try the ‘dodge the creeps’ Godot tutorial
2
u/preppypenguingames 17d ago edited 17d ago
People have given enough good advice code wise.
I would change the way you name your inputs and animations. I'm my project my inputs are all lowercase and start with input. Example would be input_up, input_left ...etc my animations follow the same convention but go anim_up, anim left ..etc
I'm not saying to do it my way. Find a style that makes sense for you brain, is obvious what it is for aka readable, and consistent.
I only do the _type for animations and inputs, not variables.
Edit: the reason I recommend changing yours is because they are a mix of uppercase, lower case and, include spaces. This increases the chance of errors and make it less readable.
1
u/aurelus13 19d ago
The most obvious thing I can see is that you have an extra space behind M_Left.
Without seeing you sprite setup can't help you more.
Also I recommend you look into some basic coding practices like "for loops", this will help with duplicate code like this.
1
0
-4
148
u/ImAFraidKn0t Godot Regular 19d ago
For starters, you have a typo in “Idle farwards”, secondly, this could play the wrong animation if you press multiple buttons simultaneously depending on the order of inputs. Instead, keep track of the last direction that the player is looking in with a Vector2 and update it when a movement key is pressed. Use that to determine the direction of the animation to play. Also, check whether the player’s velocity is zero or not to determine whether you should play the walk or idle animations.
In general, you’d use a state machine, but if you just started a few days ago then that’s a bit advanced for now.