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\$
  • 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\$ – Vaillancourt Jun 28 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\$ – crass_sandwich Jun 28 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\$ – dylan Jun 28 at 5:22
3
\$\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"
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.