Godot Version:
4.2.2 stable
Question:
Hello! It might take me a while to understand if someone tries to help me but please bear with me. I will try to explain exactly what I want and how I think it should be implemented (even though I am not managing to do it myself).
Here is a video of the current setup I have in Godot (left) and what I would like it to become (right):
Basically, in Ninja Gaiden, the player can walk past walls that they can otherwise climb against if they are in mid-air. Also, they only climb to a wall if they jump toward it and not from behind. Right now, because I am using simple CollisionShape2D as walls, my player cannot go through them and climb to it on only the side I want (which would be the right side on the video for example). I hope it makes sense so far? The video should help.
I think I need to replace my CollisionShape2D by first using an Area2D so that the player does not collide with it. Then if my raycast attached to the player enters in the Area2D: they climb to it? Something like that… I tried for hours but couldn’t even get the player to climb to an area 2D (which has a CollisionShape2D attached to it). I put the signals but I am not even sure it did anything. I watched multiple videos about Area2D but it didn’t help.
I know it’s not clear at all, sorry. I hope the video helps to understand what I would like.
My current player script:
extends CharacterBody2D
@onready var sprite = $AnimatedSprite2D
@onready var wall_checker = $WallChecker
const SPEED = 100.0
const JUMP_VELOCITY = -310.0
var last_direction = 1
var direction = 1
var prev_velocity = Vector2.ZERO
var gravity: int = 900
var is_sticking = false
var is_crouching: bool = false
var is_attacking: bool
var is_wall_jumping: bool = false
func _ready():
is_attacking = false
func _physics_process(delta):
print(is_near_wall())
if direction != 0:
last_direction = direction
# ADD THE GRAVITY.
if not is_on_floor():
velocity.y += gravity * delta
prev_velocity = velocity
# HANDLE JUMP.
if Input.is_action_just_pressed("jump") and is_on_floor() and not is_attacking:
velocity.y = JUMP_VELOCITY
is_wall_jumping = false
# HANDLE CROUCH.
if not is_attacking:
if Input.is_action_pressed("crouch") and is_on_floor():
is_crouching = true
else:
is_crouching = false
# Get the input direction and handle the movement/deceleration.
var direction = Input.get_axis("move_left", "move_right")
if is_attacking and is_on_floor():
velocity.x = 0 # Stop movement during attack
else:
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
if not is_on_floor() and not is_wall_jumping:
velocity.x = lerp(prev_velocity.x, velocity.x, 0.090 / 2)
if not is_attacking and !is_sticking: # Condition to check if not sticking to a wall
if Input.is_action_just_pressed("attack"): # Check attack input only when not sticking to a wall
is_attacking = true
handle_attack_animation(delta)
set_direction()
handle_sticking()
move_and_slide()
# Update animations
handle_movement_animation(direction)
toggle_flip_sprite(direction)
func set_direction():
direction = 1 if not sprite.flip_h else -1
wall_checker.rotation_degrees = 90 * -direction
func is_near_wall():
return wall_checker.is_colliding()
func handle_sticking():
var direction = Input.get_axis("move_left", "move_right")
if !is_on_floor() and is_on_wall() and wall_checker.is_colliding():
is_sticking = true
is_attacking = false
velocity.x = 0
velocity.y = 0
sprite.play("climb")
elif !is_on_floor() and is_on_wall() and !wall_checker.is_colliding():
sprite.flip_h = direction < 0
is_sticking = true
is_attacking = false
sprite.play("jump")
if Input.is_action_just_pressed("jump") and is_on_wall() and wall_checker.is_colliding():
if direction != 0 and direction != last_direction:
sprite.flip_h = direction < 0
is_sticking = false
velocity.y = JUMP_VELOCITY / 1.5
velocity.x = direction * SPEED / 1
is_wall_jumping = true
func handle_movement_animation(dir):
if is_on_floor() and not is_attacking and !is_on_wall():
if velocity.length() == 0:
if is_crouching:
sprite.play("crouch")
else:
sprite.play("stand")
else:
sprite.play("run")
elif not is_on_floor() and not is_attacking and !is_on_wall():
sprite.play("jump")
func toggle_flip_sprite(direction):
if direction != 0 and is_on_floor() and !is_on_wall():
sprite.flip_h = direction < 0
func handle_attack_animation(delta):
if is_attacking and !is_on_wall():
if is_crouching:
sprite.play("crouch_attack")
else:
sprite.play("stand_attack")
if is_attacking and !is_on_floor() and !is_on_wall():
velocity.y += gravity * delta + 11 # Counteract gravity to prevent gaining height when attacking while jumping
func _on_animated_sprite_2d_animation_finished():
is_attacking = false
Good luck to anyone brave enough to try and help me, thank you. I will just try to move on to another part of the game if it’s too complicated for now.