improve floor normal checks even more
This commit is contained in:
@@ -1080,8 +1080,9 @@ _stop_on_landing = false
|
||||
metadata/_custom_type_script = "uid://ceyu5der8j8gq"
|
||||
|
||||
[node name="Trajectory17" type="Marker2D" parent="Trajectories"]
|
||||
position = Vector2(114, -2672)
|
||||
position = Vector2(58, -2024)
|
||||
script = ExtResource("4_74lek")
|
||||
flip_direction = true
|
||||
_steps = 190
|
||||
_jump = false
|
||||
metadata/_custom_type_script = "uid://ceyu5der8j8gq"
|
||||
|
||||
@@ -95,56 +95,37 @@ static func process_collision(
|
||||
return new_velocity
|
||||
|
||||
|
||||
static func shapecast(
|
||||
static func collide_shape(
|
||||
pos: Vector2,
|
||||
direction: Vector2,
|
||||
shape: Shape2D,
|
||||
space_state: PhysicsDirectSpaceState2D
|
||||
) -> bool:
|
||||
space_state: PhysicsDirectSpaceState2D,
|
||||
max_results: int = 1
|
||||
) -> Array[Vector2]:
|
||||
var floor_query := PhysicsShapeQueryParameters2D.new()
|
||||
floor_query.collision_mask = 1
|
||||
floor_query.transform = Transform2D(0, pos)
|
||||
floor_query.motion = direction
|
||||
floor_query.shape = shape
|
||||
floor_query.margin = -0.08
|
||||
return space_state.intersect_shape(floor_query).size() > 0
|
||||
return space_state.collide_shape(floor_query, max_results)
|
||||
|
||||
|
||||
static func raycast_down(
|
||||
pos: Vector2, shape: RectangleShape2D, space_state: PhysicsDirectSpaceState2D
|
||||
) -> Dictionary:
|
||||
var half_width := shape.size.x / 2.0
|
||||
var from := pos + Vector2.UP * (shape.size.x + 1)
|
||||
var to := pos + Vector2.DOWN * (shape.size.x + 1)
|
||||
|
||||
var result: Dictionary = {}
|
||||
|
||||
var query_center := PhysicsRayQueryParameters2D.create(from, to)
|
||||
var result_center := space_state.intersect_ray(query_center)
|
||||
if result_center and result_center["normal"] != Vector2.ZERO:
|
||||
if result_center["normal"] == Vector2.UP:
|
||||
return result_center
|
||||
result = result_center
|
||||
|
||||
var query_left := PhysicsRayQueryParameters2D.create(
|
||||
from + Vector2.LEFT * half_width, to + Vector2.LEFT * half_width
|
||||
)
|
||||
var result_left := space_state.intersect_ray(query_left)
|
||||
if result_left and result_left["normal"] != Vector2.ZERO:
|
||||
if result_left["normal"] == Vector2.UP:
|
||||
return result_left
|
||||
result = result_left
|
||||
|
||||
var query_right := PhysicsRayQueryParameters2D.create(
|
||||
from + Vector2.RIGHT * half_width, to + Vector2.RIGHT * half_width
|
||||
)
|
||||
var result_right := space_state.intersect_ray(query_right)
|
||||
if result_right and result_right["normal"] != Vector2.ZERO:
|
||||
if result_right["normal"] == Vector2.UP:
|
||||
return result_right
|
||||
result = result_right
|
||||
|
||||
return result
|
||||
static func raycast_floor_angle(
|
||||
collisions: Array[Vector2], space_state: PhysicsDirectSpaceState2D
|
||||
) -> float:
|
||||
var floor_angle: float = 0
|
||||
for i in range(1, collisions.size(), 2):
|
||||
var from := collisions[i] + Vector2.UP
|
||||
var to := collisions[i] + Vector2.DOWN
|
||||
var query := PhysicsRayQueryParameters2D.create(from, to)
|
||||
var result := space_state.intersect_ray(query)
|
||||
if result["normal"] != Vector2.ZERO:
|
||||
var normal := result["normal"] as Vector2
|
||||
floor_angle = -normal.angle_to(Vector2.UP)
|
||||
if is_zero_approx(floor_angle):
|
||||
return floor_angle
|
||||
return floor_angle
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
@@ -261,27 +242,27 @@ func _handle_collision() -> void:
|
||||
var is_on_wall_prev := _is_on_wall
|
||||
|
||||
var space_state := get_world_2d().direct_space_state
|
||||
_is_on_floor = shapecast(
|
||||
_shape.global_position, Vector2.DOWN, _shape.shape, space_state
|
||||
var floor_collisions := collide_shape(
|
||||
_shape.global_position, Vector2.DOWN, _shape.shape, space_state, 3
|
||||
)
|
||||
_is_on_wall = (
|
||||
shapecast(_shape.global_position, Vector2.LEFT, _shape.shape, space_state)
|
||||
or shapecast(_shape.global_position, Vector2.RIGHT, _shape.shape, space_state)
|
||||
)
|
||||
_is_on_ceiling = shapecast(
|
||||
var ceiling_collisions := collide_shape(
|
||||
_shape.global_position, Vector2.UP, _shape.shape, space_state
|
||||
)
|
||||
var wall_collisions := collide_shape(
|
||||
_shape.global_position, Vector2.LEFT, _shape.shape, space_state
|
||||
)
|
||||
if not wall_collisions:
|
||||
wall_collisions = collide_shape(
|
||||
_shape.global_position, Vector2.RIGHT, _shape.shape, space_state
|
||||
)
|
||||
|
||||
_is_on_floor = floor_collisions.size() > 0
|
||||
_is_on_ceiling = ceiling_collisions.size() > 0
|
||||
_is_on_wall = wall_collisions.size() > 0
|
||||
|
||||
var is_on_floor_changed := not is_on_floor_prev and _is_on_floor
|
||||
if is_on_floor_changed and _is_on_floor:
|
||||
var raycast_result := raycast_down(
|
||||
global_position, _shape.shape as RectangleShape2D, space_state
|
||||
)
|
||||
if raycast_result:
|
||||
var normal := raycast_result["normal"] as Vector2
|
||||
_floor_angle = -normal.angle_to(Vector2.UP)
|
||||
else:
|
||||
_floor_angle = 0
|
||||
if is_on_floor_changed:
|
||||
_floor_angle = raycast_floor_angle(floor_collisions, space_state)
|
||||
|
||||
var hit_floor := is_on_floor_changed and is_zero_approx(_floor_angle)
|
||||
var hit_slope := is_on_floor_changed and not is_zero_approx(_floor_angle)
|
||||
|
||||
@@ -250,29 +250,27 @@ func _draw() -> void:
|
||||
|
||||
var shape_pos := to_global(pos) + Vector2.UP * (_player_size.y / 2.0)
|
||||
|
||||
is_on_floor = Player.shapecast(
|
||||
shape_pos, Vector2.DOWN, _player_shape, space_state
|
||||
var floor_collisions := Player.collide_shape(
|
||||
shape_pos, Vector2.DOWN, _player_shape, space_state, 3
|
||||
)
|
||||
is_on_wall = (
|
||||
Player.shapecast(shape_pos, Vector2.LEFT, _player_shape, space_state)
|
||||
or Player.shapecast(
|
||||
shape_pos, Vector2.RIGHT, _player_shape, space_state
|
||||
)
|
||||
)
|
||||
is_on_ceiling = Player.shapecast(
|
||||
var ceiling_collisions := Player.collide_shape(
|
||||
shape_pos, Vector2.UP, _player_shape, space_state
|
||||
)
|
||||
var wall_collisions := Player.collide_shape(
|
||||
shape_pos, Vector2.LEFT, _player_shape, space_state
|
||||
)
|
||||
if not wall_collisions:
|
||||
wall_collisions = Player.collide_shape(
|
||||
shape_pos, Vector2.RIGHT, _player_shape, space_state
|
||||
)
|
||||
|
||||
is_on_floor = floor_collisions.size() > 0
|
||||
is_on_ceiling = ceiling_collisions.size() > 0
|
||||
is_on_wall = wall_collisions.size() > 0
|
||||
|
||||
var is_on_floor_changed := not is_on_floor_prev and is_on_floor
|
||||
if is_on_floor_changed and is_on_floor:
|
||||
var raycast_result := Player.raycast_down(
|
||||
to_global(pos), _player_shape, space_state
|
||||
)
|
||||
if raycast_result:
|
||||
var normal := raycast_result["normal"] as Vector2
|
||||
floor_angle = -normal.angle_to(Vector2.UP)
|
||||
else:
|
||||
floor_angle = 0
|
||||
if is_on_floor_changed:
|
||||
floor_angle = Player.raycast_floor_angle(floor_collisions, space_state)
|
||||
|
||||
var hit_floor := is_on_floor_changed and is_zero_approx(floor_angle)
|
||||
var hit_slope := is_on_floor_changed and not is_zero_approx(floor_angle)
|
||||
@@ -359,12 +357,16 @@ func _draw_collision_hit(pos: Vector2, side: Side, color: Color) -> void:
|
||||
|
||||
var is_left_or_right := side == SIDE_LEFT or side == SIDE_RIGHT
|
||||
var line_from := (
|
||||
(Vector2.UP if is_left_or_right else Vector2.LEFT) * _player_size.y / 2
|
||||
(Vector2.UP * _player_size.y)
|
||||
if is_left_or_right
|
||||
else (Vector2.LEFT * _player_size.x)
|
||||
)
|
||||
var line_to := (
|
||||
(Vector2.DOWN if is_left_or_right else Vector2.RIGHT) * _player_size.y / 2
|
||||
(Vector2.DOWN * _player_size.y)
|
||||
if is_left_or_right
|
||||
else (Vector2.RIGHT * _player_size.x)
|
||||
)
|
||||
draw_dashed_line(pos + line_from, pos + line_to, color)
|
||||
draw_dashed_line(pos + line_from / 2, pos + line_to / 2, color)
|
||||
|
||||
|
||||
func _draw_arrowhead(from: Vector2, to: Vector2, color: Color) -> void:
|
||||
|
||||
Reference in New Issue
Block a user