From 4113e975a729e00eab404616fcc3418cf1c6be52 Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sat, 14 Oct 2023 23:23:02 -0700 Subject: [PATCH 1/7] Remove accidentally added temp file It's just a copy of project.godot from a failed save. See issue 82270. Add that pattern to gitignore. --- .gitignore | 4 +- project.godot~RF222a71b8.TMP | 112 ----------------------------------- 2 files changed, 3 insertions(+), 113 deletions(-) delete mode 100644 project.godot~RF222a71b8.TMP diff --git a/.gitignore b/.gitignore index 0e0aed5..dc74cc7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ data_*/ mono_crash.*.json # Kenney ignores -build/ \ No newline at end of file +build/ +# https://github.com/godotengine/godot/issues/82270 +*~*.TMP diff --git a/project.godot~RF222a71b8.TMP b/project.godot~RF222a71b8.TMP deleted file mode 100644 index cbb3fc7..0000000 --- a/project.godot~RF222a71b8.TMP +++ /dev/null @@ -1,112 +0,0 @@ -; Engine configuration file. -; It's best edited using the editor UI and not directly, -; since the parameters that go here are not all obvious. -; -; Format: -; [section] ; section goes between [] -; param=value ; assign values to parameters - -config_version=5 - -[application] - -config/name="Starter Kit FPS" -config/tags=PackedStringArray("starterkit") -run/main_scene="res://scenes/main.tscn" -config/features=PackedStringArray("4.1", "Forward Plus") -boot_splash/bg_color=Color(0.92549, 0.92549, 0.960784, 1) -boot_splash/image="res://splash-screen.png" -config/icon="res://icon.png" - -[autoload] - -Audio="*res://scripts/audio.gd" - -[display] - -window/size/viewport_width=1280 -window/size/viewport_height=720 - -[editor] - -movie_writer/mjpeg_quality=1.0 -movie_writer/movie_file="D:/Godot/test.avi" - -[input] - -move_right={ -"deadzone": 0.25, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":1.0,"script":null) -] -} -move_left={ -"deadzone": 0.25, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":0,"axis_value":-1.0,"script":null) -] -} -move_forward={ -"deadzone": 0.25, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) -] -} -move_back={ -"deadzone": 0.25, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null) -] -} -jump={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null) -] -} -camera_left={ -"deadzone": 0.5, -"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":-1.0,"script":null) -] -} -camera_right={ -"deadzone": 0.5, -"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":2,"axis_value":1.0,"script":null) -] -} -camera_up={ -"deadzone": 0.5, -"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":-1.0,"script":null) -] -} -camera_down={ -"deadzone": 0.5, -"events": [Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":3,"axis_value":1.0,"script":null) -] -} -mouse_capture={ -"deadzone": 0.5, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) -] -} -mouse_capture_exit={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"echo":false,"script":null) -] -} -shoot={ -"deadzone": 0.5, -"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(92, 12),"global_position":Vector2(96, 55),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":5,"axis_value":1.0,"script":null) -] -} -weapon_toggle={ -"deadzone": 0.5, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":10,"pressure":0.0,"pressed":true,"script":null) -] -} - -[rendering] - -anti_aliasing/quality/screen_space_aa=1 From a36ae6e38a7db1a6facaeea545a9e9592b2eb72b Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sat, 14 Oct 2023 23:31:46 -0700 Subject: [PATCH 2/7] Rework camera to work with gamepad Fix camera moves 180 degrees every frame when using gamepad. Store a rotation delta and use rotate_toward to move with a max speed instead of a lerp. Has the same general feel with mouse, but now gamepad feels reasonable. --- objects/player.gd | 62 +++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/objects/player.gd b/objects/player.gd index 17af10d..160c870 100644 --- a/objects/player.gd +++ b/objects/player.gd @@ -3,6 +3,7 @@ extends CharacterBody3D @export_subgroup("Properties") @export var movement_speed = 5 @export var jump_strength = 7 +@export var max_look_speed := Vector2.ONE * 5.0 # in radians per second @export_subgroup("Weapons") @export var weapons: Array[Weapon] = [] @@ -10,11 +11,12 @@ extends CharacterBody3D var weapon: Weapon var weapon_index := 0 -var mouse_sensitivity = 700 +var gamepad_sensitivity := 0.05 # max radians we try to move per physics frame +var mouse_sensitivity = 700 # 1/max radians we try to move per mouse input var mouse_captured := true var movement_velocity: Vector3 -var rotation_target: Vector3 +var rotation_delta: Vector2 # x: horizontal, y: vertical var input: Vector3 var input_mouse: Vector2 @@ -47,10 +49,26 @@ signal health_updated func _ready(): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED - + rotation_delta = Vector2.ZERO + initiate_change_weapon(weapon_index) -func _physics_process(delta): + +func angle_difference(from: float, to: float) -> float: + var diff := fmod(to - from, TAU) + return fmod(2.0 * diff, TAU) - diff + + +func rotate_toward(from: float, to: float, delta: float) -> float: + # Not yet in gdscript: https://github.com/godotengine/godot/pull/80225 + var diff := angle_difference(from, to) + var diff_abs := absf(diff) + # When `delta < 0` move no further than to PI radians away from `p_to` (as + # PI is the max possible angle distance). + return from + clamp(delta, diff_abs - PI, diff_abs) * signf(diff) + + +func _physics_process(delta: float): # Handle functions @@ -70,12 +88,19 @@ func _physics_process(delta): move_and_slide() # Rotation - - camera.rotation.z = lerp_angle(camera.rotation.z, -input_mouse.x * 25 * delta, delta * 5) - - camera.rotation.x = lerp_angle(camera.rotation.x, rotation_target.x, delta * 25) - rotation.y = lerp_angle(rotation.y, rotation_target.y, delta * 25) - + + # Roll a bit when turning horizontally. + camera.rotation.z = lerp_angle(camera.rotation.z, -input_mouse.x * 25 * delta, delta * 5) + + var look_amount := max_look_speed * delta + # pitch + var pitch := rotate_toward(camera.rotation.x, camera.rotation.x + rotation_delta.y, look_amount.x) + pitch = clamp(pitch, -TAU * 0.23, TAU * 0.23) + camera.rotation.x = pitch + # yaw + rotation.y = rotate_toward(rotation.y, rotation.y + rotation_delta.x, look_amount.y) + rotation_delta = Vector2.ZERO + container.position = lerp(container.position, container_offset - (applied_velocity / 30), delta * 10) # Movement sound @@ -108,8 +133,8 @@ func _input(event): input_mouse = event.relative / mouse_sensitivity - rotation_target.y -= event.relative.x / mouse_sensitivity - rotation_target.x -= event.relative.y / mouse_sensitivity + rotation_delta.x -= event.relative.x / mouse_sensitivity + rotation_delta.y -= event.relative.y / mouse_sensitivity func handle_controls(_delta): @@ -133,15 +158,10 @@ func handle_controls(_delta): movement_velocity = input.normalized() * movement_speed # Rotation - - var rotation_input := Vector3.ZERO - - rotation_input.y = Input.get_axis("camera_left", "camera_right") - rotation_input.x = Input.get_axis("camera_up", "camera_down") / 2 - - rotation_target -= rotation_input.limit_length(1.0) * 5 - rotation_target.x = clamp(rotation_target.x, deg_to_rad(-90), deg_to_rad(90)) - + + var rotation_input := Input.get_vector("camera_right", "camera_left", "camera_down", "camera_up") + rotation_delta += rotation_input * gamepad_sensitivity + # Shooting action_shoot() From 9bd817d9e455cf42b649d294e978c115d51ba871 Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sat, 14 Oct 2023 23:36:50 -0700 Subject: [PATCH 3/7] Jump with gamepad A Use more conventional jump button. --- project.godot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project.godot b/project.godot index cbb3fc7..9963bd0 100644 --- a/project.godot +++ b/project.godot @@ -61,7 +61,7 @@ move_back={ jump={ "deadzone": 0.5, "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null) ] } camera_left={ From cb5d697704e49bad98e78cd4fa8bf58e12af3eaa Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sat, 14 Oct 2023 23:27:14 -0700 Subject: [PATCH 4/7] Whitespace: Remove trailing and adjust spacing Used gdformat from godot-gdscript-toolkit to automatically clean up formatting to be consistent across the project. One exception: there's a long line in player.gd that it split across multiple lines that seemed worse than before. --- objects/enemy.gd | 49 +++++------ objects/impact.gd | 1 + objects/player.gd | 207 ++++++++++++++++++++++++---------------------- scripts/audio.gd | 14 ++-- scripts/hud.gd | 2 +- scripts/weapon.gd | 24 +++--- 6 files changed, 154 insertions(+), 143 deletions(-) diff --git a/objects/enemy.gd b/objects/enemy.gd index caaf9e4..30ef97a 100644 --- a/objects/enemy.gd +++ b/objects/enemy.gd @@ -1,6 +1,6 @@ extends Node3D -@export var player:Node3D +@export var player: Node3D @onready var raycast = $RayCast @onready var muzzle_a = $MuzzleA @@ -8,66 +8,67 @@ extends Node3D var health := 100 var time := 0.0 -var target_position:Vector3 +var target_position: Vector3 var destroyed := false # When ready, save the initial position + func _ready(): - target_position = position + func _process(delta): - - self.look_at(player.position + Vector3(0, 0.5, 0), Vector3.UP, true) # Look at player - target_position.y += (cos(time * 5) * 1) * delta # Sine movement (up and down) - + self.look_at(player.position + Vector3(0, 0.5, 0), Vector3.UP, true) # Look at player + target_position.y += (cos(time * 5) * 1) * delta # Sine movement (up and down) + time += delta - + position = target_position + # Take damage from player + func damage(amount): - Audio.play("sounds/enemy_hurt.ogg") - + health -= amount - + if health <= 0 and !destroyed: destroy() + # Destroy the enemy when out of health + func destroy(): - Audio.play("sounds/enemy_destroy.ogg") - + destroyed = true queue_free() + # Shoot when timer hits 0 + func _on_timer_timeout(): - raycast.force_raycast_update() - + if raycast.is_colliding(): - var collider = raycast.get_collider() - - if collider.has_method("damage"): # Raycast collides with player - + + if collider.has_method("damage"): # Raycast collides with player # Play muzzle flash animation(s) - + muzzle_a.frame = 0 muzzle_a.play("default") muzzle_a.rotation_degrees.z = randf_range(-45, 45) - + muzzle_b.frame = 0 muzzle_b.play("default") muzzle_b.rotation_degrees.z = randf_range(-45, 45) - + Audio.play("sounds/enemy_attack.ogg") - - collider.damage(5) # Apply damage to player + + collider.damage(5) # Apply damage to player diff --git a/objects/impact.gd b/objects/impact.gd index b0c7595..6cb6c14 100644 --- a/objects/impact.gd +++ b/objects/impact.gd @@ -2,5 +2,6 @@ extends AnimatedSprite3D # Remove this impact effect after the animation has completed + func _on_animation_finished(): queue_free() diff --git a/objects/player.gd b/objects/player.gd index 160c870..19c0b42 100644 --- a/objects/player.gd +++ b/objects/player.gd @@ -21,7 +21,7 @@ var rotation_delta: Vector2 # x: horizontal, y: vertical var input: Vector3 var input_mouse: Vector2 -var health:int = 100 +var health: int = 100 var gravity := 0.0 var previously_floored := false @@ -31,7 +31,7 @@ var jump_double := true var container_offset = Vector3(1.2, -1.1, -2.75) -var tween:Tween +var tween: Tween signal health_updated @@ -42,12 +42,12 @@ signal health_updated @onready var sound_footsteps = $SoundFootsteps @onready var blaster_cooldown = $Cooldown -@export var crosshair:TextureRect +@export var crosshair: TextureRect # Functions + func _ready(): - Input.mouse_mode = Input.MOUSE_MODE_CAPTURED rotation_delta = Vector2.ZERO @@ -69,24 +69,23 @@ func rotate_toward(from: float, to: float, delta: float) -> float: func _physics_process(delta: float): - # Handle functions - + handle_controls(delta) handle_gravity(delta) - + # Movement var applied_velocity: Vector3 - - movement_velocity = transform.basis * movement_velocity # Move forward - + + movement_velocity = transform.basis * movement_velocity # Move forward + applied_velocity = velocity.lerp(movement_velocity, delta * 10) applied_velocity.y = -gravity - + velocity = applied_velocity move_and_slide() - + # Rotation # Roll a bit when turning horizontally. @@ -94,225 +93,235 @@ func _physics_process(delta: float): var look_amount := max_look_speed * delta # pitch - var pitch := rotate_toward(camera.rotation.x, camera.rotation.x + rotation_delta.y, look_amount.x) + var pitch := rotate_toward( + camera.rotation.x, camera.rotation.x + rotation_delta.y, look_amount.x + ) pitch = clamp(pitch, -TAU * 0.23, TAU * 0.23) camera.rotation.x = pitch # yaw - rotation.y = rotate_toward(rotation.y, rotation.y + rotation_delta.x, look_amount.y) + rotation.y = rotate_toward(rotation.y, rotation.y + rotation_delta.x, look_amount.y) rotation_delta = Vector2.ZERO - container.position = lerp(container.position, container_offset - (applied_velocity / 30), delta * 10) - + container.position = lerp( + container.position, container_offset - (applied_velocity / 30), delta * 10 + ) + # Movement sound - + sound_footsteps.stream_paused = true - + if is_on_floor(): if abs(velocity.x) > 1 or abs(velocity.z) > 1: sound_footsteps.stream_paused = false - + # Landing after jump or falling - + camera.position.y = lerp(camera.position.y, 0.0, delta * 5) - - if is_on_floor() and gravity > 1 and !previously_floored: # Landed + + if is_on_floor() and gravity > 1 and !previously_floored: # Landed Audio.play("sounds/land.ogg") camera.position.y = -0.1 - + previously_floored = is_on_floor() - + # Falling/respawning - + if position.y < -10: get_tree().reload_current_scene() + # Mouse movement + func _input(event): if event is InputEventMouseMotion and mouse_captured: - input_mouse = event.relative / mouse_sensitivity - + rotation_delta.x -= event.relative.x / mouse_sensitivity rotation_delta.y -= event.relative.y / mouse_sensitivity + func handle_controls(_delta): - # Mouse capture - + if Input.is_action_just_pressed("mouse_capture"): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED mouse_captured = true - + if Input.is_action_just_pressed("mouse_capture_exit"): Input.mouse_mode = Input.MOUSE_MODE_VISIBLE mouse_captured = false - + input_mouse = Vector2.ZERO - + # Movement - + input.x = Input.get_axis("move_left", "move_right") input.z = Input.get_axis("move_forward", "move_back") - + movement_velocity = input.normalized() * movement_speed - + # Rotation - var rotation_input := Input.get_vector("camera_right", "camera_left", "camera_down", "camera_up") + var rotation_input := Input.get_vector( + "camera_right", "camera_left", "camera_down", "camera_up" + ) rotation_delta += rotation_input * gamepad_sensitivity # Shooting - + action_shoot() - + # Jumping - + if Input.is_action_just_pressed("jump"): - if jump_single or jump_double: Audio.play("sounds/jump_a.ogg, sounds/jump_b.ogg, sounds/jump_c.ogg") - + if jump_double: - gravity = -jump_strength jump_double = false - - if(jump_single): action_jump() - + + if jump_single: + action_jump() + # Weapon switching - + action_weapon_toggle() + # Handle gravity + func handle_gravity(delta): - gravity += 20 * delta - + if gravity > 0 and is_on_floor(): - jump_single = true gravity = 0 + # Jumping + func action_jump(): - gravity = -jump_strength - - jump_single = false; - jump_double = true; + + jump_single = false + jump_double = true + # Shooting + func action_shoot(): - if Input.is_action_pressed("shoot"): - - if !blaster_cooldown.is_stopped(): return # Cooldown for shooting - + if !blaster_cooldown.is_stopped(): + return # Cooldown for shooting + Audio.play(weapon.sound_shoot) - - container.position.z += 0.25 # Knockback of weapon visual - camera.rotation.x += 0.025 # Knockback of camera - movement_velocity += Vector3(0, 0, weapon.knockback) # Knockback - + + container.position.z += 0.25 # Knockback of weapon visual + camera.rotation.x += 0.025 # Knockback of camera + movement_velocity += Vector3(0, 0, weapon.knockback) # Knockback + # Set muzzle flash position, play animation - + muzzle.play("default") - + muzzle.rotation_degrees.z = randf_range(-45, 45) muzzle.scale = Vector3.ONE * randf_range(0.40, 0.75) muzzle.position = container.position - weapon.muzzle_position - + blaster_cooldown.start(weapon.cooldown) - + # Shoot the weapon, amount based on shot count - + for n in weapon.shot_count: - raycast.target_position.x = randf_range(-weapon.spread, weapon.spread) raycast.target_position.y = randf_range(-weapon.spread, weapon.spread) - + raycast.force_raycast_update() - - if !raycast.is_colliding(): continue # Don't create impact when raycast didn't hit - + + if !raycast.is_colliding(): + continue # Don't create impact when raycast didn't hit + var collider = raycast.get_collider() - + # Hitting an enemy - + if collider.has_method("damage"): collider.damage(weapon.damage) - + # Creating an impact animation - + var impact = preload("res://objects/impact.tscn") var impact_instance = impact.instantiate() - + impact_instance.play("shot") - + get_tree().root.add_child(impact_instance) - + impact_instance.position = raycast.get_collision_point() + (raycast.get_collision_normal() / 10) - impact_instance.look_at(camera.global_transform.origin, Vector3.UP, true) + impact_instance.look_at(camera.global_transform.origin, Vector3.UP, true) + # Toggle between available weapons (listed in 'weapons') + func action_weapon_toggle(): - if Input.is_action_just_pressed("weapon_toggle"): - weapon_index = wrap(weapon_index + 1, 0, weapons.size()) initiate_change_weapon(weapon_index) - + Audio.play("sounds/weapon_change.ogg") + # Initiates the weapon changing animation (tween) + func initiate_change_weapon(index): - weapon_index = index - + tween = get_tree().create_tween() tween.set_ease(Tween.EASE_OUT_IN) tween.tween_property(container, "position", container_offset - Vector3(0, 1, 0), 0.1) - tween.tween_callback(change_weapon) # Changes the model + tween.tween_callback(change_weapon) # Changes the model + # Switches the weapon model (off-screen) + func change_weapon(): - weapon = weapons[weapon_index] # Step 1. Remove previous weapon model(s) from container - + for n in container.get_children(): container.remove_child(n) - + # Step 2. Place new weapon model in container - + var weapon_model = weapon.model.instantiate() container.add_child(weapon_model) - + weapon_model.position = weapon.position weapon_model.rotation_degrees = weapon.rotation - + # Step 3. Set model to only render on layer 2 (the weapon camera) - + for child in weapon_model.find_children("*", "MeshInstance3D"): child.layers = 2 - + # Set weapon data - + raycast.target_position = Vector3(0, 0, -1) * weapon.max_distance crosshair.texture = weapon.crosshair + func damage(amount): - health -= amount - health_updated.emit(health) # Update health on HUD - + health_updated.emit(health) # Update health on HUD + if health < 0: - get_tree().reload_current_scene() # Reset when out of health + get_tree().reload_current_scene() # Reset when out of health diff --git a/scripts/audio.gd b/scripts/audio.gd index 77686bb..a1a0d8d 100644 --- a/scripts/audio.gd +++ b/scripts/audio.gd @@ -8,14 +8,14 @@ var bus = "master" var available = [] # The available players. var queue = [] # The queue of sounds to play. -func _ready(): +func _ready(): for i in num_players: var p = AudioStreamPlayer.new() add_child(p) - + available.append(p) - + p.volume_db = -10 p.finished.connect(_on_stream_finished.bind(p)) p.bus = bus @@ -24,16 +24,16 @@ func _ready(): func _on_stream_finished(stream): available.append(stream) -func play(sound_path): # Path (or multiple, separated by commas) + +func play(sound_path): # Path (or multiple, separated by commas) var sounds = sound_path.split(",") queue.append("res://" + sounds[randi() % sounds.size()].strip_edges()) -func _process(_delta): +func _process(_delta): if not queue.is_empty() and not available.is_empty(): - available[0].stream = load(queue.pop_front()) available[0].play() available[0].pitch_scale = randf_range(0.9, 1.1) - + available.pop_front() diff --git a/scripts/hud.gd b/scripts/hud.gd index 2585284..b3b6baa 100644 --- a/scripts/hud.gd +++ b/scripts/hud.gd @@ -1,5 +1,5 @@ extends CanvasLayer + func _on_health_updated(health): - $Health.text = str(health) + "%" diff --git a/scripts/weapon.gd b/scripts/weapon.gd index 4324497..2b72b9b 100644 --- a/scripts/weapon.gd +++ b/scripts/weapon.gd @@ -2,21 +2,21 @@ extends Resource class_name Weapon @export_subgroup("Model") -@export var model:PackedScene # Model of the weapon -@export var position:Vector3 # On-screen position -@export var rotation:Vector3 # On-screen rotation -@export var muzzle_position:Vector3 # On-screen position of muzzle flash +@export var model: PackedScene # Model of the weapon +@export var position: Vector3 # On-screen position +@export var rotation: Vector3 # On-screen rotation +@export var muzzle_position: Vector3 # On-screen position of muzzle flash @export_subgroup("Properties") -@export_range(0.1, 1) var cooldown: float = 0.1 # Firerate -@export_range(1, 20) var max_distance: int = 10 # Fire distance -@export_range(0, 100) var damage: float = 25 # Damage per hit -@export_range(0, 5) var spread: float = 0 # Spread of each shot -@export_range(1, 5) var shot_count: int = 1 # Amount of shots -@export_range(0, 50) var knockback: int = 20 # Amount of knockback +@export_range(0.1, 1) var cooldown: float = 0.1 # Firerate +@export_range(1, 20) var max_distance: int = 10 # Fire distance +@export_range(0, 100) var damage: float = 25 # Damage per hit +@export_range(0, 5) var spread: float = 0 # Spread of each shot +@export_range(1, 5) var shot_count: int = 1 # Amount of shots +@export_range(0, 50) var knockback: int = 20 # Amount of knockback @export_subgroup("Sounds") -@export var sound_shoot: String # Sound path +@export var sound_shoot: String # Sound path @export_subgroup("Crosshair") -@export var crosshair: Texture2D # Image of crosshair on-screen +@export var crosshair: Texture2D # Image of crosshair on-screen From 28fc66d961c457f5803d9eef09b862692d6947f2 Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sat, 14 Oct 2023 23:53:43 -0700 Subject: [PATCH 5/7] Tune up jump to reach platforms Increase jump power so you can jump to all platforms with enemies. --- objects/player.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objects/player.gd b/objects/player.gd index 19c0b42..a41b635 100644 --- a/objects/player.gd +++ b/objects/player.gd @@ -2,7 +2,7 @@ extends CharacterBody3D @export_subgroup("Properties") @export var movement_speed = 5 -@export var jump_strength = 7 +@export var jump_strength = 8 @export var max_look_speed := Vector2.ONE * 5.0 # in radians per second @export_subgroup("Weapons") From b2c60a56e3e15db89e7477d212502d69c84d9322 Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sun, 15 Oct 2023 00:04:49 -0700 Subject: [PATCH 6/7] Always have a valid weapon Fix crash when you're shooting when you die or when you start the game. Since weapon is nil (waiting for anim to finish before assigning it), the game crashes trying on Audio.play(weapon.sound_shoot). --- objects/player.gd | 1 + 1 file changed, 1 insertion(+) diff --git a/objects/player.gd b/objects/player.gd index a41b635..12f58f0 100644 --- a/objects/player.gd +++ b/objects/player.gd @@ -51,6 +51,7 @@ func _ready(): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED rotation_delta = Vector2.ZERO + weapon = weapons[weapon_index] # weapon must never be nil initiate_change_weapon(weapon_index) From a10a5c56bf0db8e2b95b4300011fb86b5e95161a Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Sun, 15 Oct 2023 00:20:23 -0700 Subject: [PATCH 7/7] Use circular movement deadzone get_vector is a circular deadzone, but two get_axis will be a cross-shaped one. https://docs.godotengine.org/en/stable/tutorials/inputs/controllers_gamepads_joysticks.html#which-input-singleton-method-should-i-use https://github.com/godotengine/godot-docs/issues/5378#issuecomment-1635899278 --- objects/player.gd | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/objects/player.gd b/objects/player.gd index 12f58f0..fa9e510 100644 --- a/objects/player.gd +++ b/objects/player.gd @@ -18,7 +18,6 @@ var mouse_captured := true var movement_velocity: Vector3 var rotation_delta: Vector2 # x: horizontal, y: vertical -var input: Vector3 var input_mouse: Vector2 var health: int = 100 @@ -157,10 +156,8 @@ func handle_controls(_delta): # Movement - input.x = Input.get_axis("move_left", "move_right") - input.z = Input.get_axis("move_forward", "move_back") - - movement_velocity = input.normalized() * movement_speed + var input := Input.get_vector("move_left", "move_right", "move_forward", "move_back") + movement_velocity = Vector3(input.x, 0, input.y).normalized() * movement_speed # Rotation