diff --git a/LICENSE.md b/LICENSE.md index fc44c93..6447933 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,19 @@ -Copyright © 2024 ArtyIF +Copyright (c) 2024 ArtyIF -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: +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: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index b5fdc2b..01417a5 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,16 @@ two cars (no way to easily switch between them). `addons/aacc` folder! Some files' licenses require attribution if you're going to use them! +**NOTE**: the project is semi-abandoned! Changes are still being made, but +only as necessary for the game I'm currently working on, No Downforce. Once +I'm done with that, I'm probably going to resume working fully on this project. + ## Dependencies -- Godot 4.4+ (tested on dev5) +- Godot 4.4+ (tested on dev6) - - For the Godot 4.3 version, see 3e0cc4987715be7c1ad1e39ebd9c060fab6e6751 - [lawnjelly's smoothing addon](https://github.com/lawnjelly/smoothing-addon/tree/4.x) - for physics interpolation (Godot 4.4's interpolation is currently broken?) + for physics interpolation (there is built-in one in Godot 4.4, but it needs some + extra adjustments to be usable) - [Hydraboo's TrailRenderer](https://github.com/Hyrdaboo/TrailRenderer) for skid trails - Blender 3.5 or later (3.0-3.4 might also work) for the demo scene diff --git a/addons/aacc/materials/particles/burnout/burnout_process.tres b/addons/aacc/materials/particles/burnout/burnout_process.tres index 1743dd1..69d535d 100644 --- a/addons/aacc/materials/particles/burnout/burnout_process.tres +++ b/addons/aacc/materials/particles/burnout/burnout_process.tres @@ -8,7 +8,6 @@ colors = PackedColorArray(1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0) gradient = SubResource("Gradient_4fd70") [sub_resource type="Curve" id="Curve_ea1f5"] -max_value = 2.0 bake_resolution = 256 _data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 2), 2.0, 0.0, 0, 0] point_count = 2 diff --git a/addons/aacc/scenes/burnout_particles.tscn b/addons/aacc/scenes/burnout_particles.tscn index 8f7d77d..5fb1764 100644 --- a/addons/aacc/scenes/burnout_particles.tscn +++ b/addons/aacc/scenes/burnout_particles.tscn @@ -8,6 +8,7 @@ material = ExtResource("2_ygvqw") size = Vector2(2, 2) [node name="BurnoutParticles" type="GPUParticles3D"] +layers = 2 sorting_offset = 10.0 cast_shadow = 0 gi_mode = 0 @@ -15,7 +16,8 @@ emitting = false amount = 50 amount_ratio = 0.0 lifetime = 2.0 -fixed_fps = 50 +fixed_fps = 0 +collision_base_size = 2.0 visibility_aabb = AABB(-25, -2, -25, 50, 10, 50) draw_order = 3 process_material = ExtResource("1_urvgu") diff --git a/addons/aacc/scenes/sparks.tscn b/addons/aacc/scenes/sparks.tscn index e84d510..25b4a88 100644 --- a/addons/aacc/scenes/sparks.tscn +++ b/addons/aacc/scenes/sparks.tscn @@ -11,6 +11,7 @@ one_shot = true explosiveness = 1.0 fixed_fps = 0 trail_enabled = true +trail_lifetime = 0.1 process_material = ExtResource("1_5lk4l") draw_pass_1 = ExtResource("2_jdqw7") script = ExtResource("3_smau7") diff --git a/addons/aacc/scripts/aacc_global.gd b/addons/aacc/scripts/aacc_global.gd index c9d6d0c..f9fb681 100644 --- a/addons/aacc/scripts/aacc_global.gd +++ b/addons/aacc/scripts/aacc_global.gd @@ -1,5 +1,6 @@ extends Node var current_car: Car +var current_car_input: CarInput var current_shadow_color: Color = Color.BLACK var current_shadow_color_amount: float = 0.0 diff --git a/addons/aacc/scripts/audio/car_tire_screech_sound.gd b/addons/aacc/scripts/audio/car_tire_screech_sound.gd index 40cba90..5089663 100644 --- a/addons/aacc/scripts/audio/car_tire_screech_sound.gd +++ b/addons/aacc/scripts/audio/car_tire_screech_sound.gd @@ -4,6 +4,7 @@ class_name CarTireScreechSound extends AudioStreamPlayer3D @onready var car: Car = get_node("..") func _physics_process(_delta: float) -> void: + pitch_scale = lerp(0.5, 1.25, car.burnout_amount) volume_db = linear_to_db(car.burnout_amount) diff --git a/addons/aacc/scripts/car.gd b/addons/aacc/scripts/car.gd index 8a2cb07..225bb1b 100644 --- a/addons/aacc/scripts/car.gd +++ b/addons/aacc/scripts/car.gd @@ -330,7 +330,7 @@ func update_revs(delta: float) -> void: #region Traction func get_brake_force() -> float: var brake_speed = clamp(local_linear_velocity.z, -1.0, 1.0) - return brake_speed * (linear_grip if linear_velocity.length() < 0.25 else brake_force) * (1.0 if input_handbrake else (input_forward if is_reversing() else input_backward)) + return brake_speed * brake_force * (1.0 if input_handbrake else (input_forward if is_reversing() else input_backward)) func get_side_grip_force() -> float: return -local_linear_velocity.x * mass diff --git a/addons/aacc/scripts/car_input.gd b/addons/aacc/scripts/car_input.gd index 820273b..f67d4a6 100644 --- a/addons/aacc/scripts/car_input.gd +++ b/addons/aacc/scripts/car_input.gd @@ -5,6 +5,9 @@ class_name CarInput extends Node @export var enabled: bool = true @onready var _car: Car = AACCGlobal.current_car +func _ready() -> void: + AACCGlobal.current_car_input = self + func _physics_process(delta: float) -> void: if not enabled: return if not _car: return diff --git a/addons/aacc/scripts/car_wheel.gd b/addons/aacc/scripts/car_wheel.gd index ebd0f90..d9e67f0 100644 --- a/addons/aacc/scripts/car_wheel.gd +++ b/addons/aacc/scripts/car_wheel.gd @@ -102,6 +102,7 @@ func configure_raycasts() -> void: raycast_instance_2.process_physics_priority = -1000 func set_raycast_values() -> void: + # TODO: apply forces per raycast var collision_point_1: Vector3 = raycast_instance_1.get_collision_point() var collision_normal_1: Vector3 = raycast_instance_1.get_collision_normal() var distance_1: float = raycast_instance_1.global_position.distance_to(collision_point_1) @@ -138,11 +139,12 @@ func update_visuals(delta: float) -> void: var steer_rotation: float = -car.smooth_steer.get_current_value() * car.base_steer_velocity * steer_multiplier if not (freeze_on_handbrake and car.input_handbrake): - current_forward_spin -= car.local_linear_velocity.z * delta / wheel_radius - if (not block_wheelspin) and car.local_linear_velocity.length() < 0.25: - # BUG: when wheelspinning backwards the wheel spins forward after - # letting go of the throttle - current_forward_spin += (car.max_acceleration * delta * (1.0 if car.current_gear >= 0 else -1.0) * car.burnout_amount) / (car.mass * wheel_radius) + if is_colliding: # TODO: smooth it out + current_forward_spin -= car.local_linear_velocity.z * delta / wheel_radius + if (not block_wheelspin) and car.local_linear_velocity.length() < 0.25: + # BUG: when wheelspinning backwards the wheel spins forward after + # letting go of the throttle + current_forward_spin += (car.max_acceleration * delta * (1.0 if car.current_gear >= 0 else -1.0) * car.burnout_amount) / (car.mass * wheel_radius) if current_forward_spin > 2 * PI: current_forward_spin -= 2 * PI diff --git a/addons/aacc/scripts/hit_reaction.gd b/addons/aacc/scripts/hit_reaction.gd index 9149b20..ef5458d 100644 --- a/addons/aacc/scripts/hit_reaction.gd +++ b/addons/aacc/scripts/hit_reaction.gd @@ -19,11 +19,13 @@ func play_hit_sound(_body: Node) -> void: if projected_velocity.length() > 0.1: # TODO: have a globally-accessible class take care of it var hit_instance: AudioStreamPlayer3D - var hit_amount: float = clamp((projected_velocity.length() - 0.1) / 5.0, 0.0, 1.0) + var hit_amount: float if car.global_basis.y.dot(state.get_contact_local_normal(i)) < 0.9659: + hit_amount = clamp((projected_velocity.length() - 0.1) / 5.0, 0.0, 1.0) hit_instance = hit_sound.instantiate() else: + hit_amount = clamp((projected_velocity.length() - 0.1) / 2.0, 0.0, 1.0) hit_instance = land_sound.instantiate() hit_instance.volume_db = linear_to_db(hit_amount) hit_instance.pitch_scale = randf_range(0.9, 1.1) diff --git a/addons/aacc/shaders/shadow_decal_shader.gdshader b/addons/aacc/shaders/shadow_decal_shader.gdshader index 0bf620b..5b279d9 100644 --- a/addons/aacc/shaders/shadow_decal_shader.gdshader +++ b/addons/aacc/shaders/shadow_decal_shader.gdshader @@ -4,9 +4,12 @@ shader_type spatial; render_mode world_vertex_coords, unshaded, cull_front, depth_test_disabled, blend_mul, fog_disabled; -uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap; +uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear; +#if CURRENT_RENDERER == RENDERER_FORWARD_PLUS + uniform sampler2D NORMAL_TEXTURE : hint_normal_roughness_texture, filter_linear; +#endif -uniform sampler2D shadow_texture : source_color, hint_default_black, repeat_disable; +uniform sampler2D shadow_texture : source_color, hint_default_black, repeat_disable, filter_linear_mipmap_anisotropic; uniform int shadow_texture_mipmaps = 9; uniform float shadow_size = 4.0; @@ -26,10 +29,10 @@ void vertex() { // Credit: https://stackoverflow.com/questions/32227283/getting-world-position-from-depth-buffer-value vec3 world_pos_from_depth(float depth, vec2 screen_uv, mat4 inverse_proj, mat4 inverse_view) { float z = depth; - if (CURRENT_RENDERER == RENDERER_COMPATIBILITY) { + #if CURRENT_RENDERER == RENDERER_COMPATIBILITY z *= 2.0; z -= 1.0; - } + #endif vec4 clipSpacePosition = vec4(screen_uv * 2.0 - 1.0, z, 1.0); vec4 viewSpacePosition = inverse_proj * clipSpacePosition; viewSpacePosition /= viewSpacePosition.w; @@ -83,8 +86,16 @@ void fragment() { shadow *= vec3(1.0) - (shadow_color * shadow_color_amount); shadow = clamp(vec3(1.0) - shadow, 0.0, 1.0); - ALBEDO = mix(vec3(1.0), shadow, vertical_blend); - if (CURRENT_RENDERER == RENDERER_COMPATIBILITY) { + float normal_blend = 1.0; + #if CURRENT_RENDERER == RENDERER_FORWARD_PLUS + vec3 normal = texture(NORMAL_TEXTURE, SCREEN_UV).xyz * 2.0 - 1.0; + vec3 world_normals = (INV_VIEW_MATRIX * vec4(normal, 0.0)).xyz; + mat3 basis = mat3(MODEL_MATRIX); + normal_blend = clamp(dot(basis * vec3(0.0, 1.0, 0.0), world_normals), 0.0, 1.0); + #endif + + ALBEDO = mix(vec3(1.0), shadow, vertical_blend * normal_blend); + #if CURRENT_RENDERER == RENDERER_COMPATIBILITY // Compatibility renderer seems to use some tricks for HDR that break // multiplication blend modes right now. // @@ -96,10 +107,10 @@ void fragment() { // NOTE: This value is unnecessary when glow is disabled and tonemap's // white value is 1. It might require adjusting with other white values. ALBEDO *= 3.719675661; - } - if (CURRENT_RENDERER == RENDERER_MOBILE) { + #endif + #if CURRENT_RENDERER == RENDERER_MOBILE // Similar story to Compatibility renderer, except that this value is // fixed and doesn't change depending on environment settings. ALBEDO *= 2.0; - } + #endif }