diff --git a/project.godot b/project.godot index 70cd1c1..09ebfe4 100644 --- a/project.godot +++ b/project.godot @@ -22,7 +22,7 @@ config/icon="res://icon.svg" CursorManager="*res://scripts/globals/cursor_manager.gd" FullscreenManager="*res://scripts/globals/fullscreen_manager.gd" -DebugDraw="*res://scripts/globals/debug_draw.gd" +DebugManager="*res://scripts/globals/debug_manager.gd" UiManager="*res://scripts/globals/ui_manager.gd" HoveringManager="*res://scripts/globals/hovering_manager.gd" SelectionManager="*res://scripts/globals/selection_manager.gd" @@ -86,5 +86,5 @@ toggle_camera_navigation={ 3d_physics/layer_1="default" 3d_physics/layer_2="units" -3d_physics/layer_3="controlled_units" +3d_physics/layer_3="Layer 3" 3d_physics/layer_9="items" diff --git a/scenes/ui/anthill_info.tscn b/scenes/ui/anthill_info.tscn index 493fa1f..3a8fa18 100644 --- a/scenes/ui/anthill_info.tscn +++ b/scenes/ui/anthill_info.tscn @@ -22,20 +22,28 @@ script = ExtResource("2_aj5vl") [node name="AddOneButton" type="Button" parent="."] layout_mode = 0 -offset_left = 166.0 +offset_left = 138.0 offset_top = 44.0 -offset_right = 193.0 +offset_right = 165.0 offset_bottom = 75.0 text = "+1" [node name="AddFiveButton" type="Button" parent="."] layout_mode = 0 -offset_left = 197.0 +offset_left = 169.0 offset_top = 44.0 -offset_right = 224.0 +offset_right = 196.0 offset_bottom = 75.0 text = "+5" +[node name="AddMaxButton" type="Button" parent="."] +layout_mode = 0 +offset_left = 200.0 +offset_top = 45.0 +offset_right = 242.0 +offset_bottom = 76.0 +text = "max" + [node name="HoneydewCounter" parent="." instance=ExtResource("3_8onrx")] layout_mode = 0 offset_left = 13.0 diff --git a/scenes/units/abstract/controlled_unit.tscn b/scenes/units/abstract/controlled_unit.tscn index 232465a..c5f5c64 100644 --- a/scenes/units/abstract/controlled_unit.tscn +++ b/scenes/units/abstract/controlled_unit.tscn @@ -10,7 +10,6 @@ center_offset = Vector3(0, 0.001, 0) orientation = 1 [node name="ControlledUnit" instance=ExtResource("1_iivmb")] -collision_layer = 4 script = ExtResource("2_ruawn") [node name="SelectionIndicator" type="MeshInstance3D" parent="." index="6"] diff --git a/scenes/units/abstract/unit.tscn b/scenes/units/abstract/unit.tscn index 1690a1f..c3a1cb7 100644 --- a/scenes/units/abstract/unit.tscn +++ b/scenes/units/abstract/unit.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=5 format=3 uid="uid://c70vx0utm5knp"] +[gd_scene load_steps=6 format=3 uid="uid://c70vx0utm5knp"] [ext_resource type="Script" path="res://scripts/units/unit.gd" id="1_ulhs6"] [ext_resource type="Material" uid="uid://f0nlf4tdpvbd" path="res://resources/materials/indicators/hover_indicator_mat.tres" id="2_uk1jy"] @@ -11,6 +11,8 @@ material = ExtResource("2_uk1jy") center_offset = Vector3(0, 0.001, 0) orientation = 1 +[sub_resource type="BoxMesh" id="BoxMesh_hvf81"] + [node name="Unit" type="CharacterBody3D"] collision_layer = 2 collision_mask = 0 @@ -40,3 +42,6 @@ neighbor_distance = 10.0 aabb = AABB(-0.25, 0, -0.25, 0.5, 0.5, 0.5) [node name="UiOrigin" type="Marker3D" parent="."] + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_hvf81") diff --git a/scripts/ambient_audio.gd b/scripts/ambient_audio.gd index 3a88cbf..efd3e91 100644 --- a/scripts/ambient_audio.gd +++ b/scripts/ambient_audio.gd @@ -27,7 +27,7 @@ func _ready() -> void: func _process(_delta: float) -> void: - filter.cutoff_hz = lerp( + filter.cutoff_hz = lerpf( ZOOMED_IN_CUTOFF, ZOOMED_OUT_CUTOFF, main_camera.zoom_value, diff --git a/scripts/globals/debug_draw.gd b/scripts/globals/debug_manager.gd similarity index 93% rename from scripts/globals/debug_draw.gd rename to scripts/globals/debug_manager.gd index 666a9db..7727111 100644 --- a/scripts/globals/debug_draw.gd +++ b/scripts/globals/debug_manager.gd @@ -15,7 +15,7 @@ var markers_to_draw: Array[Dictionary] = [] var circles_to_draw: Array[Dictionary] = [] var text_to_draw: PackedStringArray = [] -@onready var camera: Camera3D = get_viewport().get_camera_3d() +@onready var main_camera: MainCamera = $/root/World/MainCamera func _ready() -> void: @@ -38,6 +38,8 @@ func _process(_delta: float) -> void: text('fps: ' + str(Performance.get_monitor(Performance.TIME_FPS))) text('draw calls: ' + str(Performance.get_monitor(Performance.RENDER_TOTAL_DRAW_CALLS_IN_FRAME))) + text('camera anim step: ' + str(main_camera.advance_anim_step)) + text('select anim step: ' + str(SelectionManager.advance_anim_step)) func _input(event: InputEvent) -> void: @@ -80,7 +82,7 @@ func circle(pos: Vector3, color: Color = DEFAULT_COLOR) -> void: func _unproject(pos: Vector3) -> Vector2: - return camera.unproject_position(pos) + return main_camera.unproject_position(pos) func _draw_text() -> void: diff --git a/scripts/globals/selection_manager.gd b/scripts/globals/selection_manager.gd index c29890a..036d08d 100644 --- a/scripts/globals/selection_manager.gd +++ b/scripts/globals/selection_manager.gd @@ -3,6 +3,10 @@ extends Node const MIN_DRAG_DISTANCE: float = 15 const UNIT_SELECT_OFFSET: float = 0.25 +const ANIM_MAX_STEP = 30 +const MIN_VISIBLE_UNITS = 25 +const MAX_VISIBLE_UNITS = 120 + var frustrum_polygon: ConvexPolygonShape3D = ConvexPolygonShape3D.new() var frustrum_polygon_points: PackedVector3Array = [ Vector3.ZERO, @@ -17,6 +21,7 @@ var visible_units: Dictionary = {} var mouse_pressed: bool = false var selecting: bool = false var selection_rect: Rect2 = Rect2() +var advance_anim_step: int = 1 var rect_style := preload("res://resources/styles/selection_rect.tres") @@ -34,7 +39,7 @@ func _ready() -> void: frustrum_area.body_exited.connect(_on_frustrum_area_body_exited) frustrum_area.input_ray_pickable = false frustrum_area.set_collision_mask_value(1, false) - frustrum_area.set_collision_mask_value(3, true) + frustrum_area.set_collision_mask_value(2, true) rect_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE rect_panel.add_theme_stylebox_override("panel", rect_style) add_child(rect_panel) @@ -51,6 +56,7 @@ func _process(_delta: float) -> void: _handle_frustrum_shape() _handle_selection_box() _handle_unit_selection() + _handle_advance_anim_step() func _input(event: InputEvent) -> void: @@ -70,6 +76,18 @@ func _input(event: InputEvent) -> void: selection_rect.size = mouse_pos - selection_rect.position +func _handle_advance_anim_step() -> void: + var remapped_unclamped := remap( + visible_units.size(), + MIN_VISIBLE_UNITS, + MAX_VISIBLE_UNITS, + 0, + 1, + ) + var clamped := clampf(remapped_unclamped, 0, 1) + advance_anim_step = roundi(lerpf(1, ANIM_MAX_STEP, clamped)) + + func _handle_frustrum_shape() -> void: var viewport_size := get_viewport().get_visible_rect().size @@ -110,27 +128,30 @@ func _handle_unit_selection() -> void: func _set_selection_state(hover: bool) -> void: var rect_abs := selection_rect.abs() - for unit: ControlledUnit in visible_units.values(): + for unit: Unit in visible_units.values(): + if unit is not ControlledUnit: + continue + var controlled_unit := unit as ControlledUnit var point := camera.unproject_position( unit.global_position + (Vector3.UP * UNIT_SELECT_OFFSET) ) if hover: - unit.set_hovered_rect(rect_abs.has_point(point)) + controlled_unit.set_hovered_rect(rect_abs.has_point(point)) else: - unit.set_selected(rect_abs.has_point(point)) - unit.set_hovered_rect(false) + controlled_unit.set_selected(rect_abs.has_point(point)) + controlled_unit.set_hovered_rect(false) func _on_frustrum_area_body_entered(unit: Node3D) -> void: - if unit is not ControlledUnit: + if unit is not Unit: return var unit_id := unit.get_instance_id() if visible_units.keys().has(unit_id): return - visible_units[unit_id] = unit as ControlledUnit + visible_units[unit_id] = unit as Unit func _on_frustrum_area_body_exited(unit: Node3D) -> void: diff --git a/scripts/main_camera.gd b/scripts/main_camera.gd index 2b0b10d..ac8c43a 100644 --- a/scripts/main_camera.gd +++ b/scripts/main_camera.gd @@ -15,6 +15,8 @@ const EDGE_THRESHOLD: float = 10 const HEADING_SPEED: float = 0.75 const BOUNDARY: float = 150 / 2 +const ANIM_MAX_STEP = 10 + @export var zoom_in_distance: float = 5 @export var zoom_in_fov: float = 25 @export var zoom_in_angle: float = -0.1 * PI @@ -38,6 +40,7 @@ var mouse_position: Vector2 = Vector2() ## 0 = zoomed in. 1 = zoomed out. var zoom_value: float = ZOOM_VALUE_DEFAULT var zoom_raw: float = zoom_value +var advance_anim_step: int = 1 var heading_to_position: Vector3 = Vector3.ZERO var heading_to_zoom: float = 0 @@ -60,21 +63,22 @@ func _ready() -> void: func _process(delta: float) -> void: _handle_heading_to(delta) - zoom_value = lerp(zoom_value, zoom_raw, delta * ZOOM_DAMP) + zoom_value = lerpf(zoom_value, zoom_raw, delta * ZOOM_DAMP) _handle_movement(delta) - fov = lerp(zoom_in_fov, zoom_out_fov, zoom_value) - rotation.x = lerp(zoom_in_angle, zoom_out_angle, zoom_value) - var distance: float = lerp(zoom_in_distance, zoom_out_distance, zoom_value) + fov = lerpf(zoom_in_fov, zoom_out_fov, zoom_value) + rotation.x = lerpf(zoom_in_angle, zoom_out_angle, zoom_value) + var distance: float = lerpf(zoom_in_distance, zoom_out_distance, zoom_value) var offset_direction := Vector3.BACK.rotated(Vector3.RIGHT, rotation.x) var offset := offset_direction * distance global_position = target_position + offset _handle_dof() + _handle_advance_anim_step() - DebugDraw.marker(target_position, 0.05) + DebugManager.marker(target_position, 0.05) func _input(event: InputEvent) -> void: @@ -88,7 +92,7 @@ func _input(event: InputEvent) -> void: zoom_raw -= ZOOM_SPEED elif button_event.button_index == MOUSE_BUTTON_WHEEL_DOWN: zoom_raw += ZOOM_SPEED - zoom_raw = clamp(zoom_raw, 0, 1) + zoom_raw = clampf(zoom_raw, 0, 1) if event.is_action_pressed("reset_camera"): head_to(anthill.global_position) @@ -111,23 +115,35 @@ func head_to(to: Vector3, zoom: float = ZOOM_VALUE_DEFAULT) -> void: state = CameraState.HEADING_TO +func _handle_advance_anim_step() -> void: + var remapped_unclamped := remap( + zoom_value, + ZOOM_VALUE_DEFAULT, + 1, + 0, + 1, + ) + var clamped := clampf(remapped_unclamped, 0, 1) + advance_anim_step = roundi(lerpf(1, ANIM_MAX_STEP, clamped)) + + func _handle_dof() -> void: - attrs.dof_blur_far_distance = lerp( + attrs.dof_blur_far_distance = lerpf( zoom_in_dof_far_distance, zoom_out_dof_far_distance, zoom_value, ) - attrs.dof_blur_far_transition = lerp( + attrs.dof_blur_far_transition = lerpf( zoom_in_dof_far_transition, zoom_out_dof_far_transition, zoom_value, ) - attrs.dof_blur_near_distance = lerp( + attrs.dof_blur_near_distance = lerpf( zoom_in_dof_near_distance, zoom_out_dof_near_distance, zoom_value, ) - attrs.dof_blur_near_transition = lerp( + attrs.dof_blur_near_transition = lerpf( zoom_in_dof_near_transition, zoom_out_dof_near_transition, zoom_value, @@ -168,11 +184,11 @@ func _handle_movement(delta: float) -> void: .rotated(Vector3.UP, rotation.y) ) - var speed: float = lerp(zoom_in_speed, zoom_out_speed, zoom_value) + var speed: float = lerpf(zoom_in_speed, zoom_out_speed, zoom_value) var velocity := direction * speed target_position += velocity * delta - target_position.x = clamp(target_position.x, -BOUNDARY, BOUNDARY) - target_position.z = clamp(target_position.z, -BOUNDARY, BOUNDARY) + target_position.x = clampf(target_position.x, -BOUNDARY, BOUNDARY) + target_position.z = clampf(target_position.z, -BOUNDARY, BOUNDARY) func _handle_heading_to(delta: float) -> void: diff --git a/scripts/ui/anthill_info.gd b/scripts/ui/anthill_info.gd index e153204..6521f3e 100644 --- a/scripts/ui/anthill_info.gd +++ b/scripts/ui/anthill_info.gd @@ -6,6 +6,7 @@ var anthill: Anthill @onready var ant_buy_button: BaseButton = $AntBuyButton @onready var add_one_button: BaseButton = $AddOneButton @onready var add_five_button: BaseButton = $AddFiveButton +@onready var add_max_button: BaseButton = $AddMaxButton @onready var counter: HoneydewCounter = $HoneydewCounter @@ -13,11 +14,13 @@ func _ready() -> void: assert(ant_buy_button != null, "ant_buy_button missing!") assert(add_one_button != null, "add_one_button missing!") assert(add_five_button != null, "add_five_button missing!") + assert(add_max_button != null, "add_max_button missing!") assert(counter != null, "counter missing!") super._ready() ant_buy_button.pressed.connect(_on_ant_buy_button_pressed) add_one_button.pressed.connect(_on_add_one_button_pressed) add_five_button.pressed.connect(_on_add_five_button_pressed) + add_max_button.pressed.connect(_on_add_max_button_pressed) func _process(delta: float) -> void: @@ -25,10 +28,12 @@ func _process(delta: float) -> void: if anthill == null or not visible: return counter.update_counter(anthill.honeydew) - add_one_button.disabled = not DebugDraw.enabled - add_one_button.visible = DebugDraw.enabled - add_five_button.disabled = not DebugDraw.enabled - add_five_button.visible = DebugDraw.enabled + add_one_button.disabled = not DebugManager.enabled + add_one_button.visible = DebugManager.enabled + add_five_button.disabled = not DebugManager.enabled + add_five_button.visible = DebugManager.enabled + add_max_button.disabled = not DebugManager.enabled + add_max_button.visible = DebugManager.enabled func open(at: Anthill) -> void: @@ -54,3 +59,7 @@ func _on_add_one_button_pressed() -> void: func _on_add_five_button_pressed() -> void: anthill.deposit_honeydew(5) + + +func _on_add_max_button_pressed() -> void: + anthill.deposit_honeydew(anthill.max_honeydew) diff --git a/scripts/units/components/gathering.gd b/scripts/units/components/gathering.gd index 51a9644..a6d539c 100644 --- a/scripts/units/components/gathering.gd +++ b/scripts/units/components/gathering.gd @@ -51,7 +51,7 @@ func _process(_delta: float) -> void: item.global_position = _get_nth_pile_pos(i) if target != null: - DebugDraw.circle(target.global_position) + DebugManager.circle(target.global_position) func _input(event: InputEvent) -> void: diff --git a/scripts/units/unit.gd b/scripts/units/unit.gd index 3d4e017..08b674c 100644 --- a/scripts/units/unit.gd +++ b/scripts/units/unit.gd @@ -4,8 +4,6 @@ class_name Unit const MOVE_SPEED: float = 3 const TURN_SPEED: float = 10 -const ANIM_FRAME_MAX = 20 - var max_wander_distance: float = 5 var min_wander_interval: float = 0.25 var max_wander_interval: float = 5 @@ -17,7 +15,6 @@ var spawn_pos: Vector3 var locomotion_value: float = 0 var showing_info: bool = false -var advance_anim_on_nth_frame: int = 1 var advance_anim_delta_accum: float = 0 @onready var nav_agent: NavigationAgent3D = $NavigationAgent3D @@ -104,10 +101,16 @@ func _animate(delta: float) -> void: animation_tree.set("parameters/locomotion/blend_position", locomotion_value) advance_anim_delta_accum += delta - advance_anim_on_nth_frame = floori( - lerp(1, ANIM_FRAME_MAX, main_camera.zoom_value) as float + + var advance_anim_step := maxi( + main_camera.advance_anim_step, + SelectionManager.advance_anim_step ) - if Engine.get_frames_drawn() % advance_anim_on_nth_frame == 0: + var frame := Engine.get_frames_drawn() + var ass: MeshInstance3D = $MeshInstance3D + var advance := (frame + get_instance_id()) % advance_anim_step == 0 + ass.visible = advance and DebugManager.enabled + if advance: animation_tree.advance(advance_anim_delta_accum) advance_anim_delta_accum = 0