It's not logical Captain

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By JayH

Hi,

I’m having trouble with some logic, it should be simple, but I just can’t seem to figure it out!

I’m making a 2D Platformer with ladders.

Collisions/Signals all working :wink:

Description
My player should be able to run around his level with the wind in his hair, running past ladders without a care in the world.

It is only when the UP key is pressed and when he is overlapping a ladder that he can no longer freely move left and right or jump.

He is then able to use a new set of controls, which centre him on the ladder and then allow him to move up and down the ladder.

Note: I haven’t got to the bit where I remove the Player from the ladder at the bottom or top, this current step is important before obviously.

So to keep things simple, I put in a conditional statement for the main left/right/jump/gravity/on_ground mechanics:

if !player_on_ladder && !Input.is_action_just_pressed("ui_up")
    #Let the player move freely

Then in the moving the Player up and down the ladder I have a conditional statement:

if player_on_Ladder && Input.is_action_just_pressed("ui_up")
    #Let the player move up and down the ladder

This all seems ‘logical’ as they appear to be opposites to each other, however I’m missing something because it doesn’t work. One thing appears to be cancelling out the other.

Can you spot a flaw in my logic? Or what logic would you suggest?

What is the thing that happens instead? It seems to me that the second check will only be true for one frame because is_action_just_pressed only fires once.

SanderVanhove | 2022-07-15 15:00

We probably need some more code context here (just more code in general). It’s important to understand where the bits of code you showed live in your script and how they relate to each other.

jgodfrey | 2022-07-15 13:52

Also, something of note… The is_action_just_pressed() will only fire in the single frame where the specified input is pressed. It does not fire continually while the input (button) is held down…

jgodfrey | 2022-07-15 13:54

I agree. It may be your handling of the player_on_ladder flag and the 1-frame input instead of holding the input (e.g., are you using a ray cast, using the player’s position, collision signals, etc. to set that flag?)

godot_dev_ | 2022-07-15 15:07

One more comment. Not sure if you typed the code into the forum or cut/pasted it from your actual project but, you show 2 variations of this variable:

player_on_ladder
player_on_Ladder

(notice the capital L in the second one). I assume that’s unintentional…

jgodfrey | 2022-07-15 15:32

Hi,

I was going to copy the code here, but I can never get it to display more than a handful of lines, so instead here’s a screenshot of the script, it shouldn’t look too complicated to understand - I hope :wink:

(You can zoom the screenshot when you open the image seperately)

The Part for moving the Player on the Ladder has had a few alterations, but it’s pretty much similar to what I posted above.

The main problem so far is that when the player reaches the ladder he stops dead. Additionally he doesn’t move upwards.

I’ve done a lot of debugging and altering the code, but I seem to always end up back in the same situation. I’ve had the player go up and down the ladder with variations, but other things often break.

I realise the code isn’t as compact as it could be, I could use some functions and pair parts up, I just need it to be readable to make it easier to understand.

JayH | 2022-07-15 16:11

FYI - to paste formatted code into the forum…

  • Copy the code to the clipboard
  • Paste the code into your forum message
  • Select the code block in the forum message
  • Press the { } button in the forum editor toolbar
  • Look at the Preview to verify it’s formatted as expected

jgodfrey | 2022-07-15 17:12

:bust_in_silhouette: Reply From: godot_dev_

Line 35: your making a redundant check. player_on_ladder is always false given your check at line 22.

Line 43: you might want to make it an elif since I don’t think it makes sense to be able to release and press jump on same frame.

Line 51: your making a redundant check. Same comment as line 35

line 66: might want to do an elif, since if the condition is true on line 22, the condition on line 66 will never be true, so your wasting a condition check

line 69: careful. You might break floor collisions with this since your manually moving the player without using move_and_slide (not sure this is an issue, but you may want to explore if the floor collision has issue from this)

Also on a naming convention note, ladder_Player_on_ladder is named oddly. It stores an x position, but its name implies it refers to a ladder.

Source of bug
The move_and_slide call is only called when your not on a ladder (only when the condition at line 22 is true). Place it at the end your _physics_process fuction every frame. At the moment when you are on the ladder, you change the velocity but never call move_and_slide

Thanks for the help - I didn’t get back sooner as I had a busy weekend :wink:

A lot of the checks I placed were redundant as I was trying anything at this stage. I realise now that some should have been removed before I posted.

