Player movement and Grappling hook

So i know what my problem is but I’m unsure about going about fixing it. Have some pretty basic movement on my player, but i’ve added a grappling hook to my player. Its not completely finished yet.
But i want the player to be able to hook onto an object and pull themselves to that object (Using left mouse button) and if the player lets go early i want them to be able to use the force generated to sling shot themself, it works fine on the Y axis but on the X axis it won’t work quite the same. And thats because i want the player to be able to move on the X axis in the air while jumping or falling, its a probably a pretty easy problem to solve but i can’t see it just want to be pointed in the right direction.
cheers

(problem is inside my movement function, inside if !isGrappling)

extends CharacterBody2D

@export var moveSpeed : float = 10
@export var sprintMultiplier : float = 1.5
@export var playerStamina = 100

@export var jumpHeight : float = 3
@export var doubleJumpMultiplier : float = 1.7

@export var hookLayer : int = 0
@export var playerCamera : Camera2D

@export var grapplingGun_Cooldown : float = 5
@export var grappleGun_Speed : float = 10
@export var grappleGun_Length : float = 100
@onready var grappleRay = $RayCast2D

const gravity : float = 6

var playerMovement : Vector2
var canDoubleJump : bool = false
var staminaDepletionRate : float = 0.1
var isGrappling : bool = false
var hookDir : Vector2


func _process(delta):
	move_and_slide()

func _physics_process(delta):
	movement(delta)
	grapplingHook(delta)

func movement(delta):
	if !is_on_floor():
		velocity.y += gravity
	
	if !isGrappling:
		playerMovement.x = Input.get_axis("A-Key","D-Key")
		velocity.x = playerMovement.x * moveSpeed
	
	playerStamina = clamp(playerStamina, 0, 100)
	if Input.is_action_pressed("Shift-Key") && playerStamina > 0:
		velocity.x = playerMovement.x * moveSpeed * sprintMultiplier
		if velocity.x < 0 or velocity.x > 0:
			playerStamina = playerStamina - staminaDepletionRate
	if !Input.is_action_pressed("Shift-Key"):
		playerStamina = playerStamina + 0.5
	
	if Input.is_action_just_pressed("Spacebar") && is_on_floor():
		velocity.y = -jumpHeight
		canDoubleJump = true
	if Input.is_action_just_pressed("Spacebar") && canDoubleJump && !is_on_floor():
		velocity.y = -jumpHeight * doubleJumpMultiplier
		canDoubleJump = false

func grapplingHook(delta):
	grappleRay.target_position.x = grappleGun_Length
	grappleRay.look_at(get_global_mouse_position())
	

	if Input.is_action_pressed("LeftMouseButton") && grappleRay.get_collider():
		isGrappling = true
		var collisionPoint = grappleRay.get_collision_point()
		
		hookDir = (collisionPoint - position).normalized()
		print(hookDir)
		if isGrappling:
			velocity = (hookDir * grappleGun_Speed)
			#velocity = lerp(position,collisionPoint, grappleGun_Speed * delta)
	else: isGrappling = false

I do not really understand what your problem is can you please describe a bit more about what the desired behavior is and what is currently not working?

Sorry for not being clear, so when the player uses the grappling gun id like some sort of force to be applied. (Player position to grappling hook point) and id still like force to be applied in that same direction just after the player releases button. While still being able to control there movement on where they land. Hope that was better.

If you want to apply a force you need to be constantly increasing velocity for as long as that force is applied, for that you also need to account for the velocity of the previous frame (which I do not see you doing, correct me if I missed a part of your code it is quite late at night here). Member variable velocity of CharacterBody2D will retain this information and even correct it if collisions occur (after calls to move_and_slide) which is what I presume you want. Then after the player releases the grappling hook you just need to stop adding the force and retain the current velocity as it does not change while in air (unless you want to add air resistance). If you want the x coordinate to still be kind of player controller while in air then edit (do not reassign) the x axis of the velocity variable according to player input.

I think your major problem was not accounting for velocity of the previous frame. Your y axis works correctly because you are doing that (you use += to apply gravity instead of = which you always use to modify the x variable)

Alright thanks ill give it a try!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.