I am trying to create animation for when the player is on a wall, I just recently set it the game to deal with animation for a ladder so I tried basically to do the same thing with the walls by using this code:
##---------------------------------------------------------
#the way to get sprite animation to play on the walls?!?
if(charOnWall):
if(wall_up):
print("going up wall");
hero_sprite.play("wall_up");
elif(wall_down):
print("going down wall");
hero_sprite.play("wall_down");
else:
print("idling_on_wall");
hero_sprite.play("wall_idle");
##------------------------------------------------------------
I made sure that there is no other wall animations are playing before this code to override what is happening, and all the conditions are being met. That is, if the character is going up on the wall, “going up wall” is printed in the debugger, same with wall down, and if no movement, “idling_on_wall” is printed.
But only the first frame is being played which happens to be the same frame for all three. Actually, can now confirm it is dropping through to the first frame of the idle animation when Idle, and playing the first frame of the other animations.
I really can’t see the problem here, so, all help is greatly appreciated.
The reason for not showing you the full code is because I don’t want you to have an aneurysm and die of shock. I was hoping that the snippet might be enough to diagnose the problem.
I know this code is all over the place and should be done better, I have seen how it should be done better using states, but, this is my code, done with much hard work, much thinking and much twiddling of thumbs and much tears.
So, please keep that in mind before ripping me a new one.
I’ll post the code later tonight when I am able, and made sure I’ve censored it correctly.
Focus on the Snippet: Even without the full code, the snippet you can provide might be enough to identify potential issues. Sometimes a small section can reveal underlying problems.
Explain the Problem: If you can describe the specific behavior you’re encountering, that might give clues without needing the complete code.
Focus on Solutions: Instead of dwelling on how the code could be better structured, let’s explore potential solutions to the specific problem you’re facing. We can discuss strategies using states or other approaches without needing to see the entire codebase.
Be Kind: There’s no need to worry about me getting upset. My goal is to help you improve your code, not judge your process.
As promised full character code below. Also of note I am not responsible for any result in the destruction of any brain matter.
extends CharacterBody2D
#bound to player node
#access to sprite
@onready var hero_sprite = $AnimatedSprite2D
#access to the HUD - UI elements?!?
@onready var num_jump = $"../UI/CanvasLayer/numJumpUI4"
@onready var power_up = $"../UI/CanvasLayer/PowerUpsUI"
@onready var ui = $"../UI"
@onready var currHealth = $"../UI/CanvasLayer/numJumpUI4"
@onready var maxHealth = $"../UI/CanvasLayer/PowerUpsUI"
## Raycast 2D
@onready var wallchecker = $Wallchecker
#-----------------------------
#Player Health --
#-----------------------------
#variable to control health bar on the UI.
var MAX_Health: float = 100;
var CURR_Health: float = 100;
#changed vars
#const SPEED = 300.0
#const JUMP_VELOCITY = -400.0
const SPEED = 130.0 #slower
const JUMP_VELOCITY = -300.0 #less height
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
#acess the jump sound???
@onready var jump_sfx = $JumpSFX
#--
var onSpike: bool = false;
#--
# var to pick up bomb
var canPickUp = true;
#---------------------
var maxJumps; #maximum number of jumps
var powerUps; #boolean value
var jumpCount;
#now creating a var (bool???) to know if hero
#is "on" a ladder initally set to false
var on_ladder : bool = false;
var ladder_up : bool = false;
var ladder_down : bool = false;
#var to keep track of hero is on ice
var on_ice : bool = false
var new_ice: bool = false
#var to set 'friction'
var acceleration = 100;
var deceleration = 100;
var friction: float = 0.1
var direction : float
#-------------------------------
#Jumping and wall vars
var isJumping : bool = false;
var wallCheck : bool = false;
var wallSlideGravity :int = 100;
var onRock : bool = false;
var onWallAnim: bool = false
#---------------------------
# For wall animations
var charOnWall: bool = false;
var wall_up : bool = false;
var wall_down: bool = false;
#--------------------------------
#----------------------------------------------------------------
func _ready():
initialize();
#pass # Replace with function body.
#now using TileMap node! in Game node
#tiles need a physics layer to hold up the hero
func _physics_process(delta):
#print (is_on_wall() );
##print(is_near_wall() );
#if(on_wall):
# print("... it's working ...")
#-- on spike: nothing happens forcing animation to play -------
if (hero_sprite.animation=="hit" and hero_sprite.is_playing() ):
return;
else:
onSpike = false;
#---------------------------------------
if(!on_ladder):
ladder_up = false;
ladder_down = false;
##-- ladder code ---------------------------------
##cannot play animations at all here ##
## assumption because of the physics below
## physics works in that it stops sliding down ladder
## and going up and down works however - no animation
if(on_ladder):
##print(on_ladder)
##hero_sprite.play("on_ladder")##
if(Input.is_action_pressed("UP") ):
##going up
ladder_up = true;
ladder_down = false
##print("ladder up")
#up speed
velocity.y = -90;
elif(Input.is_action_pressed("DOWN") ):
##going down
ladder_up = false;
ladder_down = true;
velocity.y = 90;
else:
velocity.y = -16.3;
ladder_down = false;
ladder_up = false;
##-------------------------------------------------
# Add the gravity.
if not is_on_floor():
velocity.y += gravity * delta;
#set jumpcount to zero
if(is_on_floor() ):
jumpCount = 0;
wallCheck = false;
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
direction = Input.get_axis("move_left", "move_right") #defined
#get direction
#if direction > 0 then we are going right
#if direction < 0 then we are going left
if direction > 0:
hero_sprite.flip_h = false;
wallchecker.scale.x = 1;
#wallchecker.cast_to = wallchecker.cast_to.rotated(PI) #facing right - rotate accordingly
elif direction < 0:
hero_sprite.flip_h = true;
wallchecker.scale.x = -1;
#wallchecker.cast_to = wallchecker.cast_to.rotated(PI) ; #facing left rotate 180
#play correct animations
#hopefully
###this might be the case of the sprite animation problem
## GD King - adding one line here **
if(! on_ladder): #if false
if is_on_floor():
isJumping = false;
charOnWall = false;
if direction == 0:
hero_sprite.play("idle");
elif (direction !=0):
hero_sprite.play("Run");
else:
hero_sprite.play("jumping");
##-- wall --------------------------------------------------
if Input.is_action_just_pressed("jump") and jumpCount < maxJumps:
#redirect to MediaManager - cool
MediaManager.play_track("jump");
##[some other code]
velocity.y = JUMP_VELOCITY;
jumpCount += 1;
isJumping = true;
if( is_near_wall() and isJumping and onRock):
##print("on_wall: "+str(isJumping)+" near wall: "+str(is_near_wall()) );
#print("...near wall...");
#------------------------
#### we are on wall ###
#------------------------
velocity.y = 0.0; #stay stationary or close to it
charOnWall=true;
jumpCount = 0;
if(Input.is_action_pressed("jump") and Input.is_action_pressed("move_right") and direction == -1):
print("true");
velocity.x=450 * direction;
velocity.y = JUMP_VELOCITY * .7
if(Input.is_action_pressed("jump") and Input.is_action_pressed("move_left") and direction == -1):
print("true");
velocity.x=450 * -direction;
velocity.y = JUMP_VELOCITY * .7
if(Input.is_action_pressed("DOWN")):
velocity.y = 18;
wall_down = true;
if(Input.is_action_pressed("UP")):
velocity.y = -18;
wall_up = true
if(velocity.y == 0):
wall_up = false;
wall_down = false
##pass
#-------------------------------------------------------------
##-- Wall movement w/ animation ----------------------------
#only way to get sprite animation to play on the walls ?!?
if(charOnWall):
if(wall_up):
print("going up wall");
hero_sprite.play("wall_up");
elif(wall_down):
print("going down wall");
hero_sprite.play("wall_down");
else:
print("idling_on_wall");
hero_sprite.play("wall_idle");
##-- End Wall -------------------------------------------
##---------------------------------------------------------
#the way to get sprite animation to play on_ladder
if(on_ladder):
if(ladder_up):
print("going up")
hero_sprite.play("climb_up")
#playClimbUpAnim();
elif(ladder_down):
print("going down")
hero_sprite.play("climb_down")
else:
print("idling_on_ladder")
hero_sprite.play("on_ladder")
##------------------------------------------------------------
##control speed
##normal movement no ice
if(!on_ice):
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
##on Ice movement
if(on_ice):
if(new_ice == true && direction<0):
velocity.x = -50;
print("New ICE")
new_ice = false;
if(new_ice == true && direction>0):
velocity.x = 50;
print("New ICE")
new_ice = false;
if direction:
velocity.x = lerpf(velocity.x, SPEED * direction, 1 * delta);
else:
velocity.x = lerpf(velocity.x, SPEED * direction, 2 * delta);
#finally
move_and_slide()
#-- End Physics -------------------------------------------------------------------
#-------------------------------------------------------------------------------
## function implementing raycasting
## called: is_near_wall
func is_near_wall():
return wallchecker.is_colliding()
#pass
##-- end is_near_wall ---------------------------------------------------------
func initialize():
maxJumps = 1;
jumpCount = 0;
powerUps = false ;
print("NumJumps: " + str(maxJumps) );
print("Powerups: " + str(powerUps) );
updateUI();
#function to call updateUI with a function here
#can't seem to just adjust the values themselves in in UI
#which I find strange
#then the function in ui.updateUI get the return values of the var
#and get them from here
#like I said weird, unweidly but I got nothing
#hard coded the path to UI with onready seems to work?!?
func updateUI():
#add i to jump when powerup achieved
#yes this is bad programming practice but then again this whole game is
#powerUps=true;
if (powerUps==true):
hero_sprite.scale = Vector2(1.1, 1.1);
maxJumps=2;
num_jump.text=str(maxJumps);
power_up.text=str(powerUps);
#call to upDateUI in the node UI
#ui.updateUI();
#pass
func setNumJumpsinUI():
return maxJumps;
func setPowerUpsinUI():
return powerUps;
#remove player CURR_health by amount passed to function
#from where I can't remember
func removeHealth(remove):
##remove=10;
CURR_Health -= remove;
#CURR_Health -= remove;
print("Current Health: "+str(CURR_Health));
#send value to UI ??
#access directly - rather than using a function
#in UI - I suppose I could do that too but this is easier
#UPdate Bar
ui.progress_bar.value = (CURR_Health/MAX_Health)*100;
if (CURR_Health <= 0):
print("... You are dead")
#ladder set function
func setLadder(TFvalue):
on_ladder = TFvalue;
#ladder set function
func setIce(TFvalue):
on_ice = TFvalue;
#play the hit animation onspike()
#velocity.x doesn't work >:
func playHitAnamation():
hero_sprite.play("hit");
if(direction == 1):
velocity.y = -200
velocity.x = 200;
else:
velocity.y = -200
velocity.x = -200;
#not used anymore - it was
func playClimbUpAnim():
print("Climb up")
hero_sprite.play("climb_up");
func KillEnemy():
velocity.y = -200
func nearRock(TFvalue):
onRock = TFvalue;
That’s it, sorry out there to the real programmers that now what they are doing. And doubly sorry for the triple conditionals!?!
Yeah, I understand it must be trying to play another animation, but, what is it I can’t figure out. Unless, there is a gdscript function to find out what is playing at that exact fraction of a second, I have no idea what it could be.
When the character is on the the wall, in my case charOnWall there are three possible animations “wall-idling”, “wall-up” or “wall-down”, there really isn’t another another possibility, even if I jump off the wall completely it goes into the wall-idling animation as intended before hitting ground and going back into the on_floor animations be that whatever: run, jump, idle.
I did try this adding a line to confirm that the correct animation hero_sprite.animation == “wall_up” is playing ala this:
##-- Wall movement w/ animation ----------------------------
#only way to get sprite animation to play on the walls ?!?
if(charOnWall):
if(wall_up):
print("going up wall");
hero_sprite.play("wall_up");
if(hero_sprite.animation=="wall_up"):
print("confirm up");
elif(wall_down):
print("going down wall");
hero_sprite.play("wall_down");
else:
print("idling_on_wall");
hero_sprite.play("wall_idle");
##-- End Wall -------------------------------------------
It did print out the confirmation message that is/should be playing wall_up when going up.
Dude, how can you be late! You are helping me, I should be saying thankyou for just bothering to reply, let alone help. Helping on the forum isn’t a paid position.
Right, so here, you want me to indent the code so the ladder component is an “elif”
on the wall component and not separate? Is that correct? Oh dear, I really need to refactor this.
well um, from reading the code i already knew it’s because of that jumping animation is being played for every frame whenever it’s not on the floor and not on ladder. so you should somehow not play the jumping animation when it’s not on the floor and not on ladder while you are doing climbing animation
first thing to check is to put print on here:
put print every if else branch
and it will tell you which one is being accessed all the time when you are on the wall or climbing
Unfortunately, I have changed the codes that I have provided because I have wrongfully made something wrong with the tabs in codes (the 3rd code box) so you can recheck it. I think it will solve your problem
I think you have to make sure , if the_player is_on_floor or not is_on_floor by using if,elif or else statements and try to gather them in one function . I ran over the same problem where the game was playing just the frame 0 when i pressed jump . but somehow i fixed it . Like this …
if is_on_floor():
if is_attacking == false and is_running == false:
if direction == 0:
$AnimatedSprite2D.play("Idle")
else:
$AnimatedSprite2D.play("walk")
elif is_attacking == false and is_running == true:
if direction == 0:
$AnimatedSprite2D.play("Idle")
else:
$AnimatedSprite2D.play("run")
elif is_attacking == true and is_running == false :
$AnimatedSprite2D.play("attack")
velocity.x = 0
elif is_attacking == true and is_running == true:
$AnimatedSprite2D.play("run + attack")
elif not is_on_floor():
if direction == 0:
$AnimatedSprite2D.play("jump")
else:
$AnimatedSprite2D.play("jumpf")
As expected, it was extremely easy to fix, but, I cannot figure out why it happened in the first place. There was only one place where the is_on_floor didn’t take into account that the charOnWall needed to be set to false - but, it was accounted for elsewhere. The code needs to be refactored something shocking. Especially seeing as I want to add in one other state where the knight can attack with a sword, but, that might be a step too far. Maybe I need to keep jumping as the attack or a projectile
@KingGD your code looked great, I thought it took in and accounted for every possibility, so, I must say I owe you a extreme amount of gratitude. To put up with my spaghetti code like this and be able to follow it, is really something. I am a martial artist and I’ve been hit, kicked, punched and been thrown around more than I can remember. It unfortunately takes it’s toll on the grey matter.