Compare commits

...

9 Commits

Author SHA1 Message Date
Kenney a8113ca3ed Merge branch 'main' of https://github.com/KenneyNL/Starter-Kit-FPS 2025-09-16 18:05:20 +07:00
Kenney 3d68eb389c Upgraded to Godot 4.5
The project has been upgraded to Godot 4.5. The visuals have been tweaked slightly, a new skybox has been added and the readme now has basic instructions
2025-09-16 18:04:48 +07:00
Kenney 51e4df4c2e
Merge pull request #12 from Kurt-Burgoyne/MouseRotation
Separation of controller and mouse rotation
2025-09-16 13:30:22 +07:00
Kenney eafd11a728
Merge pull request #11 from Lamoot/many-jump
Multi-jump system, as many jumps as desired.
2025-09-16 13:27:29 +07:00
Kenney 84be51d289
Merge pull request #13 from kelo221/main
Fix shot accuracy
2025-09-16 13:27:06 +07:00
V e48c826067 Fix shot accuracy
The camera gets moved upward before the gun fires, this causes the impact scene and the target of the shot to be incorrect.
2024-04-10 19:07:35 +07:00
Kurt Burgoyne 45036ffa9c Removed left over comment 2024-01-13 11:20:35 +07:00
Kurt Burgoyne 9efe92d92e Seperated Controller and Mouse camera rotation. 2024-01-13 11:18:52 +07:00
Lamoot 50efc5d5d5
Multi-jump system, as many umps as desired.
Instead of hard-coding the jumping mechanic to solely 2 jumps, i.e. double-jump, allow for any number of jumps. By default this is still set to 2, but more are possible if required.
2023-12-13 20:50:35 +07:00
17 changed files with 113 additions and 61 deletions

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Kenney
Copyright (c) 2025 Kenney
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

@ -22,11 +22,21 @@ This package includes a basic template for a first person shooter in Godot 4.3 (
| <kbd>Left mouse button</kbd> | Shoot |
| <kbd>E</kbd> | Switch weapon |
### Instructions
1. How to add more weapons?
Duplicate one of the existing resources in the 'weapons' folder, adjust the properties in the inspector. Select the 'Player' node in the scene and add your new resources to the 'Weapons' array.
2. How to adjust properties like cooldown, damage and spread?
Select the resource of the weapon you'd like to change in the 'weapons' folder, adjust the properties in the inspector.
### License
MIT License
Copyright (c) 2024 Kenney
Copyright (c) 2025 Kenney
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

@ -15,9 +15,12 @@ dest_files=["res://.godot/imported/blaster.glb-865d95bc6d15a20a70b45829eaeb4dc5.
nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
@ -31,6 +34,9 @@ animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=0
gltf/embedded_image_handling=1

@ -0,0 +1 @@
uid://bfgpo8fvf136p

@ -0,0 +1 @@
uid://b6udw8uhlp4ei

@ -0,0 +1 @@
uid://bwkexrmt718dx

@ -2,6 +2,7 @@ extends CharacterBody3D
@export_subgroup("Properties")
@export var movement_speed = 5
@export_range(0, 100) var number_of_jumps:int = 2
@export var jump_strength = 8
@export_subgroup("Weapons")
@ -25,8 +26,7 @@ var gravity := 0.0
var previously_floored := false
var jump_single := true
var jump_double := true
var jumps_remaining:int
var container_offset = Vector3(1.2, -1.1, -2.75)
@ -52,7 +52,7 @@ func _ready():
weapon = weapons[weapon_index] # Weapon must never be nil
initiate_change_weapon(weapon_index)
func _physics_process(delta):
func _process(delta):
# Handle functions
@ -60,7 +60,7 @@ func _physics_process(delta):
handle_gravity(delta)
# Movement
var applied_velocity: Vector3
movement_velocity = transform.basis * movement_velocity # Move forward
@ -71,13 +71,7 @@ func _physics_process(delta):
velocity = applied_velocity
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)
# Rotation
container.position = lerp(container.position, container_offset - (basis.inverse() * applied_velocity / 30), delta * 10)
# Movement sound
@ -107,13 +101,10 @@ func _physics_process(delta):
func _input(event):
if event is InputEventMouseMotion and mouse_captured:
input_mouse = event.relative / mouse_sensitivity
rotation_target.y -= event.relative.x / mouse_sensitivity
rotation_target.x -= event.relative.y / mouse_sensitivity
handle_rotation(event.relative.x, event.relative.y, false)
func handle_controls(_delta):
func handle_controls(delta):
# Mouse capture
@ -128,17 +119,13 @@ func handle_controls(_delta):
input_mouse = Vector2.ZERO
# Movement
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
# Handle Controller Rotation
var rotation_input := Input.get_vector("camera_right", "camera_left", "camera_down", "camera_up")
rotation_target -= Vector3(-rotation_input.y, -rotation_input.x, 0).limit_length(1.0) * gamepad_sensitivity
rotation_target.x = clamp(rotation_target.x, deg_to_rad(-90), deg_to_rad(90))
if rotation_input:
handle_rotation(rotation_input.x, rotation_input.y, true, delta)
# Shooting
@ -148,39 +135,43 @@ func handle_controls(_delta):
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 jumps_remaining:
action_jump()
# Weapon switching
action_weapon_toggle()
# Camera rotation
func handle_rotation(xRot: float, yRot: float, isController: bool, delta: float = 0.0):
if isController:
rotation_target -= Vector3(-yRot, -xRot, 0).limit_length(1.0) * gamepad_sensitivity
rotation_target.x = clamp(rotation_target.x, deg_to_rad(-90), deg_to_rad(90))
camera.rotation.x = lerp_angle(camera.rotation.x, rotation_target.x, delta * 25)
rotation.y = lerp_angle(rotation.y, rotation_target.y, delta * 25)
else:
rotation_target += (Vector3(-yRot, -xRot, 0) / mouse_sensitivity)
rotation_target.x = clamp(rotation_target.x, deg_to_rad(-90), deg_to_rad(90))
camera.rotation.x = rotation_target.x;
rotation.y = rotation_target.y;
# Handle gravity
func handle_gravity(delta):
gravity += 20 * delta
if gravity > 0 and is_on_floor():
jump_single = true
jumps_remaining = number_of_jumps
gravity = 0
# Jumping
func action_jump():
gravity = -jump_strength
jump_single = false;
jump_double = true;
func action_jump():
Audio.play("sounds/jump_a.ogg, sounds/jump_b.ogg, sounds/jump_c.ogg")
gravity = -jump_strength
jumps_remaining -= 1
# Shooting
@ -192,10 +183,6 @@ func action_shoot():
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
# Set muzzle flash position, play animation
muzzle.play("default")
@ -234,7 +221,11 @@ func action_shoot():
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)
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
# Toggle between available weapons (listed in 'weapons')

