diff --git a/scenes/heroes/0.tscn b/scenes/heroes/0.tscn index 4b0c300..e8870c0 100644 --- a/scenes/heroes/0.tscn +++ b/scenes/heroes/0.tscn @@ -20,7 +20,7 @@ radial_segments = 64 rings = 8 _sections_unfolded = [ "Resource" ] -[node name="RigidBody" type="KinematicBody" groups=[ +[node name="RigidBody" type="RigidBody" groups=[ "player", ]] @@ -28,13 +28,27 @@ input_ray_pickable = true input_capture_on_drag = false collision_layer = 1 collision_mask = 1 +mode = 2 +mass = 100.0 +friction = 1.0 +bounce = 0.0 +gravity_scale = 1.0 +custom_integrator = false +continuous_cd = false +contacts_reported = 4 +contact_monitor = true +sleeping = false +can_sleep = true axis_lock_linear_x = false axis_lock_linear_y = false axis_lock_linear_z = false axis_lock_angular_x = false axis_lock_angular_y = false axis_lock_angular_z = false -collision/safe_margin = 0.001 +linear_velocity = Vector3( 0, 0, 0 ) +linear_damp = -1.0 +angular_velocity = Vector3( 0, 0, 0 ) +angular_damp = -1.0 script = ExtResource( 1 ) _sections_unfolded = [ "Angular", "Collision", "Linear", "Transform", "Visibility" ] diff --git a/scenes/player.tscn b/scenes/player.tscn index 09ad850..41e0521 100644 --- a/scenes/player.tscn +++ b/scenes/player.tscn @@ -20,7 +20,7 @@ radial_segments = 64 rings = 8 _sections_unfolded = [ "Resource" ] -[node name="RigidBody" type="KinematicBody" index="0" groups=[ +[node name="RigidBody" type="RigidBody" index="0" groups=[ "player", ]] @@ -28,13 +28,27 @@ input_ray_pickable = true input_capture_on_drag = false collision_layer = 1 collision_mask = 1 +mode = 2 +mass = 200.0 +friction = 1.0 +bounce = 0.0 +gravity_scale = 1.0 +custom_integrator = false +continuous_cd = false +contacts_reported = 0 +contact_monitor = false +sleeping = false +can_sleep = true axis_lock_linear_x = false axis_lock_linear_y = false axis_lock_linear_z = false axis_lock_angular_x = false axis_lock_angular_y = false axis_lock_angular_z = false -collision/safe_margin = 0.001 +linear_velocity = Vector3( 0, 0, 0 ) +linear_damp = -1.0 +angular_velocity = Vector3( 0, 0, 0 ) +angular_damp = -1.0 script = ExtResource( 1 ) _sections_unfolded = [ "Angular", "Axis Lock", "Collision", "Linear", "Transform", "Visibility", "collision" ] diff --git a/scripts/heroes/0.gd b/scripts/heroes/0.gd index 793bc39..b280db8 100644 --- a/scripts/heroes/0.gd +++ b/scripts/heroes/0.gd @@ -1,30 +1,52 @@ extends "res://scripts/player.gd" -const wallride_speed = 0 -const wallride_speed_necessary = 15 -const wallride_leap_height = 10 -const wallride_leap_side = 10 +const wallride_speed_necessary = 2 +const wallride_leap_height = 14 +const wallride_leap_side = 8 var since_on_wall = 0 var last_wall_normal = Vector3() var wallride_forgiveness = .150 -func control_player(delta): - wallride(delta) - .control_player(delta) +func control_player(state): + .control_player(state) + wallride(state) + +func wallride(state): + + var ray = get_node("Ray") + var vel = state.get_linear_velocity() -func wallride(delta): # If our feet aren't touching, but we are colliding, we are wall-riding - if is_on_wall() and not is_on_floor() and velocity.length() > wallride_speed_necessary: - since_on_wall = 0 - last_wall_normal = get_slide_collision(0).normal + if !ray.is_colliding() and get_colliding_bodies() and vel.length() > wallride_speed_necessary: + last_wall_normal = state.get_contact_local_normal(0) + # Make sure it isn't the floor + if last_wall_normal.dot(Vector3(0,1,0)) < 0.95: + since_on_wall = 0 else: - since_on_wall += delta + since_on_wall += state.get_step() + + debug_node.set_text(str(since_on_wall < wallride_forgiveness)) if since_on_wall < wallride_forgiveness: - var aim = get_node("Yaw").get_global_transform().basis # Add zero gravity - velocity.y = -gravity # So it's undone in super + set_gravity_scale(0) + # Remove any momentum we may have + state.set_linear_velocity(Vector3(vel.x, 0, vel.z)) + # Because 1/2 of our energy is wasted in the wall, get more forwards/backwards here: + var aim = get_node("Yaw").get_global_transform().basis + if Input.is_action_pressed("move_forwards"): + apply_impulse(Vector3(), -air_accel * aim[2] * get_mass()) + if Input.is_action_pressed("move_backwards"): + apply_impulse(Vector3(), air_accel * aim[2] * get_mass()) # Allow jumping (for wall hopping!) if Input.is_action_just_pressed("jump"): - velocity.y += wallride_leap_height - velocity += wallride_leap_side * last_wall_normal + var jump_impulse = wallride_leap_side * last_wall_normal + jump_impulse.y += wallride_leap_height + set_gravity_scale(1) # Jumping requires gravity + state.apply_impulse(Vector3(), jump_impulse * get_mass()) + else: + # We need to return to falling (we aren't riding anymore) + set_gravity_scale(1) + + state.integrate_forces() + diff --git a/scripts/player.gd b/scripts/player.gd index d8718ed..c08da7a 100644 --- a/scripts/player.gd +++ b/scripts/player.gd @@ -2,31 +2,29 @@ # This source code form is governed by the MIT license. # Original: https://raw.githubusercontent.com/Calinou/fps-test/master/scripts/player.gd -extends KinematicBody +extends RigidBody var view_sensitivity = 0.25 var yaw = 0 var pitch = 0 -var gravity = -.8 -var velocity = Vector3() -slave var slave_tf = Basis() -slave var slave_vel = Vector3() - var timer = 0 # Walking speed and jumping height are defined later. -var walk_speed = 3 -var jump_speed = 15 -const air_accel = .5 +var walk_speed = 2 +var jump_speed = 3 +const air_accel = .6 +var floor_friction = 0.92 +var air_friction = 0.98 -var weight = .1 var health = 100 var stamina = 10000 -var ray_length = 10 var debug_node +slave var slave_transform = Basis() +slave var slave_lin_v = Vector3() +slave var slave_ang_v = Vector3() func _ready(): set_process_input(true) @@ -62,16 +60,16 @@ func _input(event): quit() -func _physics_process(delta): - if is_network_master(): - control_player(delta) - rset_unreliable("slave_tf", get_transform()) - rset_unreliable("slave_vel", velocity) - else: - set_transform(slave_tf) - move_and_slide(slave_vel) +master func _integrate_forces(state): + control_player(state) + rpc_unreliable("set_status", get_transform(), get_linear_velocity(), get_angular_velocity()) -func control_player(delta): +slave func set_status(tf, lv, av): + set_transform(tf) + set_linear_velocity(lv) + set_angular_velocity(av) + +func control_player(state): var aim = get_node("Yaw").get_global_transform().basis @@ -87,42 +85,54 @@ func control_player(delta): direction += aim[0] direction = direction.normalized() + var ray = get_node("Ray") + + if ray.is_colliding(): + var up = state.get_total_gravity().normalized() + var normal = ray.get_collision_normal() + var floor_velocity = Vector3() + var object = ray.get_collider() + + if object is RigidBody or object is StaticBody: + var point = ray.get_collision_point() - object.get_translation() + var floor_angular_vel = Vector3() + if object is RigidBody: + floor_velocity = object.get_linear_velocity() + floor_angular_vel = object.get_angular_velocity() + elif object is StaticBody: + floor_velocity = object.get_constant_linear_velocity() + floor_angular_vel = object.get_constant_angular_velocity() + # Surely there should be a function to convert Euler angles to a 3x3 matrix + var tf = Basis(Vector3(1, 0, 0), floor_angular_vel.x) + tf = tf.rotated(Vector3(0, 1, 0), floor_angular_vel.y) + tf = tf.rotated(Vector3(0, 0, 1), floor_angular_vel.z) + floor_velocity += tf.xform_inv(point) - point + yaw = fmod(yaw + rad2deg(floor_angular_vel.y) * state.get_step(), 360) + get_node("Yaw").set_rotation(Vector3(0, deg2rad(yaw), 0)) - var friction - - if is_on_floor(): - - friction = 1 - 0.16 - velocity.x *= friction - velocity.z *= friction - velocity.y = 0 - velocity += direction * walk_speed + var diff = floor_velocity + direction * walk_speed + state.apply_impulse(Vector3(), diff * get_mass()) + var lin_v = state.get_linear_velocity() + lin_v.x *= floor_friction + lin_v.z *= floor_friction + state.set_linear_velocity(lin_v) if Input.is_action_pressed("jump"): - velocity.y += jump_speed + state.apply_impulse(Vector3(), normal * jump_speed * get_mass()) else: - friction = 1 - 0.01 - velocity.x *= friction - velocity.z *= friction - velocity.y += gravity - velocity += direction * air_accel - - # Just for testing TODO - if Input.is_action_pressed("jump"): - velocity.y += jump_speed * 0.1 - - debug_node.set_text("%8.f,%8.f,%8.f" % [velocity.x, velocity.y, velocity.z]) + state.apply_impulse(Vector3(), direction * air_accel * get_mass()) + var lin_v = state.get_linear_velocity() + lin_v.x *= air_friction + lin_v.z *= air_friction + state.set_linear_velocity(lin_v) - velocity = move_and_slide(velocity, Vector3(0, 1, 0)) + # print(state.get_linear_velocity()) - for i in range(get_slide_count()): - var collision = get_slide_collision(i) - if collision.collider.is_in_group("objective"): + var vel = get_linear_velocity() + debug_node.set_text("%8.f,%8.f,%8.f" % [vel.x, vel.y, vel.z]) - var rel_pos = collision.position - collision.collider.get_translation() - debug_node.set_text("%8.f,%8.f,%8.f" % [rel_pos.x, rel_pos.y, rel_pos.z]) - collision.collider.apply_impulse(collision.position, Vector3(0, -weight, 0)) + state.integrate_forces() func _exit_scene(): Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)