I had to do some messing about with the layers and raycast checks to keep my character from being able to jump in the water. Might just be me since I have the water on a different tilemap than the base grass but I thought I'd mention it. Great video as usual.
edit: i found a solution, replace the part where you set up your raycast.cast_to (or raycast.target_position if you're on godot 4) with this: if percent_moved_to_next_tile == 0.0: Ray.target_position = desired_step Ray.force_raycast_update() ledge_ray.target_position = desired_step ledge_ray.force_raycast_update() door_ray.target_position = desired_step door_ray.force_raycast_update() else: Ray.target_position = Vector2.ZERO Ray.force_raycast_update() ledge_ray.target_position = Vector2.ZERO ledge_ray.force_raycast_update() door_ray.target_position = Vector2.ZERO door_ray.force_raycast_update() what this will do is only cast the ray if you only just started moving, preventing the raycasts from casting mid movement there seems to be a bug, probably exclusive to godot 4, which is causing the player to jump the ledges by 1 tile if they walk towards it from 2 or more tiles away, and the same thing happens with entering doors in the next video. anyone got a fix? it doesn't seem to happen if i am holding shift (which i have set up to make my movement speed 8.0 rather than 4.0)
as an addition to my edit above, for future proofing and saving you a lot of editing, i prefer to use: if percent_moved_to_next_tile == 0.0: cast_rays(desired_step) else: cast_rays(Vector2.ZERO) and then have the following function: func cast_rays(target): Ray.target_position = target Ray.force_raycast_update() ledge_ray.target_position = target ledge_ray.force_raycast_update() door_ray.target_position = target door_ray.force_raycast_update()
The solution I found for entering doors was to include your solution, as well as add a boolean at the top of the Player script for when we are entering a door. For the changes to func move(), it looks something like this: var desired_step: Vector2 = input_direction * TILE_SIZE / 2 if percent_moved_to_next_tile == 0.0: ray.target_position = desired_step ray.force_raycast_update() ledge_ray.target_position = desired_step ledge_ray.force_raycast_update() door_ray.target_position = desired_step door_ray.force_raycast_update() else: ray.target_position = Vector2.ZERO ray.force_raycast_update() ledge_ray.target_position = Vector2.ZERO ledge_ray.force_raycast_update() door_ray.target_position = Vector2.ZERO door_ray.force_raycast_update() print("Door Detected: {door}, Percent Moved: {pcnt}".format({"door":door_ray.is_colliding(), "pcnt": percent_moved_to_next_tile})) if door_ray.is_colliding() or entering_door: # CHANGE HERE if percent_moved_to_next_tile == 0.0: emit_signal("player_entering_door_signal") entering_door = true # CHANGE HERE percent_moved_to_next_tile += walk_speed * delta if percent_moved_to_next_tile > 1.0: position = initial_position + (input_direction * TILE_SIZE) percent_moved_to_next_tile = 0.0 is_moving = false stop_input = true entering_door = false # CHANGE HERE $AnimationPlayer.play("Disappear") else: position = initial_position + (input_direction * TILE_SIZE * percent_moved_to_next_tile) Hopefully this helps someone in the future, took me hours to find the issue. In Godot4 it seems that both "door_ray.is_colliding()" and "percent_moved_to_next_tile >= 1.0" can be true at the same time, making the player enter the door while only moving into the cell in front of the door. With your changes, it stops is_colliding from being true at that point, but it stops it from catching that it should also be true for when we actually want it to be true lol. So one way makes you "exit" without entering, and the other makes you "enter" without exiting. My fix seems to fix the issue.
btw i could have fix the bug you said about jumping when 1 tile away from ledge. issue is with the float values, sometimes percent_move_to_next_tile were more than one, 1.067 in deep. and yeah maybe it is a bug iin GDscript, because this fails sometimes if(percent_moved >= 1): when percent is 1.067 to fix it simply on the move func: func move(delta) -> void: percent_moved += SPEED * delta; if(!jumping_over_ledge && percent_moved >= .99): percent_moved = 1.0 this also prevents auto jumping too fast were theres 1 ledge, void, 1 ledge and you can keep jumping :D :D PD: still wondering why you need that raycast extra code to make it work, it works to me without it
This video series is really helpful toward my project. I just have a problem: when I jump over a ledge, the landing dust effect always appears to be 1 tile to the left of where I started jumping. Can you help me?
if you place a TallGrass 2 tiles away and then jump the ledge, the grass plays the stepped animation despite you still 1 tile away from it. to solve it simply check againt 1.99 and not 2, this means, never reach the tile by 0.1, so the grass effect doesnt trigger if(percent_moved >= 1.99): position = start_position + (TILE_SIZE * input_direction * 2); percent_moved = 0; is_moving = false; jumping_over_ledge = false; OR just update the Y curvature while jumping initial_position + (-0.96 - 0.57 * new_position + 0.05 * pow(new_position, 2)); that was overlapping (initial_position.y + 32) EX: initial_position_y = 64 log after jumping (272, 64) ....... ....... ....... (272, 82.24) (272, 84.46222) (272, 86.79823) (272, 89.248) (272, 91.81155) (272, 94.48889) (272, 97.28) (272, 96) 64 + 2 tiles should be 96, that's ok, but if you look, it reach 97.28, making overlapping the area and triggering the grass effect 0.57 is the way to go, since it returns the last two position the same (272, 85.68889) (272, 88.096) (272, 90.61689) (272, 93.25156) (272, 96) (272, 96) PD: you can jump 2 ledges in a row, its weird XD, anyway this is more a level design, who would put 2 ledges side by side? :D PD2: i tried to fix the bug that you can jump over 2 ledges, the idea was to move the ledge_ray position.y to +=16 to hit the next tile and check if it colliding, if true it means there a ledge 1 tile away the current ledge ypu are trying to jump, but in the end and couldnt figure it out, since you need to reset the position aswell... if someone finds a solution for this, please post it!
Hello, Ive been having quite a lot of trouble with ledge jumping as any other solid object in my tilemap I can jump over(Even if it's on a different tilemap) and I don't know how to fix this, I looked on the github repo and I have te exact same code, do you know how to fix this.
Your LedgeRayCast2D's position is probably not centered on the Player like BlockingRayCast2D is; instead of creating a new RayCast2D, just duplicate the existing one(BlockingRayCast2D) and modify it's name to LedgeRayCast2D and collision mask to the Ledge layer
You have the best description of bitmasking for autotile. I have struggled with it for such a long time. Much appreciated.
I had to do some messing about with the layers and raycast checks to keep my character from being able to jump in the water. Might just be me since I have the water on a different tilemap than the base grass but I thought I'd mention it. Great video as usual.
Great series so far. Looking better each episode
Great video again! Thanks Arkeve!
edit: i found a solution, replace the part where you set up your raycast.cast_to (or raycast.target_position if you're on godot 4) with this:
if percent_moved_to_next_tile == 0.0:
Ray.target_position = desired_step
Ray.force_raycast_update()
ledge_ray.target_position = desired_step
ledge_ray.force_raycast_update()
door_ray.target_position = desired_step
door_ray.force_raycast_update()
else:
Ray.target_position = Vector2.ZERO
Ray.force_raycast_update()
ledge_ray.target_position = Vector2.ZERO
ledge_ray.force_raycast_update()
door_ray.target_position = Vector2.ZERO
door_ray.force_raycast_update()
what this will do is only cast the ray if you only just started moving, preventing the raycasts from casting mid movement
there seems to be a bug, probably exclusive to godot 4, which is causing the player to jump the ledges by 1 tile if they walk towards it from 2 or more tiles away, and the same thing happens with entering doors in the next video. anyone got a fix? it doesn't seem to happen if i am holding shift (which i have set up to make my movement speed 8.0 rather than 4.0)
as an addition to my edit above, for future proofing and saving you a lot of editing, i prefer to use:
if percent_moved_to_next_tile == 0.0:
cast_rays(desired_step)
else:
cast_rays(Vector2.ZERO)
and then have the following function:
func cast_rays(target):
Ray.target_position = target
Ray.force_raycast_update()
ledge_ray.target_position = target
ledge_ray.force_raycast_update()
door_ray.target_position = target
door_ray.force_raycast_update()
The solution I found for entering doors was to include your solution, as well as add a boolean at the top of the Player script for when we are entering a door. For the changes to func move(), it looks something like this:
var desired_step: Vector2 = input_direction * TILE_SIZE / 2
if percent_moved_to_next_tile == 0.0:
ray.target_position = desired_step
ray.force_raycast_update()
ledge_ray.target_position = desired_step
ledge_ray.force_raycast_update()
door_ray.target_position = desired_step
door_ray.force_raycast_update()
else:
ray.target_position = Vector2.ZERO
ray.force_raycast_update()
ledge_ray.target_position = Vector2.ZERO
ledge_ray.force_raycast_update()
door_ray.target_position = Vector2.ZERO
door_ray.force_raycast_update()
print("Door Detected: {door}, Percent Moved: {pcnt}".format({"door":door_ray.is_colliding(), "pcnt": percent_moved_to_next_tile}))
if door_ray.is_colliding() or entering_door: # CHANGE HERE
if percent_moved_to_next_tile == 0.0:
emit_signal("player_entering_door_signal")
entering_door = true # CHANGE HERE
percent_moved_to_next_tile += walk_speed * delta
if percent_moved_to_next_tile > 1.0:
position = initial_position + (input_direction * TILE_SIZE)
percent_moved_to_next_tile = 0.0
is_moving = false
stop_input = true
entering_door = false # CHANGE HERE
$AnimationPlayer.play("Disappear")
else:
position = initial_position + (input_direction * TILE_SIZE * percent_moved_to_next_tile)
Hopefully this helps someone in the future, took me hours to find the issue. In Godot4 it seems that both "door_ray.is_colliding()" and "percent_moved_to_next_tile >= 1.0" can be true at the same time, making the player enter the door while only moving into the cell in front of the door. With your changes, it stops is_colliding from being true at that point, but it stops it from catching that it should also be true for when we actually want it to be true lol. So one way makes you "exit" without entering, and the other makes you "enter" without exiting. My fix seems to fix the issue.
what was the original error? i could manage to make it work wthout what you mentioning
btw i could have fix the bug you said about jumping when 1 tile away from ledge.
issue is with the float values, sometimes percent_move_to_next_tile were more than one, 1.067 in deep. and yeah maybe it is a bug iin GDscript, because this fails sometimes
if(percent_moved >= 1): when percent is 1.067
to fix it simply on the move func:
func move(delta) -> void:
percent_moved += SPEED * delta;
if(!jumping_over_ledge && percent_moved >= .99):
percent_moved = 1.0
this also prevents auto jumping too fast were theres 1 ledge, void, 1 ledge and you can keep jumping :D :D
PD: still wondering why you need that raycast extra code to make it work, it works to me without it
GOOD VIDEO AS ALWAYS!! VERY INSPIRING 👍👍
YESSSSSSSSSS
What are some ways to make jumping left and right work setup gfx for it but can't think of a way to do it.
This video series is really helpful toward my project. I just have a problem: when I jump over a ledge, the landing dust effect always appears to be 1 tile to the left of where I started jumping. Can you help me?
if you place a TallGrass 2 tiles away and then jump the ledge, the grass plays the stepped animation despite you still 1 tile away from it. to solve it simply check againt 1.99 and not 2, this means, never reach the tile by 0.1, so the grass effect doesnt trigger
if(percent_moved >= 1.99):
position = start_position + (TILE_SIZE * input_direction * 2);
percent_moved = 0;
is_moving = false;
jumping_over_ledge = false;
OR just update the Y curvature while jumping
initial_position + (-0.96 - 0.57 * new_position + 0.05 * pow(new_position, 2));
that was overlapping (initial_position.y + 32)
EX: initial_position_y = 64
log after jumping
(272, 64)
.......
.......
.......
(272, 82.24)
(272, 84.46222)
(272, 86.79823)
(272, 89.248)
(272, 91.81155)
(272, 94.48889)
(272, 97.28)
(272, 96)
64 + 2 tiles should be 96, that's ok, but if you look, it reach 97.28, making overlapping the area and triggering the grass effect
0.57 is the way to go, since it returns the last two position the same
(272, 85.68889)
(272, 88.096)
(272, 90.61689)
(272, 93.25156)
(272, 96)
(272, 96)
PD: you can jump 2 ledges in a row, its weird XD, anyway this is more a level design, who would put 2 ledges side by side? :D
PD2: i tried to fix the bug that you can jump over 2 ledges, the idea was to move the ledge_ray position.y to +=16 to hit the next tile and check if it colliding, if true it means there a ledge 1 tile away the current ledge ypu are trying to jump, but in the end and couldnt figure it out, since you need to reset the position aswell... if someone finds a solution for this, please post it!
Hello, Ive been having quite a lot of trouble with ledge jumping as any other solid object in my tilemap I can jump over(Even if it's on a different tilemap) and I don't know how to fix this, I looked on the github repo and I have te exact same code, do you know how to fix this.
This indeed also makes me go yesssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
For Godot 4 i use this in the move function and it's working :
func move(delta):
var desired_step: Vector2 = input_direction * TILE_SIZE / 2
ray_cast_2d.target_position = desired_step
ray_cast_2d.force_raycast_update()
ledge_ray_cast_2d.target_position = desired_step
ledge_ray_cast_2d.force_raycast_update()
if jumping_over_ledge:
handle_ledge_jump(delta)
elif ledge_ray_cast_2d.is_colliding() and input_direction == Vector2(0, 1): # Detect ledge
start_ledge_jump()
elif ledge_ray_cast_2d.is_colliding():
percent_moved_to_next_tile = 0.0
is_moving = false
elif !ray_cast_2d.is_colliding(): # Regular movement
handle_regular_movement(delta)
else: # Collision detected
percent_moved_to_next_tile = 0.0
is_moving = false
func handle_ledge_jump(delta):
percent_moved_to_next_tile += jump_speed * delta
if percent_moved_to_next_tile >= 2.0:
position = initial_position + (input_direction * TILE_SIZE * 2)
percent_moved_to_next_tile = 0.0
is_moving = false
jumping_over_ledge = false
shadow.visible = false
var dust_effect = LandingDustEffect.instantiate()
dust_effect.position = position
get_tree().current_scene.add_child(dust_effect)
else:
# Parabolic motion for the ledge jump
shadow.visible = true
var input = input_direction.y * TILE_SIZE * percent_moved_to_next_tile
position.y = initial_position.y + (-0.96 - 0.53 * input + 0.05 * pow(input, 2))
jumping_over_ledge = true
func start_ledge_jump():
jumping_over_ledge = true
percent_moved_to_next_tile = 0.0
func handle_regular_movement(delta):
if percent_moved_to_next_tile == 0:
emit_signal("player_moving_signal")
percent_moved_to_next_tile += walk_speed * delta
if percent_moved_to_next_tile >= 1.0:
position = initial_position + (TILE_SIZE * input_direction)
percent_moved_to_next_tile = 0.0
is_moving = false
emit_signal("player_stopped_signal")
else:
position = initial_position + (TILE_SIZE * input_direction * percent_moved_to_next_tile)
sorry sir, but if my player is facing down and it back to ledge, it can still jump to y down, how can i fix it?
Your LedgeRayCast2D's position is probably not centered on the Player like BlockingRayCast2D is; instead of creating a new RayCast2D, just duplicate the existing one(BlockingRayCast2D) and modify it's name to LedgeRayCast2D and collision mask to the Ledge layer
👍👍👍
Hey^^ i think you didn't see my comment on your First Video on this game it would be really nice of you if you could help 😅
Oh sorry about that, replied to the comment. Try emailing me your issue/code to sketchthedev@gmail.com.