Godot Version
Godot 3.6
Question
I am trying to create a pin joint between the player and the object when press the grab button. But the pin position is on the centre of the world which i don’t want at all. My character is in a different scene and it loads to the level using code. I tried everything but nothing is working. My character is a rigidbody.
Below is a video example of what is happening
Below is my character scenes tree
Below is my code
“” extends RigidBody2D
=== Constants ===
const GRAVITY_FORCE = 800
const TILT_SPEED = 50
const MAX_TILT_ANGLE = 30
const MAX_JUMP_FORCE = 1000
const MIN_JUMP_FORCE = 0
const JUMP_DECAY_RATE = 1000
const FRICTION = 100
const MAX_SLIDING_SPEED = 200
const COYOTE_TIME = 0.1
const SWING_FORCE = 1500 # Stronger because it’s rigid stick feeling
=== Variables ===
var holding_jump = false
var jump_timer = 0.0
var jump_force_current = MAX_JUMP_FORCE
var current_tilt = 0
var on_ground = false
var was_on_ground = false
var coyote_timer = 0.0
var is_grabbing = false
var grab_point = Vector2()
var pin_joint = null
var grabbed_body = null
=== Nodes ===
onready var anim_player = $AnimationPlayer
onready var spring_bar = $SpringBar
onready var mouth_area = $MouthArea
func _ready():
gravity_scale = 0 # We manually apply gravity
func _process(delta):
_handle_input(delta)
func _physics_process(delta):
if is_grabbing:
_apply_swing_physics(delta)
else:
_apply_gravity(delta)
_update_tilt(delta)
_check_landing()
func _integrate_forces(state):
if not is_grabbing:
_apply_friction(state)
func _handle_input(delta):
if Input.is_action_just_pressed(“jump”) and not is_grabbing:
holding_jump = true
jump_timer = 0.0
jump_force_current = MAX_JUMP_FORCE
anim_player.play(“jump”)
anim_player.seek(anim_player.get_animation(“jump”).length, true)
anim_player.playback_speed = 0
elif Input.is_action_pressed("jump") and holding_jump and not is_grabbing:
jump_timer += delta
jump_force_current = max(MIN_JUMP_FORCE, MAX_JUMP_FORCE - JUMP_DECAY_RATE * jump_timer)
var progress = jump_force_current / MAX_JUMP_FORCE
var anim_len = anim_player.get_animation("jump").length
anim_player.seek(anim_len * progress, true)
elif Input.is_action_just_released("jump") and holding_jump and not is_grabbing:
holding_jump = false
anim_player.stop()
anim_player.seek(0, true)
if on_ground or coyote_timer > 0.0:
_execute_jump()
else:
jump_timer = 0.0
jump_force_current = MAX_JUMP_FORCE
# Grab input
if Input.is_action_just_pressed("grab"):
_try_grab()
if Input.is_action_just_released("grab") and is_grabbing:
_release_grab()
# Update spring bar
spring_bar.value = jump_force_current
spring_bar.modulate = Color.red.linear_interpolate(Color.green, jump_force_current / MAX_JUMP_FORCE)
func _execute_jump():
var tilt_rad = deg2rad(current_tilt)
var jump_direction = Vector2(sin(tilt_rad), -cos(tilt_rad)).normalized()
linear_velocity = jump_direction * jump_force_current
jump_timer = 0.0
jump_force_current = MAX_JUMP_FORCE
coyote_timer = 0.0
func _apply_gravity(delta):
if not on_ground:
linear_velocity.y += GRAVITY_FORCE * delta
func _apply_friction(state):
if on_ground:
var friction_force = Vector2(-linear_velocity.x, 0).normalized() * FRICTION * state.step
linear_velocity += friction_force
linear_velocity.x = clamp(linear_velocity.x, -MAX_SLIDING_SPEED, MAX_SLIDING_SPEED)
func _update_tilt(delta):
var input_dir = Input.get_action_strength(“right”) - Input.get_action_strength(“left”)
current_tilt += input_dir * TILT_SPEED * delta
current_tilt = clamp(current_tilt, -MAX_TILT_ANGLE, MAX_TILT_ANGLE)
rotation_degrees = current_tilt
func _check_landing():
var space_state = get_world_2d().direct_space_state
var ray_start = global_position
var ray_end = global_position + Vector2(0, 10).rotated(rotation)
var result = space_state.intersect_ray(ray_start, ray_end, [self])
on_ground = result.size() > 0
if on_ground:
coyote_timer = COYOTE_TIME
else:
coyote_timer -= get_physics_process_delta_time()
func _try_grab():
for body in mouth_area.get_overlapping_bodies():
if body.is_in_group(“grabbable”):
is_grabbing = true
grabbed_body = body
grab_point = mouth_area.global_position
linear_velocity = Vector2.ZERO
_create_pin_joint()
break
func _create_pin_joint():
pin_joint = PinJoint2D.new()
get_parent().add_child(pin_joint)
pin_joint.node_a = get_path()
pin_joint.node_b = grabbed_body.get_path()
pin_joint.position = grab_point
func _release_grab():
is_grabbing = false
if pin_joint and pin_joint.is_inside_tree():
pin_joint.queue_free()
pin_joint = null
grabbed_body = null
func _apply_swing_physics(delta):
# Still apply gravity
linear_velocity.y += GRAVITY_FORCE * delta
# Swing input
var input_dir = Input.get_action_strength("right") - Input.get_action_strength("left")
if input_dir != 0:
# Apply force sideways relative to bottom (body center)
var force = Vector2(input_dir * SWING_FORCE, 0)
apply_impulse(Vector2.ZERO, force * delta)
“”