diff --git a/CHANGELOG.md b/CHANGELOG.md index e67f77b..c003fb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ### Changed ### Deprecated ### Removed +- Remove LOD scripts ([#35](https://github.com/MechanicalFlower/Marble/pull/35)) ### Fixed - Correct loading of sound effects for the menu ([#27](https://github.com/MechanicalFlower/Marble/pull/27)) - Include `override.cfg` in each export presets ([#28](https://github.com/MechanicalFlower/Marble/pull/28)) diff --git a/scenes/marble.tscn b/scenes/marble.tscn index d6a1e14..215bdb5 100644 --- a/scenes/marble.tscn +++ b/scenes/marble.tscn @@ -1,23 +1,12 @@ -[gd_scene load_steps=12 format=3 uid="uid://4g5aorgnd1hu"] +[gd_scene load_steps=9 format=3 uid="uid://4g5aorgnd1hu"] [ext_resource type="Script" path="res://scripts/marble.gd" id="1"] [ext_resource type="Material" uid="uid://5gxm1ehx7waa" path="res://resources/materials/xray_marble.tres" id="2"] -[ext_resource type="Script" path="res://scripts/lod/lod_spatial.gd" id="2_5e2c6"] [ext_resource type="Script" path="res://scripts/roll_sound.gd" id="4"] [ext_resource type="AudioStream" uid="uid://3hc6gfblh3gf" path="res://assets/sounds/sfx/roll.wav" id="4_d1o80"] [ext_resource type="AudioStream" uid="uid://b7ga03rbxi6qs" path="res://assets/sounds/sfx/hit.wav" id="6_iicuw"] [ext_resource type="AudioStream" uid="uid://c44julexev4dj" path="res://assets/sounds/explosion/bomb.ogg" id="7_1gve1"] -[sub_resource type="SphereMesh" id="1"] -radius = 0.3 -height = 0.6 - -[sub_resource type="SphereMesh" id="5"] -radius = 0.3 -height = 0.6 -radial_segments = 32 -rings = 16 - [sub_resource type="SphereMesh" id="4"] radius = 0.3 height = 0.6 @@ -33,24 +22,9 @@ max_contacts_reported = 10000 contact_monitor = true script = ExtResource("1") -[node name="LODSpatial" type="Node3D" parent="."] -script = ExtResource("2_5e2c6") - -[node name="Ball-0" type="MeshInstance3D" parent="LODSpatial"] -mesh = SubResource("1") -skeleton = NodePath("../..") -surface_material_override/0 = ExtResource("2") - -[node name="Ball-1" type="MeshInstance3D" parent="LODSpatial"] -visible = false -mesh = SubResource("5") -skeleton = NodePath("../..") -surface_material_override/0 = ExtResource("2") - -[node name="Ball-2" type="MeshInstance3D" parent="LODSpatial"] -visible = false +[node name="Ball" type="MeshInstance3D" parent="."] +unique_name_in_owner = true mesh = SubResource("4") -skeleton = NodePath("../..") surface_material_override/0 = ExtResource("2") [node name="CollisionShape" type="CollisionShape3D" parent="."] diff --git a/scripts/lod/lod_particles.gd b/scripts/lod/lod_particles.gd deleted file mode 100644 index 7a8d7fc..0000000 --- a/scripts/lod/lod_particles.gd +++ /dev/null @@ -1,51 +0,0 @@ -class_name LODParticles -extends GPUParticles3D - -# If `false`, LOD won't update anymore. This can be used for performance comparison -# purposes. -@export var enable_lod := true - -# The maximum particle emitting distance in units. -# Past this distance, particles will no longer emit. -@export_range(0.0, 1000.0, 0.1) var max_emit_distance := 50 - -# The rate at which LODs will be updated (in seconds). Lower values are more reactive -# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. -# Set this accordingly depending on your camera movement speed. -# The default value should suit most projects already. -# Note: Slow cameras don't need to have LOD-enabled objects update their status often. -# This can overridden by setting the project setting `lod/_refresh_rate`. -var _refresh_rate := 0.25 - -# The internal refresh timer. -var _timer := 0.0 - - -func _ready() -> void: - if ProjectSettings.has_setting("lod/_refresh_rate"): - _refresh_rate = ProjectSettings.get_setting("lod/_refresh_rate") - - # Add random jitter to the timer to ensure LODs don't all swap at the same time. - randomize() - _timer += randf_range(0, _refresh_rate) - - -# Despite LOD not being related to physics, we chose to run in `_physics_process()` -# to minimize the amount of method calls per second (and therefore decrease CPU usage). -func _physics_process(delta: float) -> void: - if not enable_lod: - return - - # We need a camera to do the rest. - var camera := get_viewport().get_camera_3d() as Camera3D - if camera == null: - return - - if _timer <= _refresh_rate: - _timer += delta - return - - _timer = 0.0 - - var distance := camera.global_transform.origin.distance_to(global_transform.origin) + lod_bias - emitting = distance < max_emit_distance diff --git a/scripts/lod/lod_spatial.gd b/scripts/lod/lod_spatial.gd deleted file mode 100644 index 16afe05..0000000 --- a/scripts/lod/lod_spatial.gd +++ /dev/null @@ -1,85 +0,0 @@ -class_name LODSpatial -extends Node3D - -# If `false`, LOD won't update anymore. This can be used for performance comparison -# purposes. -@export var enable_lod := true - -# The maximum LOD 0 (high quality) distance in units. -@export_range(0.0, 1000.0, 0.1) var lod_0_max_distance := 10 - -# The maximum LOD 1 (medium quality) distance in units. -@export_range(0.0, 1000.0, 0.1) var lod_1_max_distance := 25 - -# The maximum LOD 2 (low quality) distance in units. -# Past this distance, all LOD variants are hidden. -@export_range(0.0, 1000.0, 0.1) var lod_2_max_distance := 100 - -# The rate at which LODs will be updated (in seconds). Lower values are more reactive -# but use more CPU, which is especially noticeable with large amounts of LOD-enabled nodes. -# Set this accordingly depending on your camera movement speed. -# The default value should suit most projects already. -# Note: Slow cameras don't need to have LOD-enabled objects update their status often. -# This can overridden by setting the project setting `lod/refresh_rate`. -var _refresh_rate := 0.25 - -# The LOD bias in units. -# Positive values will decrease the detail level and improve performance. -# Negative values will improve visual appearance at the cost of performance. -# This can overridden by setting the project setting `lod/bias`. -var _lod_bias := 0.0 - -# The internal refresh timer. -var _timer := 0.0 - - -func _ready() -> void: - if ProjectSettings.has_setting(&"lod/spatial_bias"): - _lod_bias = ProjectSettings.get_setting(&"lod/spatial_bias") - if ProjectSettings.has_setting(&"lod/refresh_rate"): - _refresh_rate = ProjectSettings.get_setting(&"lod/refresh_rate") - - # Add random jitter to the timer to ensure LODs don't all swap at the same time. - randomize() - _timer += randf_range(0, _refresh_rate) - - -# Despite LOD not being related to physics, we chose to run in `_physics_process()` -# to minimize the amount of method calls per second (and therefore decrease CPU usage). -func _physics_process(delta: float) -> void: - if not enable_lod: - return - - # We need a camera to do the rest. - var camera := get_viewport().get_camera_3d() - if camera == null: - return - - if _timer <= _refresh_rate: - _timer += delta - return - - _timer = 0.0 - - var distance := camera.global_transform.origin.distance_to(global_transform.origin) + _lod_bias - # The LOD level to choose (lower is more detailed). - var lod: int - if distance < lod_0_max_distance: - lod = 0 - elif distance < lod_1_max_distance: - lod = 1 - elif distance < lod_2_max_distance: - lod = 2 - else: - # Hide the LOD object entirely. - lod = 3 - - for node in get_children(): - # `-lod` also matches `-lod0`, `-lod1`, `-lod2`, … - if node.has_method(&"set_visible"): - if "-lod0" in node.name: - node.visible = lod == 0 - if "-lod1" in node.name: - node.visible = lod == 1 - if "-lod2" in node.name: - node.visible = lod == 2 diff --git a/scripts/main.gd b/scripts/main.gd index 9a42f7a..44d66dd 100644 --- a/scripts/main.gd +++ b/scripts/main.gd @@ -1,5 +1,4 @@ class_name Main - extends Node enum State { MODE_START, MODE_PAUSE, MODE_MARBLE } @@ -77,7 +76,7 @@ func _unhandled_input(event): ) else: - print("Could not place start marble") + printerr("No marble to focus on!") KEY_ESCAPE: if _mode != State.MODE_START and _mode != State.MODE_PAUSE: @@ -114,6 +113,7 @@ func _unhandled_input(event): break +# Reset marble positions func reset_position() -> void: _positions = [] for i in range(7): @@ -121,12 +121,13 @@ func reset_position() -> void: _positions.append([i, j]) +# Try placing a new marble on the start line func try_place_start_marble() -> Marble: var piece = get_highest_piece() if piece == null: return null if len(_positions) == 0: - print("There are limited places to ensure equality among the marbles.") + printerr("There are limited places to ensure equality among the marbles.") return null randomize() var position = _positions.pop_at(randi() % len(_positions)) @@ -150,6 +151,7 @@ func try_place_start_marble() -> Marble: return new_marble +# Get the highest piece in the race func get_highest_piece() -> Piece: var pieces = _race.get_children() if len(pieces) == 0: @@ -161,8 +163,9 @@ func get_highest_piece() -> Piece: return highest_piece +# Replace cameras with a new one func replace_camera(new_camera, old_cameras) -> void: - # Ensure old cameras are remove from the current scene + # Ensure old cameras are removed from the current scene for camera in old_cameras: if camera.is_inside_tree(): remove_from_tree(camera) @@ -171,6 +174,7 @@ func replace_camera(new_camera, old_cameras) -> void: add_child(new_camera) +# Set the game mode func set_mode(mode): var start_a_new_race = false @@ -182,19 +186,19 @@ func set_mode(mode): for marble in _marbles: marble.pause() - # Ensure timer is reset + # Ensure the timer is reset _race_has_started = false _timer.set_wait_time(10) _timer.stop() - # Ensure that the pause menu is close + # Ensure that the pause menu is closed if _pause_menu.visible: _pause_menu.close() _mode = mode if _mode == State.MODE_MARBLE: - # If no marbles exists + # If no marbles exist if start_a_new_race: await Fade.fade_out(1, Color.BLACK, "Diamond", false, false).finished @@ -250,6 +254,7 @@ func set_mode(mode): replace_camera(_rotation_camera, [_cinematic_camera]) +# Remove a node from the scene tree static func remove_from_tree(node): node.get_parent().remove_child(node) @@ -311,6 +316,7 @@ func _process(delta): replace_camera(_rotation_camera, [_cinematic_camera]) +# Handle victory conditions on explosion mode func explosion_victory(_last_marble: Marble) -> bool: var marble_exploded_count := 0 var tmp_marble = null diff --git a/scripts/marble.gd b/scripts/marble.gd index 6477486..e782362 100644 --- a/scripts/marble.gd +++ b/scripts/marble.gd @@ -14,6 +14,7 @@ var _checkpoint_count := 0 @onready var _name := get_node(^"%Name") as Label3D @onready var _bomb_sound = get_node(^"%BombSound") @onready var _score = get_node(^"%Score") +@onready var _ball_mesh := get_node(^"%Ball") func _ready() -> void: @@ -23,16 +24,15 @@ func _ready() -> void: # Set material color var color = Color(randf(), randf(), randf()) - for i in range(3): - var x_ray_material: StandardMaterial3D = ( - get_node("LODSpatial/Ball-%d" % i).get_active_material(0) - ) - x_ray_material.set_albedo(color) - var toon_material: StandardMaterial3D = x_ray_material.get_next_pass() - toon_material.set_albedo(color) + var x_ray_material: StandardMaterial3D = ( + _ball_mesh.get_active_material(0) + ) + x_ray_material.set_albedo(color) + var toon_material: StandardMaterial3D = x_ray_material.get_next_pass() + toon_material.set_albedo(color) # toon_material.set_shader_parameter(&"albedo", color) - x_ray_material.set_next_pass(toon_material) - get_node("LODSpatial/Ball-%d" % i).set_surface_override_material(0, x_ray_material) + x_ray_material.set_next_pass(toon_material) + _ball_mesh.set_surface_override_material(0, x_ray_material) # Set collision mask var collision_enabled = SettingsManager.get_value(&"marbles", &"collision_enabled") as bool