1
\$\begingroup\$

enter image description hereIm using raycast to detect if a block is to my side. I can use raycast to see if i need to climb stairs but the transition is bad. I immediately reach the top of the stairs when trying to go on them.

extends KinematicBody2D signal collected const ACCELERATION = 200 const GRAVITY = 10 var JUMP = -400 var SPACE_JUMP = JUMP * 1.25 var LEDGE_JUMP = JUMP * .75 var state = "idle" var prev_state = "idle" var velocity = Vector2.ZERO var acceleration = Vector2(200,0) var deceleration = Vector2(500,0) var terminal_velocity = Vector2(200,0) onready var collisionShape2D = $CollisionShape2D var gravity = Vector2(0,10) var jump = -400 var timer = 0 var facing = 1 var threshold = .5 var floor_normal = Vector2(0,-1) func _ready(): collisionShape2D.shape.radius = 28 #collisionShape2D.shape.extents = Vector2(31.9,31.9) func _physics_process(delta): timer += delta var ax = Input.get_joy_axis(0,0) var ay = Input.get_joy_axis(0,1) var space_rid = get_world_2d().space var space_state = Physics2DServer.space_get_direct_state(space_rid) var ray_down = space_state.intersect_ray(global_position, global_position + Vector2(0,32),[self]) var ray_side1 = space_state.intersect_ray(global_position, global_position + Vector2(facing*32,-16),[self]) var ray_side2 = space_state.intersect_ray(global_position, global_position + Vector2(facing*32,0),[self]) var ray_up = space_state.intersect_ray(global_position + Vector2(facing*32,-32), global_position + Vector2(facing*32,-64)) if ay > .25 and state == "ledge_grab": state = "jump" gravity.y = GRAVITY elif ay > .25 and state == "idle": state = "ball" collisionShape2D.shape.radius = 14 elif ay < -.25 and state == "ball" and not ray_up.has("collider"): state = "idle" collisionShape2D.shape.radius = 28 if is_on_floor(): if state == "jump": state = "idle" acceleration.x = ACCELERATION if abs(ax) < .1: ax = 0 if state == "moving": state = "idle" else: if state == "idle": state = "moving" if ax < -threshold: facing = -1 velocity.x -= acceleration.x * delta elif ax > threshold: facing = 1 velocity.x += acceleration.x * delta else: velocity.x += -sign(velocity.x) * deceleration.x * delta if abs(velocity.x) < 1: velocity.x = 0 velocity.x = clamp(velocity.x,-terminal_velocity.x,terminal_velocity.x) velocity += gravity if not ray_up.has("collider") and ray_side1.has("collider") and state != "ledge_grab" and state != "jump": state = "ledge_grab" position.y = ray_side1.metadata.y * 32 + 32 gravity = Vector2.ZERO velocity = Vector2.ZERO position.x -= facing if not ray_up.has("collider") and ray_side2.has("collider") and ray_down.has("collider"): #What should i do here? position.y -= 32 position.x += facing * 24 if state == "idle" or state == "moving" or state == "jump" or state == "ball": velocity = move_and_slide(velocity,floor_normal) var collision = move_and_collide(velocity * delta,true,true,true) if collision: if collision.collider.name == "StaticBody2D": jump = SPACE_JUMP collision.collider.free() print(state) func jump(): if is_on_floor() and state != "ball": velocity.y = jump acceleration.x += -jump state = "jump" if state == "ledge_grab": gravity.y = GRAVITY velocity.y = LEDGE_JUMP acceleration.x += -jump state = "jump" func _unhandled_input(event): if event is InputEventJoypadButton: if event.pressed and event.button_index == 0: jump() 
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Keep in mind that an image is worth a thousand words! You could add a screenshot or an animated gif showing your current situation. \$\endgroup\$ Commented Jun 28, 2020 at 1:33
  • \$\begingroup\$ From the looks of it, the stair colliders are currently squares, but it might be easier if you made them right triangles instead. That way, internally they're essentially slopes, and you shouldn't need any additional logic to support going up them. \$\endgroup\$ Commented Jun 28, 2020 at 4:28
  • \$\begingroup\$ This might work. I initially tried slopes but the player still couldnt climb them. Not enough force in the right direction so maybe i need to adjust the velocity vector when colliding with slopes. \$\endgroup\$ Commented Jun 28, 2020 at 5:22

1 Answer 1

4
\$\begingroup\$

Make the stairs a slope:

You wouldn't have to add any code, only another collision shape with a ray, so the player doesn't slide down the slope. This method would result in visible clipping and wouldn't look that great.

Teleport the player:

Like you already did in code, you could test if there is a stair in front of the player, and if there is, teleport him on top of the stair. That doesn't look very elegant though.

Animate the player with Tweens:

Using tweens to animate stair stepping

I added a raycast to find the position of the stair, then used this code to animate the player:

if not ray_up.has("collider") and ray_side2.has("collider") and ray_down.has("collider") and state != "walking_stair" and $RayCast2D.get_collider(): state = "walking_stair" var stair_pos = $RayCast2D.get_collision_point() stair_pos.y -= 2 $Tween.interpolate_property(self, "global_position", global_position, Vector2(global_position.x, stair_pos.y), .1) $Tween.start() yield($Tween, "tween_completed") $Tween.interpolate_property(self, "global_position", global_position, stair_pos, .1) $Tween.start() yield($Tween, "tween_completed") global_position = stair_pos state = "idle" 
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.