Godot 4.5
I need some help with this code. I can’t get the player to step up a block automatically. The player has a 36x18 collision box and the tiles are 18x18. It’d also be nice for you to clean up my code if it’s messy, I’m new to gdscript
Code:
extends CharacterBody2D
— Visual Node Reference —
@onready var visual_node = $AnimatedSprite2D
— Sound Nodes —
@onready var chase_sound_player = $ChaseSoundPlayer
— Exported variables —
@export var speed: float = 45
@export var chase_radius: float = 200.0
@export var step_height: float = 12.0 # Max height the predator can step up
@export var step_width: float = 16.0 # How far forward to check for a step
— Internal variables —
var gravity: float = ProjectSettings.get_setting(“physics/2d/default_gravity”)
var wander_timer: float = 0.0
var wander_dir: float = 0.0 # horizontal wandering direction
func _ready() → void:
add_to_group(“Predator”)
randomize()
_set_new_wander_direction()
func _physics_process(delta: float) → void:
# — 1. Determine horizontal velocity —
var current_velocity_x = 0.0
var nearest_species = _find_nearest_species()
var distance_to_species = INF
var is_chasing = false
if nearest_species:
distance_to_species = global_position.distance_to(nearest_species.global_position)
if nearest_species and distance_to_species <= chase_radius:
current_velocity_x = _chase_target_x_direction(nearest_species) * speed
is_chasing = true
else:
current_velocity_x = _wander(delta) * speed
is_chasing = false
# --- 2. Flip sprite and play chase sound ---
if current_velocity_x > 0:
visual_node.flip_h = true
elif current_velocity_x < 0:
visual_node.flip_h = false
if is_chasing:
_play_chase_sound()
else:
_stop_chase_sound()
# --- 3. Step-Up Check ---
var direction = sign(current_velocity_x)
if direction != 0 and is_on_floor():
_try_step_up(direction)
# --- 4. Apply Gravity ---
if not is_on_floor():
velocity.y += gravity * delta
else:
if velocity.y >= 0:
velocity.y = 0
# --- 5. Set horizontal velocity and move ---
velocity.x = current_velocity_x
move_and_slide()
— Step-Up —
func _try_step_up(direction: float) → void:
var shape_half_width = 18.0 # Half of 36px collider width
var ray_offset = shape_half_width + 1.0
# 1. Check for wall (low ray)
var low_ray_start = global_position + Vector2(direction * ray_offset, -step_height / 2.0)
var low_ray_end = low_ray_start + Vector2(direction * step_width, 0)
var params_low = PhysicsRayQueryParameters2D.create(low_ray_start, low_ray_end)
params_low.exclude = [self]
var result_low = get_world_2d().direct_space_state.intersect_ray(params_low)
if result_low.is_empty():
return # no wall, so not a step
# 2. Check clearance (high ray)
var high_ray_start = global_position + Vector2(direction * ray_offset, -step_height - 1.0)
var high_ray_end = high_ray_start + Vector2(direction * step_width, 0)
var params_high = PhysicsRayQueryParameters2D.create(high_ray_start, high_ray_end)
params_high.exclude = [self]
var result_high = get_world_2d().direct_space_state.intersect_ray(params_high)
if not result_high.is_empty():
return # blocked above, can't step
# 3. Step up slightly
global_position.y -= step_height + 1.0
— Behavior Functions —
func _find_nearest_species() → Node2D:
var nearest = null
var nearest_dist = INF
for species in get_tree().get_nodes_in_group(“Species”):
var dist = global_position.distance_to(species.global_position)
if dist < nearest_dist:
nearest_dist = dist
nearest = species
return nearest
func _chase_target_x_direction(target: Node2D) → float:
var dir = (target.global_position - global_position).normalized()
return sign(dir.x)
func _wander(delta: float) → float:
wander_timer -= delta
if wander_timer <= 0:
_set_new_wander_direction()
return wander_dir
func _set_new_wander_direction() → void:
wander_dir = [-1, 1].pick_random()
wander_timer = randf_range(1.0, 3.0)
— Sound Functions —
func _play_chase_sound():
if not chase_sound_player.playing:
chase_sound_player.play()
func _stop_chase_sound():
chase_sound_player.stop()