Now, I have the code for the player pasted below. The problem with the code is that the ladder climbing animations will not play it sits at the first frame and stays there, and I can’t understand why. I don’t have much understanding of the way to set and change animations as well as the physics involved. I just can’t seem to wrap my mind around it - it’s like I need to separate all of them out but don’t see how. I tried to set it like my Unity code years ago - but, I’d forgtten just about all of it and got totally corrupted. I also want to add wall climbing as well and that is going to introduce more problems unless I get this sorted first.
I know the code is all over the place just like my mind so don’t laugh too much. Ok here it is:
#now using TileMap node! in Game node
#tiles need a physics layer to hold up the hero
func _physics_process(delta):
#-- on spike----------------------------
if (hero_sprite.animation=="hit" and hero_sprite.is_playing() ):
return;
else:
onSpike = false;
#print("... onSpike over");
#---------------------------------------
if(!on_ladder):
ladder_up=false;
##-- ladder code ---------------------------------
##cannot play animations at all here ##
## assumption because of the physics below
## don't know how to rectify that ##
## 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;
print("ladder up")
##hero_sprite.play("climb_up")
velocity.y = -100;
elif(Input.is_action_pressed("DOWN") ):
##going down
velocity.y = 100;
else:
velocity.y = -16.3;
##-------------------------------------------------
# Add the gravity.
if not is_on_floor():
velocity.y += gravity * delta;
#set jumpcount to zero
if(is_on_floor() ):
jumpCount = 0;
# Handle jump.
#handle doublue jump
#if Input.is_action_just_pressed("jump") and is_on_floor():
if Input.is_action_just_pressed("jump") and jumpCount < numJumps:
#jump_sfx.play();
#redirect to MediaManager - cool
MediaManager.play_track("jump");
##[some other code]
velocity.y = JUMP_VELOCITY;
jumpCount += 1;
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("move_left", "move_right")
#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;
elif direction < 0:
hero_sprite.flip_h = true;
#play correct animations
#hopefully
###this might be the case of the sprite animation problem
if is_on_floor():
if direction == 0:
hero_sprite.play("idle");
elif (direction !=0):
hero_sprite.play("Run");
else:
hero_sprite.play("jumping");
##---------------------------------------------------------
#only way to get sprite animation to play on_ladder
if(on_ladder):
## single frame
hero_sprite.play("on_ladder")
if(ladder_up):
#animation won't play only first frame#
print("going up")
hero_sprite.play("going_up")
##-----------------------------------------------------------
##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 direction:
velocity.x = move_toward(velocity.x, direction*SPEED, acceleration*delta)
else:
velocity.x = move_toward(velocity.x, 0, deceleration * delta)
move_and_slide()
#-----------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------
Now, any help to get everything together and extensible when I get to possible implementing wall jumping here is the biggest THANKYOU I can give.
I tried cleaning up the language in the comments - please forgive me if there is still some there.
Hmm I think it is because you have played the ladder animation and jumping animation together, to fix it try to do this:
if !on_ladder: # means if on_ladder is false
if is_on_floor():
if direction == 0:
hero_sprite.play("idle");
elif (direction !=0):
hero_sprite.play("Run");
else:
hero_sprite.play("jumping");
Do same to all animations before you have played any other like:
if(on_ladder):
## single frame
if(ladder_up):
#animation won't play only first frame#
print("going up")
hero_sprite.play("going_up")
else:
hero_sprite.play("on_ladder")
I really miss the use of braces makes thing so much more readable. I actually found a hard copy of the code I used in that Unity game, looking at it now it’s really complicated, like using a Rayast to find a ladder, like what was I thinking, and having everything separated to make some semblance of sense.
Back to the topic at hand, I am trying it what you suggested right now, I will report back as soon as I have finished .
Ok, I tried what you suggested and the on_ladder animation actually played (so progress), I thought wow this is going to work, however the other 2 animations underneath that:
climb_up
climb_down
both failed to play using only the first frame. Here is climb_up animation:
##---------------------------------------------------------
#only way to get sprite animation to play on_ladder
if(on_ladder):
## single frame
hero_sprite.play("on_ladder")
if(ladder_up):
#animation won't play only first frame#
print("going up")
hero_sprite.play("going_up")
elif(ladder_down):
hero_sprite.play("climb_down")
##-----------------------------------------------------------
It might be because on_ladder variable is still true, but the inner “if” should override that. But I don’t know. I’ll try adding an “and/&&” to see what happens. I’ve also found that sometimes the first play animations won’t play all animation that are in the game only some of them - can’t figure out why. Like, idle won’t play or run!
Your codes is wrong because first you have started the on_ladder animation then started going_up animation and in the next frame of the process function, it playing the on_ladder animation again so that going_up animation stopped after a single frame. This topic is similar like this. It is a common mistake
and it ended up with the same result, only the idling animation on the ladder would play.
I think it’s like you were hinting at - it’s probably because as I have hit the “up” button, it goes to play the animation, but, before it can play it, the “Up” is still being pressed so it tries to play it again and when it’s released it can play the idling animation without being interfered with by a button press/release.
Now, what I want can be done, I did it in Unity, just don’t know how to do it yet in Godot a much freer environment.
Okey dokey, here is is it’s not that much different for what I posted in the original post. But they ARE some differences. The last function playClimbUpAnim() is not used:
#access to sprite
@onready var hero_sprite = $AnimatedSprite2D
#access to the 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"
## access the sound manager
#that code didn't word
#-----------------------------
#Player Health --
#-----------------------------
#variable to control health bar on the UI.
var MAX_Health: float = 100;
var CURR_Health: float = 100;
#changes made
#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")
#access the jump sound??? Not used anymore
@onready var jump_sfx = $JumpSFX
#--
var onSpike: bool = false;
#--
# var to pick up bomb
var canPickUp = true;
#---------------------
var numJumps; #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 to set 'friction'
var acceleration = 100;
var deceleration = 100;
var friction: float = 0.1
var direction: float
#----------------------------------------------------------------
func _ready():
initialize();
#pass # Replace with function body.
#used StaticBody2D w/ CollisionShape2D - world boundary
#now removed
#now using TileMap node! in Game node
#tiles need a physics layer to hold up the hero
func _physics_process(delta):
#-- on spike----------------------------
if (hero_sprite.animation=="hit" and hero_sprite.is_playing() ):
return;
else:
onSpike = false;
#print("... onSpike over");
#---------------------------------------
if(!on_ladder):
ladder_up=false;
ladder_down=false;
##-- ladder code ---------------------------------
##cannot play animations at all here ##
## assumption because of the physics below
## don't know how to rectify that ##
## 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")
#hero_sprite.play("climb_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;
# Handle jump.
#handle doublue jump
#if Input.is_action_just_pressed("jump") and is_on_floor():
if Input.is_action_just_pressed("jump") and jumpCount < numJumps:
#jump_sfx.play();
#redirect to MediaManager - cool
MediaManager.play_track("jump");
##[some other code]
velocity.y = JUMP_VELOCITY;
jumpCount += 1;
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction = Input.get_axis("move_left", "move_right")
#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;
elif direction < 0:
hero_sprite.flip_h = true;
#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():
if direction == 0:
hero_sprite.play("idle");
elif (direction !=0):
hero_sprite.play("Run");
else:
hero_sprite.play("jumping");
##---------------------------------------------------------
#only 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 direction:
velocity.x = move_toward(velocity.x, direction*SPEED, acceleration*delta)
else:
velocity.x = move_toward(velocity.x, 0, deceleration * delta)
move_and_slide()
#-----------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------
func initialize():
numJumps = 1;
powerUps = false ;
print("NumJumps: " + str(numJumps) );
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 wierd, 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);
numJumps=2;
num_jump.text=str(numJumps);
power_up.text=str(powerUps);
#ui.power_ups_ui.text = str(numJumps); #var numJumps;
#ui.num_jump_ui_4.text = str(powerUps); #var powerUps
#call to upDateUI in the node UI
#ui.updateUI();
#pass
func setNumJumpsinUI():
return numJumps;
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
func playHitAnamation():
hero_sprite.play("hit");
func playClimbUpAnim():
print("Climb up")
hero_sprite.play("climb_up");