1extends KinematicBody 2 3const ANIM_FLOOR = 0 4const ANIM_AIR = 1 5 6const SHOOT_TIME = 1.5 7const SHOOT_SCALE = 2 8const CHAR_SCALE = Vector3(0.3, 0.3, 0.3) 9const TURN_SPEED = 40 10 11var movement_dir = Vector3() 12var linear_velocity = Vector3() 13 14var jumping = false 15 16var air_idle_deaccel = false 17var accel = 19.0 18var deaccel = 14.0 19var sharp_turn_threshold = 140 20var max_speed = 3.1 21 22var prev_shoot = false 23var shoot_blend = 0 24 25onready var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") * ProjectSettings.get_setting("physics/3d/default_gravity_vector") 26 27func _ready(): 28 get_node("AnimationTree").set_active(true) 29 30 31func _physics_process(delta): 32 linear_velocity += gravity * delta 33 34 var anim = ANIM_FLOOR 35 36 var vv = linear_velocity.y # Vertical velocity. 37 var hv = Vector3(linear_velocity.x, 0, linear_velocity.z) # Horizontal velocity. 38 39 var hdir = hv.normalized() # Horizontal direction. 40 var hspeed = hv.length() # Horizontal speed. 41 42 # Player input. 43 var cam_basis = get_node("Target/Camera").get_global_transform().basis 44 var dir = Vector3() # Where does the player intend to walk to. 45 dir = (Input.get_action_strength("move_right") - Input.get_action_strength("move_left")) * cam_basis[0] 46 dir += (Input.get_action_strength("move_backwards") - Input.get_action_strength("move_forward")) * cam_basis[2] 47 dir.y = 0 48 dir = dir.normalized() 49 50 var jump_attempt = Input.is_action_pressed("jump") 51 var shoot_attempt = Input.is_action_pressed("shoot") 52 53 if is_on_floor(): 54 var sharp_turn = hspeed > 0.1 and rad2deg(acos(dir.dot(hdir))) > sharp_turn_threshold 55 56 if dir.length() > 0.1 and !sharp_turn: 57 if hspeed > 0.001: 58 hdir = adjust_facing(hdir, dir, delta, 1.0 / hspeed * TURN_SPEED, Vector3.UP) 59 else: 60 hdir = dir 61 62 if hspeed < max_speed: 63 hspeed += accel * delta 64 else: 65 hspeed -= deaccel * delta 66 if hspeed < 0: 67 hspeed = 0 68 69 hv = hdir * hspeed 70 71 var mesh_xform = get_node("Armature").get_transform() 72 var facing_mesh = -mesh_xform.basis[0].normalized() 73 facing_mesh = (facing_mesh - Vector3.UP * facing_mesh.dot(Vector3.UP)).normalized() 74 75 if hspeed > 0: 76 facing_mesh = adjust_facing(facing_mesh, dir, delta, 1.0 / hspeed * TURN_SPEED, Vector3.UP) 77 var m3 = Basis(-facing_mesh, Vector3.UP, -facing_mesh.cross(Vector3.UP).normalized()).scaled(CHAR_SCALE) 78 79 get_node("Armature").set_transform(Transform(m3, mesh_xform.origin)) 80 81 if not jumping and jump_attempt: 82 vv = 7.0 83 jumping = true 84 get_node("SoundJump").play() 85 else: 86 anim = ANIM_AIR 87 88 if dir.length() > 0.1: 89 hv += dir * (accel * 0.2 * delta) 90 if hv.length() > max_speed: 91 hv = hv.normalized() * max_speed 92 else: 93 if air_idle_deaccel: 94 hspeed = hspeed - (deaccel * 0.2 * delta) 95 if hspeed < 0: 96 hspeed = 0 97 hv = hdir * hspeed 98 99 if jumping and vv < 0: 100 jumping = false 101 102 linear_velocity = hv + Vector3.UP * vv 103 104 if is_on_floor(): 105 movement_dir = linear_velocity 106 107 linear_velocity = move_and_slide(linear_velocity, -gravity.normalized()) 108 109 if shoot_blend > 0: 110 shoot_blend -= delta * SHOOT_SCALE 111 if (shoot_blend < 0): 112 shoot_blend = 0 113 114 if shoot_attempt and not prev_shoot: 115 shoot_blend = SHOOT_TIME 116 var bullet = preload("res://player/bullet/bullet.tscn").instance() 117 bullet.set_transform(get_node("Armature/Bullet").get_global_transform().orthonormalized()) 118 get_parent().add_child(bullet) 119 bullet.set_linear_velocity(get_node("Armature/Bullet").get_global_transform().basis[2].normalized() * 20) 120 bullet.add_collision_exception_with(self) # Add it to bullet. 121 get_node("SoundShoot").play() 122 123 prev_shoot = shoot_attempt 124 125 if is_on_floor(): 126 $AnimationTree["parameters/walk/blend_amount"] = hspeed / max_speed 127 128 $AnimationTree["parameters/state/current"] = anim 129 $AnimationTree["parameters/air_dir/blend_amount"] = clamp(-linear_velocity.y / 4 + 0.5, 0, 1) 130 $AnimationTree["parameters/gun/blend_amount"] = min(shoot_blend, 1.0) 131 132 133func adjust_facing(p_facing, p_target, p_step, p_adjust_rate, current_gn): 134 var n = p_target # Normal. 135 var t = n.cross(current_gn).normalized() 136 137 var x = n.dot(p_facing) 138 var y = t.dot(p_facing) 139 140 var ang = atan2(y,x) 141 142 if abs(ang) < 0.001: # Too small. 143 return p_facing 144 145 var s = sign(ang) 146 ang = ang * s 147 var turn = ang * p_adjust_rate * p_step 148 var a 149 if ang < turn: 150 a = ang 151 else: 152 a = turn 153 ang = (ang - a) * s 154 155 return (n * cos(ang) + t * sin(ang)) * p_facing.length() 156