fix walking with pots /pushing into walls etc
This commit is contained in:
@@ -288,7 +288,77 @@ func _physics_process(delta: float) -> void:
|
|||||||
# Sync invulnerability cleared to clients
|
# Sync invulnerability cleared to clients
|
||||||
if multiplayer.is_server():
|
if multiplayer.is_server():
|
||||||
sync_invulnerability.rpc(false)
|
sync_invulnerability.rpc(false)
|
||||||
move_and_collide(velocity * delta)
|
# Check for collisions to prevent pushing ungrabed objects
|
||||||
|
# Handle diagonal movement: try moving in each direction separately to allow sliding
|
||||||
|
var movement = velocity * delta
|
||||||
|
if movement.length() > 0:
|
||||||
|
# Store original position to test both directions from the same starting point
|
||||||
|
var original_position = global_position
|
||||||
|
var allowed_movement = Vector2.ZERO
|
||||||
|
|
||||||
|
# Test X movement
|
||||||
|
if abs(movement.x) > 0.01:
|
||||||
|
var x_movement = Vector2(movement.x, 0)
|
||||||
|
var collision_x = move_and_collide(x_movement)
|
||||||
|
var x_actual_movement = global_position - original_position
|
||||||
|
|
||||||
|
if collision_x:
|
||||||
|
var collider_x = collision_x.get_collider()
|
||||||
|
if collider_x != null:
|
||||||
|
var is_pot_x = "is_being_grabbed" in collider_x or "is_being_lifted" in collider_x
|
||||||
|
var is_player_x = "is_player" in collider_x and collider_x.is_player
|
||||||
|
# If it's an ungrabed pot/player, move back and don't allow X movement
|
||||||
|
if ((is_pot_x and not collider_x.is_being_grabbed and not collider_x.is_being_lifted) or (is_player_x and collider_x != self)):
|
||||||
|
if not (grabbed_entity == collider_x or held_entity == collider_x):
|
||||||
|
# Move back to original position
|
||||||
|
global_position = original_position
|
||||||
|
allowed_movement.x = 0
|
||||||
|
else:
|
||||||
|
# We're grabbing it, allow the movement
|
||||||
|
allowed_movement.x = x_actual_movement.x
|
||||||
|
else:
|
||||||
|
# It's a wall - use the actual movement (move_and_collide handled sliding)
|
||||||
|
allowed_movement.x = x_actual_movement.x
|
||||||
|
else:
|
||||||
|
# No collision, X movement succeeded
|
||||||
|
allowed_movement.x = x_actual_movement.x
|
||||||
|
|
||||||
|
# Reset to original position for Y test
|
||||||
|
global_position = original_position
|
||||||
|
|
||||||
|
# Test Y movement
|
||||||
|
if abs(movement.y) > 0.01:
|
||||||
|
var y_movement = Vector2(0, movement.y)
|
||||||
|
var collision_y = move_and_collide(y_movement)
|
||||||
|
var y_actual_movement = global_position - original_position
|
||||||
|
|
||||||
|
if collision_y:
|
||||||
|
var collider_y = collision_y.get_collider()
|
||||||
|
if collider_y != null:
|
||||||
|
var is_pot_y = "is_being_grabbed" in collider_y or "is_being_lifted" in collider_y
|
||||||
|
var is_player_y = "is_player" in collider_y and collider_y.is_player
|
||||||
|
# If it's an ungrabed pot/player, move back and don't allow Y movement
|
||||||
|
if ((is_pot_y and not collider_y.is_being_grabbed and not collider_y.is_being_lifted) or (is_player_y and collider_y != self)):
|
||||||
|
if not (grabbed_entity == collider_y or held_entity == collider_y):
|
||||||
|
# Move back to original position
|
||||||
|
global_position = original_position
|
||||||
|
allowed_movement.y = 0
|
||||||
|
else:
|
||||||
|
# We're grabbing it, allow the movement
|
||||||
|
allowed_movement.y = y_actual_movement.y
|
||||||
|
else:
|
||||||
|
# It's a wall - use the actual movement (move_and_collide handled sliding)
|
||||||
|
allowed_movement.y = y_actual_movement.y
|
||||||
|
else:
|
||||||
|
# No collision, Y movement succeeded
|
||||||
|
allowed_movement.y = y_actual_movement.y
|
||||||
|
|
||||||
|
# Reset to original position
|
||||||
|
global_position = original_position
|
||||||
|
|
||||||
|
# Apply the combined allowed movement
|
||||||
|
if allowed_movement.length() > 0.01:
|
||||||
|
move_and_collide(allowed_movement)
|
||||||
else:
|
else:
|
||||||
# Client also needs to decrement knockback_timer for visual effects
|
# Client also needs to decrement knockback_timer for visual effects
|
||||||
if knockback_timer > 0:
|
if knockback_timer > 0:
|
||||||
|
|||||||
@@ -226,6 +226,8 @@ func _physics_process(delta: float) -> void:
|
|||||||
if "locked_grab_direction" in holder and holder.locked_grab_direction != Vector2.ZERO:
|
if "locked_grab_direction" in holder and holder.locked_grab_direction != Vector2.ZERO:
|
||||||
locked_dir = holder.locked_grab_direction.normalized()
|
locked_dir = holder.locked_grab_direction.normalized()
|
||||||
|
|
||||||
|
# Calculate desired movement based on push/pull
|
||||||
|
var desired_movement = Vector2.ZERO
|
||||||
if locked_dir != Vector2.ZERO:
|
if locked_dir != Vector2.ZERO:
|
||||||
# Project player's movement onto the push/pull direction
|
# Project player's movement onto the push/pull direction
|
||||||
var movement_along_axis = player_movement.project(locked_dir)
|
var movement_along_axis = player_movement.project(locked_dir)
|
||||||
@@ -236,18 +238,41 @@ func _physics_process(delta: float) -> void:
|
|||||||
if is_pushing:
|
if is_pushing:
|
||||||
# PUSHING: Pot moves first, ahead of player
|
# PUSHING: Pot moves first, ahead of player
|
||||||
# Move pot by slightly more than player movement so it leads (moves first)
|
# Move pot by slightly more than player movement so it leads (moves first)
|
||||||
var push_movement = movement_along_axis * push_lead_factor
|
desired_movement = movement_along_axis * push_lead_factor
|
||||||
global_position += push_movement
|
|
||||||
velocity = push_movement / delta if delta > 0 else Vector2.ZERO
|
|
||||||
else:
|
else:
|
||||||
# PULLING: Player moves first, pot follows behind
|
# PULLING: Player moves first, pot follows behind
|
||||||
# Move pot by the exact same amount as player (pot follows immediately)
|
# Move pot by the exact same amount as player (pot follows immediately)
|
||||||
global_position += movement_along_axis
|
desired_movement = movement_along_axis
|
||||||
velocity = movement_along_axis / delta if delta > 0 else Vector2.ZERO
|
|
||||||
else:
|
else:
|
||||||
# No locked direction, just move pot by player's movement
|
# No locked direction, just move pot by player's movement
|
||||||
global_position += player_movement
|
desired_movement = player_movement
|
||||||
velocity = player_movement / delta if delta > 0 else Vector2.ZERO
|
|
||||||
|
# Check for collisions before moving - use space query to test
|
||||||
|
var space_state = get_world_2d().direct_space_state
|
||||||
|
var query = PhysicsShapeQueryParameters2D.new()
|
||||||
|
query.shape = $CollisionShape2D.shape
|
||||||
|
query.transform = global_transform.translated(desired_movement)
|
||||||
|
query.collision_mask = collision_mask
|
||||||
|
query.exclude = [self, holder] # Exclude self and holder from query
|
||||||
|
|
||||||
|
var results = space_state.intersect_shape(query, 1)
|
||||||
|
var can_move = true
|
||||||
|
|
||||||
|
# Check if any collision would block movement
|
||||||
|
for result in results:
|
||||||
|
var collider = result.collider
|
||||||
|
if collider != null:
|
||||||
|
# If it's a wall, another pot, or another player, block movement
|
||||||
|
can_move = false
|
||||||
|
break
|
||||||
|
|
||||||
|
if can_move:
|
||||||
|
# No blocking collision - move the pot
|
||||||
|
global_position += desired_movement
|
||||||
|
velocity = desired_movement / delta if delta > 0 else Vector2.ZERO
|
||||||
|
else:
|
||||||
|
# Something is blocking - don't move the pot
|
||||||
|
velocity = Vector2.ZERO
|
||||||
|
|
||||||
# Update previous position for next frame
|
# Update previous position for next frame
|
||||||
previous_holder_position = holder.global_position
|
previous_holder_position = holder.global_position
|
||||||
@@ -568,10 +593,8 @@ func grab(new_holder: CharacterBody2D) -> bool:
|
|||||||
# Initialize previous position to current position so we can track movement
|
# Initialize previous position to current position so we can track movement
|
||||||
previous_holder_position = new_holder.global_position
|
previous_holder_position = new_holder.global_position
|
||||||
previous_client_position = global_position # Initialize client position tracking
|
previous_client_position = global_position # Initialize client position tracking
|
||||||
# Disable pot's collision layer so grabber can't collide with it (prevents blocking when pushing)
|
# Keep pot's collision enabled so it can collide with other players while being pushed/pulled
|
||||||
# Note: This also means other players can't collide with pot while it's grabbed
|
# The pot uses direct position updates (not move_and_collide) but still needs collision for other players
|
||||||
# The pot uses direct position updates (not move_and_collide) so collisions aren't needed for movement
|
|
||||||
self.set_collision_layer_value(8, false) # Disable pot's collision layer
|
|
||||||
# Don't change pot's position - it should stay where it is and only move when player pushes/pulls
|
# Don't change pot's position - it should stay where it is and only move when player pushes/pulls
|
||||||
return true
|
return true
|
||||||
return false
|
return false
|
||||||
|
|||||||
Reference in New Issue
Block a user