I’ve editted everything you suggested other than the one which you mention adding an elif to line 66 (now 62 - #MOVE THE PLAYER UP AND DOWN LADDER IF ON THE LADDER section) - I wasn’t sure what part you meant exactly.

I haven’t changed the part where the player is re-positioned on the ladder center via move_and_slide, I’m not sure how to refactor the code with move_and_slide, setting the position is all I know how to do here, but it seems to work ok on that currently, no obvious bugs.

Nothing has changed though, the Player still isn’t going up and down the ladder. In fact when he reaches the ladder sometimes he is pushed to the opposite side of the ladder.

When he’s on the ladder and you press UP he begins his climb, animates, but doesn’t assend (move up) the ladder :frowning:

Any further ideas?

extends KinematicBody2D
    
    #VARIABLES
    var myVelocity = Vector2() #STORE VECTOR COORINATES IN THE VARIABLE MY VELOCITY
    var onGround = false
    
    const PLAYERSPEED = 100
    const GRAVITY = 15
    const JUMPPOWER = -250
    const JUMPLOW = -100
    const FLOOR = Vector2(0,-1)
    const PLAYERLADDERSPEED = 30
    
    var player_on_ladder = false
    var ladder_Player_on_Ladder
    
    
    #MAIN ROUTINE
    func _physics_process(delta):	
    	
    	#MAIN PLAYER MOVEMENT
    	if !player_on_ladder && !Input.is_action_just_pressed("ui_up"):
    
    		#MOVE PLAYER LEFT/RIGHT
    		if Input.is_action_pressed("ui_right") :
    			myVelocity.x = PLAYERSPEED
    			$AnimatedSprite.play("Walk")
    			$AnimatedSprite.flip_h = false
    		elif Input.is_action_pressed("ui_left") :
    			myVelocity.x = -PLAYERSPEED
    			$AnimatedSprite.play("Walk")
    			$AnimatedSprite.flip_h = true
    		else:
    			myVelocity.x = 0
    			if onGround == true:
    				$AnimatedSprite.play("Idle")
    					
    		#VARIABLE JUMP HEIGHT		
    		if Input.is_action_just_pressed("space"):
    			myVelocity.y = JUMPPOWER
    		elif Input.is_action_just_released("space"):
    			myVelocity.y = -JUMPLOW
    		
    		if !player_on_ladder:
    			myVelocity.y += GRAVITY # ADD GRAVITY TO THE PLAYER
    			
    
    		#SET IF ON THE GROUND OR NOT
    		if is_on_floor() && !player_on_ladder:
    			onGround = true
    		else:
    			onGround = false
    			if myVelocity.y < 0 :
    				$AnimatedSprite.play("Jump")
    
    			if myVelocity.y > 0 :
    				$AnimatedSprite.play("Fall")
   
    			
    	
    	#MOVE THE PLAYER UP AND DOWN LADDER IF ON THE LADDER
    	if player_on_ladder:
    		if Input.is_action_just_pressed("ui_up"):
    			#myVelocity.y = 0
    			self.global_position.x = ladder_Player_on_Ladder
    			print("Player is moving up")
    			$AnimatedSprite.play("Climb")
    			myVelocity.y = -PLAYERLADDERSPEED
    		elif Input.is_action_pressed("ui_down"):
    			#myVelocity.y = 0
    			self.global_position.x = ladder_Player_on_Ladder
    			print("Player is moving down")
    			$AnimatedSprite.play("Climb")
    		myVelocity.y = PLAYERLADDERSPEED
    #
    
    	myVelocity = move_and_slide(myVelocity, FLOOR) #MOVE PLAYER
    
    
    
    #IF THE PLAYER IS ON THE LADDER
    func _on_Ladder_on_ladder(ladders) -> void: #SIGNAL WITH ADDED VARIABLE FOR LADDERS VARIABLE
    	player_on_ladder = true
    	ladder_Player_on_Ladder = ladders.ladder_position.x #SET PLAYER'S POSTION TO THE LADDER, STORE 
    	#self.global_position.x = ladders.ladder_position.x #SET PLAYER'S POSTION TO THE LADDER
    	print("Player is in the Ladder Area2D")
    	
    
    #IF THE PLAYER IS NOT ON THE LADDER
    func _on_Ladder_off_ladder() -> void:
    	print("Player is NOT in the Ladder Area2D")
    	player_on_ladder = false

JayH | 2022-07-18 11:39