Compare commits

...

2 Commits

Author SHA1 Message Date
08668de36a make trajectory collision logic the same as player logic 2025-08-22 23:35:20 +10:00
8023b9d035 fix freemove velocity 2025-08-22 23:34:42 +10:00
4 changed files with 77 additions and 63 deletions

View File

@@ -12,6 +12,7 @@ size = Vector2(18, 26)
[node name="Player" type="CharacterBody2D" node_paths=PackedStringArray("_trajectory", "_shape")]
collision_layer = 16
floor_stop_on_slope = false
floor_max_angle = 1.55334
floor_snap_length = 0.0
script = ExtResource("1_g2els")

View File

@@ -1067,9 +1067,9 @@ _steps = 79
metadata/_custom_type_script = "uid://ceyu5der8j8gq"
[node name="Trajectory16" type="Marker2D" parent="Trajectories"]
position = Vector2(271, -2253)
position = Vector2(119, -2686)
script = ExtResource("4_74lek")
flip = true
_steps = 104
_steps = 190
_jump = false
_stop_on_landing = false
metadata/_custom_type_script = "uid://ceyu5der8j8gq"

View File

@@ -160,7 +160,7 @@ func _physics_process(delta: float) -> void:
. get_vector("move_left", "move_right", "move_up", "move_down")
. normalized()
)
_velocity = (
velocity = (
direction * _jump_speed * (4.0 if Input.is_action_pressed("jump") else 1.0)
)
move_and_slide()

View File

@@ -98,6 +98,10 @@ const JUMP_REFERENCE: PackedFloat32Array = [
set(value):
_jump = value
queue_redraw()
@export var _walk: bool = false:
set(value):
_walk = value
queue_redraw()
@export var _stop_on_landing: bool = true:
set(value):
_stop_on_landing = value
@@ -190,21 +194,24 @@ func _draw() -> void:
)
draw_line(pos, pos + charge_strength_line, _charge_color)
var pos_prev := pos
var pos_min := pos
var pos_max := pos
var velocity: Vector2
var is_on_floor: bool = false
var direction: float = -1.0 if flip else 1.0
var jump_released: bool = false
var floor_angle: float = 0
var is_on_floor: bool = false
var is_on_wall: bool = false
var is_on_ceiling: bool = false
var pos_prev := pos
var space_state := get_world_2d().direct_space_state
for i in range(_steps):
pos += velocity * delta
if is_on_floor and is_zero_approx(floor_angle) and _stop_on_landing:
break
jump_released = i == 0 and _jump
velocity = (
Player
. process_movement(
@@ -215,7 +222,7 @@ func _draw() -> void:
direction,
false,
charge_strength,
i == 0 and _jump,
jump_released,
_walk_speed,
_jump_speed,
_jump_force,
@@ -224,74 +231,80 @@ func _draw() -> void:
)
)
pos += velocity * delta
if _do_collisions:
var motion_proportion := _cast_motion(pos_prev, pos, space_state)
if not is_equal_approx(motion_proportion, 1.0):
var motion := (pos - pos_prev) * motion_proportion
pos = pos_prev + motion
var hit_slope: bool = false
var hit_floor: bool = false
var hit_ceiling: bool = false
var shape_pos := to_global(pos) + Vector2.UP * (_player_size.y / 2.0)
# hitting floor
if velocity.y >= 0:
var result := Player.shapecast(
shape_pos, Vector2.DOWN, _player_shape, space_state
)
if result:
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)
hit_floor = is_zero_approx(floor_angle)
hit_slope = not is_zero_approx(floor_angle)
else:
is_on_floor = false
# hitting ceiling
if velocity.y < 0:
var result := Player.shapecast(
shape_pos, Vector2.UP, _player_shape, space_state
)
if result:
hit_ceiling = true
var is_on_floor_prev := is_on_floor
var is_on_ceiling_prev := is_on_ceiling
var is_on_wall_prev := is_on_wall
var hit_wall: bool = not hit_floor and not hit_slope and not hit_ceiling
var shape_pos := to_global(pos) + Vector2.UP * (_player_size.y / 2.0)
velocity = (
Player
. process_collision(
velocity,
hit_floor,
hit_slope,
hit_ceiling,
hit_wall,
floor_angle,
_wall_bounce_velocity_loss,
)
is_on_floor = Player.shapecast(
shape_pos, Vector2.DOWN, _player_shape, space_state
)
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(
shape_pos, Vector2.UP, _player_shape, space_state
)
if hit_floor or hit_slope:
is_on_floor = true
_draw_collision_hit(pos, SIDE_BOTTOM, _floor_hit_color)
if hit_ceiling:
_draw_collision_hit(pos, SIDE_TOP, _ceiling_hit_color)
if hit_wall:
_draw_collision_hit(
pos,
SIDE_LEFT if velocity.x > 0 else SIDE_RIGHT,
_wall_hit_color
)
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
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)
var hit_ceiling := not is_on_ceiling_prev and is_on_ceiling
var hit_wall := (
not is_on_wall_prev
and is_on_wall
and (not is_on_floor or jump_released)
and not is_zero_approx(velocity.x)
)
velocity = (
Player
. process_collision(
velocity,
hit_floor,
hit_slope,
hit_ceiling,
hit_wall,
floor_angle,
_wall_bounce_velocity_loss,
)
)
if hit_floor or hit_slope:
_draw_collision_hit(pos, SIDE_BOTTOM, _floor_hit_color)
if hit_ceiling:
_draw_collision_hit(pos, SIDE_TOP, _ceiling_hit_color)
if hit_wall:
_draw_collision_hit(
pos, SIDE_LEFT if velocity.x > 0 else SIDE_RIGHT, _wall_hit_color
)
if i % 10 == 0 && i > 0:
_draw_arrowhead(pos_prev, pos, _line_color)
points.append(pos)
pos_prev = pos
pos_min = pos_min.min(pos)
pos_max = pos_max.max(pos)
if _draw_hitbox:
draw_rect(