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
|
||||
if multiplayer.is_server():
|
||||
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:
|
||||
# Client also needs to decrement knockback_timer for visual effects
|
||||
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:
|
||||
locked_dir = holder.locked_grab_direction.normalized()
|
||||
|
||||
# Calculate desired movement based on push/pull
|
||||
var desired_movement = Vector2.ZERO
|
||||
if locked_dir != Vector2.ZERO:
|
||||
# Project player's movement onto the push/pull direction
|
||||
var movement_along_axis = player_movement.project(locked_dir)
|
||||
@@ -236,18 +238,41 @@ func _physics_process(delta: float) -> void:
|
||||
if is_pushing:
|
||||
# PUSHING: Pot moves first, ahead of player
|
||||
# Move pot by slightly more than player movement so it leads (moves first)
|
||||
var push_movement = movement_along_axis * push_lead_factor
|
||||
global_position += push_movement
|
||||
velocity = push_movement / delta if delta > 0 else Vector2.ZERO
|
||||
desired_movement = movement_along_axis * push_lead_factor
|
||||
else:
|
||||
# PULLING: Player moves first, pot follows behind
|
||||
# Move pot by the exact same amount as player (pot follows immediately)
|
||||
global_position += movement_along_axis
|
||||
velocity = movement_along_axis / delta if delta > 0 else Vector2.ZERO
|
||||
desired_movement = movement_along_axis
|
||||
else:
|
||||
# No locked direction, just move pot by player's movement
|
||||
global_position += player_movement
|
||||
velocity = player_movement / delta if delta > 0 else Vector2.ZERO
|
||||
desired_movement = player_movement
|
||||
|
||||
# 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
|
||||
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
|
||||
previous_holder_position = new_holder.global_position
|
||||
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)
|
||||
# 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) so collisions aren't needed for movement
|
||||
self.set_collision_layer_value(8, false) # Disable pot's collision layer
|
||||
# Keep pot's collision enabled so it can collide with other players while being pushed/pulled
|
||||
# The pot uses direct position updates (not move_and_collide) but still needs collision for other players
|
||||
# Don't change pot's position - it should stay where it is and only move when player pushes/pulls
|
||||
return true
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user