@ -0,0 +1 @@
uid://cu47grjp072jk

@ -13,7 +13,7 @@ config_version=5
config/name="Starter Kit FPS"
config/tags=PackedStringArray("starterkit")
run/main_scene="res://scenes/main.tscn"
config/features=PackedStringArray("4.3", "Forward Plus")
config/features=PackedStringArray("4.5", "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"
@ -29,8 +29,8 @@ window/size/viewport_height=720
[editor]
movie_writer/mjpeg_quality=1.0
movie_writer/movie_file="D:/Godot/test.avi"
movie_writer/mjpeg_quality=1.0
[input]
@ -104,6 +104,7 @@ 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,"location":0,"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)
, 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":3,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}

@ -1,18 +1,13 @@
[gd_resource type="Environment" load_steps=5 format=3 uid="uid://jvmpkdwaeaq"]
[gd_resource type="Environment" load_steps=4 format=3 uid="uid://jvmpkdwaeaq"]
[sub_resource type="Gradient" id="Gradient_tio4a"]
colors = PackedColorArray(0.591319, 0.47222, 0.770854, 1, 0.315871, 0.421528, 0.674528, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_4e6px"]
gradient = SubResource("Gradient_tio4a")
fill_to = Vector2(0, 1)
[ext_resource type="Texture2D" uid="uid://cb7sdk1i5rx04" path="res://sprites/skybox.png" id="1_u3n42"]
[sub_resource type="PanoramaSkyMaterial" id="PanoramaSkyMaterial_fjheq"]
panorama = SubResource("GradientTexture2D_4e6px")
panorama = ExtResource("1_u3n42")
energy_multiplier = 0.5
[sub_resource type="Sky" id="Sky_7bk1c"]
sky_material = SubResource("PanoramaSkyMaterial_fjheq")
radiance_size = 0
[resource]
background_mode = 2
@ -20,7 +15,6 @@ background_color = Color(0.360784, 0.392157, 0.462745, 1)
sky = SubResource("Sky_7bk1c")
ambient_light_source = 2
ambient_light_color = Color(0.662745, 0.694118, 0.772549, 1)
ambient_light_energy = 1.15
tonemap_mode = 2
ssao_enabled = true
ssao_radius = 0.45
@ -29,5 +23,7 @@ ssao_power = 5.0
glow_enabled = true
glow_levels/2 = 0.6
glow_levels/3 = 0.6
glow_levels/5 = 0.0
glow_levels/5 = 6.0
glow_intensity = 2.0
glow_strength = 0.45
glow_bloom = 0.5

@ -2,7 +2,7 @@
[ext_resource type="Environment" uid="uid://jvmpkdwaeaq" path="res://scenes/main-environment.tres" id="1_q8fpv"]
[ext_resource type="PackedScene" uid="uid://dl2ed4gkybggf" path="res://objects/player.tscn" id="2_elriq"]
[ext_resource type="Script" path="res://scripts/hud.gd" id="3_s8mkj"]
[ext_resource type="Script" uid="uid://by0qn28x1i1jj" path="res://scripts/hud.gd" id="3_s8mkj"]
[ext_resource type="FontFile" uid="uid://biqtga8moh7ah" path="res://fonts/lilita_one_regular.ttf" id="3_w27de"]
[ext_resource type="PackedScene" uid="uid://dpm3l05d7fu35" path="res://objects/platform.tscn" id="5_3s40e"]
[ext_resource type="PackedScene" uid="uid://r7rt7pth4u7o" path="res://objects/wall_low.tscn" id="5_6vel1"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 281 KiB

@ -0,0 +1 @@
uid://d2fg3ewfjx4u4

@ -0,0 +1 @@
uid://by0qn28x1i1jj

@ -0,0 +1 @@
uid://dg01pkkc1c5vd

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cb7sdk1i5rx04"
path.bptc="res://.godot/imported/skybox.png-3a75a15c5dbffccdaa926738885bd0eb.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://sprites/skybox.png"
dest_files=["res://.godot/imported/skybox.png-3a75a15c5dbffccdaa926738885bd0eb.bptc.ctex"]
[params]
compress/mode=2
compress/high_quality=true
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=false
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0