Skip to content

Instantly share code, notes, and snippets.

@lemilonkh
Created February 17, 2021 09:02
Show Gist options
  • Save lemilonkh/279f82005033073ebaa0f3777248ced7 to your computer and use it in GitHub Desktop.
Save lemilonkh/279f82005033073ebaa0f3777248ced7 to your computer and use it in GitHub Desktop.
Hookstronaut's Player Controller
extends GravityBody
class_name Player
export(float, 0, 50) var jetpack_force = 2
export(float, 0, 10) var grappling_hook_length = 50
export(float, 0, 10) var grappling_hook_force = 20
export(float, 0, 50) var mouse_sensitivity = 0.002 # rad/px
export(float, 0, 10) var controller_look_speed = 0.08
var current_planet: RigidBody
onready var camera: Camera = $Pivot/Camera
onready var rope: MeshInstance = $Rope
onready var hook_emitter: Position3D = $Pivot/Camera/LightningGun/HookEmitter
var grappled_body: RigidBody
var grappled_offset: Vector3 = Vector3()
func _init():
initial_velocity = 0
func _ready():
current_planet = find_closest_planet()
set_process_unhandled_input(true)
set_physics_process(true)
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func find_closest_planet():
var planets = get_tree().get_nodes_in_group("gravity")
var min_distance = INF
var closest_planet
for planet in planets:
var distance = planet.global_transform.origin.distance_to(global_transform.origin)
if distance < min_distance:
closest_planet = planet
min_distance = distance
return closest_planet
func get_input():
var input_direction = Vector3()
var cam_basis = camera.global_transform.basis
input_direction -= Input.get_action_strength("move_left") * cam_basis.x
input_direction += Input.get_action_strength("move_right") * cam_basis.x
input_direction += Input.get_action_strength("move_up") * cam_basis.y
input_direction -= Input.get_action_strength("move_down") * cam_basis.y
input_direction -= Input.get_action_strength("move_forward") * cam_basis.z
input_direction += Input.get_action_strength("move_back") * cam_basis.z
# rotate camera with controller
var camera_rotation = Vector2(
Input.get_action_strength("look_left") - Input.get_action_strength("look_right"),
Input.get_action_strength("look_down") - Input.get_action_strength("look_up")
) * controller_look_speed
if camera_rotation.length() > 0:
rotate_camera(camera_rotation)
return input_direction.normalized()
func _physics_process(delta):
var jetpack_velocity = get_input() * jetpack_force * delta
linear_velocity += jetpack_velocity
if Input.is_action_pressed("shoot"):
if grappled_body == null:
var raycast_result = perform_raycast()
# hook onto hit body
if !raycast_result.empty() and raycast_result["collider"] is RigidBody:
grappled_body = raycast_result["collider"]
grappled_offset = raycast_result["position"] - grappled_body.global_transform.origin
# apply force to self and hit object
if grappled_body != null:
var grappling_direction = (grappled_body.global_transform.origin - global_transform.origin).normalized()
var grappling_force = grappling_direction * grappling_hook_force
add_central_force(grappling_force)
grappled_body.add_central_force(-grappling_force)
# update grappling hook rope
var own_pos = hook_emitter.global_transform.origin
var target_pos = grappled_body.global_transform.origin + grappled_offset
var direction = target_pos - own_pos
rope.global_transform.origin = (own_pos + target_pos) / 2
rope.mesh.height = direction.length()
rope.look_at(target_pos, Vector3(0, 1, 0))
rope.rotate_object_local(Vector3(1, 0, 0), -PI/2)
rope.visible = true
else:
grappled_body = null
grappled_offset = Vector3()
rope.visible = false
if Input.is_action_pressed("pull"):
pass
#if current_planet != null:
#look_at(current_planet.global_transform.origin, Vector3(0, 0, 1))
func perform_raycast():
var center_position = get_viewport().size / 2
var from = camera.project_ray_origin(center_position)
var to = camera.project_ray_normal(center_position) * grappling_hook_length
var raycast_result = get_world().direct_space_state.intersect_ray(from, to, [self])
return raycast_result
func _input(event):
if event.is_action_pressed("toggle_capture"):
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
elif Input.get_mouse_mode() == Input.MOUSE_MODE_VISIBLE:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
if event.is_action_pressed("ui_exit"):
get_tree().quit(0)
func rotate_camera(movement: Vector2):
camera.rotate_y(movement.x)
$Pivot.rotate_x(movement.y)
$Pivot.rotation.x = clamp($Pivot.rotation.x, -PI, PI)
func _unhandled_input(event):
if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
var movement = -event.relative * mouse_sensitivity
rotate_camera(movement)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment