diff --git a/.godot/editor/Enemy.tscn-editstate-e8b868f745946f74f22434b9ddd0af8d.cfg b/.godot/editor/Enemy.tscn-editstate-e8b868f745946f74f22434b9ddd0af8d.cfg new file mode 100644 index 0000000..a3fad28 --- /dev/null +++ b/.godot/editor/Enemy.tscn-editstate-e8b868f745946f74f22434b9ddd0af8d.cfg @@ -0,0 +1,192 @@ +[editor_states] + +2D={ +"grid_offset": Vector2(0, 0), +"grid_snap_active": false, +"grid_step": Vector2(8, 8), +"grid_visibility": 1, +"ofs": Vector2(-184, -129), +"primary_grid_step": Vector2i(8, 8), +"show_group_gizmos": true, +"show_guides": true, +"show_helpers": false, +"show_lock_gizmos": true, +"show_origin": true, +"show_position_gizmos": true, +"show_rulers": true, +"show_transformation_gizmos": true, +"show_viewport": true, +"show_zoom_control": true, +"smart_snap_active": false, +"snap_guides": true, +"snap_node_anchors": true, +"snap_node_center": true, +"snap_node_parent": true, +"snap_node_sides": true, +"snap_other_nodes": true, +"snap_pixel": true, +"snap_relative": false, +"snap_rotation": false, +"snap_rotation_offset": 0.0, +"snap_rotation_step": 0.2617994, +"snap_scale": false, +"snap_scale_step": 0.1, +"zoom": 0.25 +} +3D={ +"fov": 70.01, +"gizmos_status": { +"AudioListener3D": 0, +"AudioStreamPlayer3D": 0, +"CPUParticles3D": 0, +"CSGShape3D": 0, +"Camera3D": 0, +"ChainIK3D": 0, +"CollisionObject3D": 0, +"CollisionPolygon3D": 0, +"CollisionShape3D": 0, +"Decal": 0, +"FogVolume": 0, +"GPUParticles3D": 0, +"GPUParticlesCollision3D": 0, +"Joint3D": 0, +"Light3D": 0, +"LightmapGI": 0, +"LightmapProbe": 0, +"Marker3D": 0, +"MeshInstance3DCustomAABB": 0, +"NavigationLink3D": 0, +"NavigationObstacle3D": 0, +"NavigationRegion3D": 0, +"OccluderInstance3D": 0, +"Particles3DEmissionShape": 0, +"Path3D": 0, +"PhysicalBone3D": 0, +"RayCast3D": 0, +"ReflectionProbe": 0, +"ShapeCast3D": 0, +"Skeleton3D": 0, +"SoftBody3D": 0, +"SpringArm3D": 0, +"SpringBoneCollision3D": 0, +"SpringBoneSimulator3D": 0, +"TwoBoneIK3D": 0, +"VehicleWheel3D": 0, +"VisibleOnScreenNotifier3D": 0, +"VoxelGI": 0 +}, +"local_coords": false, +"preview_sun_env": { +"environ_ao_enabled": false, +"environ_enabled": true, +"environ_energy": 1.0, +"environ_gi_enabled": false, +"environ_glow_enabled": true, +"environ_ground_color": Color(0.2, 0.169, 0.133, 1), +"environ_sky_color": Color(0.385, 0.454, 0.55, 1), +"environ_tonemap_enabled": true, +"sun_color": Color(1, 1, 1, 1), +"sun_enabled": true, +"sun_energy": 1.0, +"sun_rotation": Vector2(-1.0471976, 2.6179938), +"sun_shadow_max_distance": 100.0 +}, +"rotate_snap": 15.0, +"scale_snap": 10.0, +"show_grid": true, +"show_origin": true, +"snap_enabled": false, +"translate_snap": 1.0, +"viewport_mode": 1, +"viewports": [{ +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": true, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}, { +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": false, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}, { +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": false, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}, { +"auto_orthogonal": false, +"auto_orthogonal_enabled": true, +"cinematic_preview": false, +"display_mode": 22, +"distance": 4.0, +"doppler": false, +"frame_time": false, +"gizmos": true, +"grid": true, +"half_res": false, +"information": false, +"listener": false, +"lock_rotation": false, +"orthogonal": false, +"position": Vector3(0, 0, 0), +"transform_gizmo": true, +"use_environment": false, +"view_type": 0, +"x_rotation": 0.5, +"y_rotation": -0.5 +}], +"zfar": 4000.01, +"znear": 0.05 +} +Anim={ +"visible": false +} +selected_nodes=Array[NodePath]([]) diff --git a/.godot/editor/Enemy.tscn-folding-e8b868f745946f74f22434b9ddd0af8d.cfg b/.godot/editor/Enemy.tscn-folding-e8b868f745946f74f22434b9ddd0af8d.cfg index 9a2f877..64bd6f6 100644 --- a/.godot/editor/Enemy.tscn-folding-e8b868f745946f74f22434b9ddd0af8d.cfg +++ b/.godot/editor/Enemy.tscn-folding-e8b868f745946f74f22434b9ddd0af8d.cfg @@ -1,5 +1,5 @@ [folding] node_unfolds=[NodePath("."), PackedStringArray("Collision")] -resource_unfolds=[] +resource_unfolds=["res://scenes/Enemy.tscn::StandardMaterial3D_1", PackedStringArray(), "res://scenes/Enemy.tscn::BoxMesh_1", PackedStringArray(), "res://scenes/Enemy.tscn::BoxShape3D_1", PackedStringArray()] nodes_folded=[] diff --git a/.godot/editor/Main.gd-folding-563a585e691f0cddb6239748e25560b1.cfg b/.godot/editor/Main.gd-folding-563a585e691f0cddb6239748e25560b1.cfg new file mode 100644 index 0000000..e860dd4 --- /dev/null +++ b/.godot/editor/Main.gd-folding-563a585e691f0cddb6239748e25560b1.cfg @@ -0,0 +1,3 @@ +[folding] + +sections_unfolded=PackedStringArray() diff --git a/.godot/editor/Player.gd-folding-8e1f9fed6067558c5d7d6d94032530c3.cfg b/.godot/editor/Player.gd-folding-8e1f9fed6067558c5d7d6d94032530c3.cfg new file mode 100644 index 0000000..e860dd4 --- /dev/null +++ b/.godot/editor/Player.gd-folding-8e1f9fed6067558c5d7d6d94032530c3.cfg @@ -0,0 +1,3 @@ +[folding] + +sections_unfolded=PackedStringArray() diff --git a/.godot/editor/Player.tscn-folding-e8220e74d1354b9e6b168b513689419c.cfg b/.godot/editor/Player.tscn-folding-e8220e74d1354b9e6b168b513689419c.cfg index 9a2f877..91234b3 100644 --- a/.godot/editor/Player.tscn-folding-e8220e74d1354b9e6b168b513689419c.cfg +++ b/.godot/editor/Player.tscn-folding-e8220e74d1354b9e6b168b513689419c.cfg @@ -1,5 +1,5 @@ [folding] node_unfolds=[NodePath("."), PackedStringArray("Collision")] -resource_unfolds=[] +resource_unfolds=["res://scenes/Player.tscn::StandardMaterial3D_1", PackedStringArray(), "res://scenes/Player.tscn::CapsuleMesh_1", PackedStringArray(), "res://scenes/Player.tscn::CapsuleShape3D_1", PackedStringArray()] nodes_folded=[] diff --git a/.godot/editor/editor_layout.cfg b/.godot/editor/editor_layout.cfg index 66dff6e..c9e54a8 100644 --- a/.godot/editor/editor_layout.cfg +++ b/.godot/editor/editor_layout.cfg @@ -8,8 +8,8 @@ dock_closed=[] dock_split_2=0 dock_split_3=0 dock_hsplit_1=0 -dock_hsplit_2=280 -dock_hsplit_3=-280 +dock_hsplit_2=0 +dock_hsplit_3=0 dock_hsplit_4=0 dock_9_selected_tab_idx=0 dock_3="Scene,Import" @@ -24,7 +24,7 @@ v_split_offset=0 display_mode=0 file_sort=0 file_list_display_mode=1 -selected_paths=PackedStringArray("res://scenes/Player.tscn") +selected_paths=PackedStringArray("res://scripts/Main.gd") uncollapsed_paths=PackedStringArray("Favorites", "res://", "res://scripts/", "res://scenes/") [docks/History] @@ -34,8 +34,8 @@ include_global=true [EditorNode] -open_scenes=PackedStringArray("res://scenes/Player.tscn") -current_scene="res://scenes/Player.tscn" +open_scenes=PackedStringArray("res://scenes/Main.tscn", "res://scenes/Enemy.tscn", "res://scenes/Player.tscn") +current_scene="res://scenes/Enemy.tscn" bottom_panel_offsets={ "Audio": -450, "Debugger": 0, @@ -53,11 +53,14 @@ position=Vector2i(0, 60) [ScriptEditor] open_scripts=["res://scripts/Enemy.gd", "res://scripts/Main.gd", "res://scripts/Player.gd"] -selected_script="res://scripts/Enemy.gd" +selected_script="res://scripts/Player.gd" open_help=[] script_split_offset=400 list_split_offset=0 zoom_factor=1.0 +window_rect=Rect2i(0, 0, 2880, 1800) +window_screen=0 +window_screen_rect=Rect2i(0, 60, 2880, 1740) [GameView] diff --git a/.godot/editor/filesystem_update4 b/.godot/editor/filesystem_update4 index ec092b6..b6255d4 100644 --- a/.godot/editor/filesystem_update4 +++ b/.godot/editor/filesystem_update4 @@ -1,3 +1,5 @@ res://scripts/Enemy.gd res://scripts/Main.gd res://scripts/Player.gd +res://scenes/Player.tscn +res://scenes/Enemy.tscn diff --git a/.godot/editor/project_metadata.cfg b/.godot/editor/project_metadata.cfg new file mode 100644 index 0000000..54d8d98 --- /dev/null +++ b/.godot/editor/project_metadata.cfg @@ -0,0 +1,17 @@ +[game_view] + +select_mode=0 +embed_size_mode=1 + +[editor_metadata] + +executable_path="/Applications/Godot.app/Contents/MacOS/Godot" + +[recent_files] + +scenes=["res://scenes/Player.tscn", "res://scenes/Enemy.tscn", "res://scenes/Main.tscn"] +scripts=["Timer", "Node", "SceneTree", "Node3D", "res://scripts/Player.gd", "res://scripts/Enemy.gd", "res://scripts/Main.gd"] + +[dialog_bounds] + +project_settings=Rect2(288, 200, 2304, 1400) diff --git a/.godot/editor/script_editor_cache.cfg b/.godot/editor/script_editor_cache.cfg index 6a96df5..a2337ed 100644 --- a/.godot/editor/script_editor_cache.cfg +++ b/.godot/editor/script_editor_cache.cfg @@ -3,11 +3,11 @@ state={ "bookmarks": PackedInt32Array(), "breakpoints": PackedInt32Array(), -"column": 0, +"column": 28, "folded_lines": PackedInt32Array(), "h_scroll_position": 0, -"row": 294, -"scroll_position": 392.0, +"row": 211, +"scroll_position": 193.0, "selection": false, "syntax_highlighter": "GDScript" } @@ -17,12 +17,16 @@ state={ state={ "bookmarks": PackedInt32Array(), "breakpoints": PackedInt32Array(), -"column": 15, +"column": 14, "folded_lines": PackedInt32Array(), "h_scroll_position": 0, -"row": 192, -"scroll_position": 184.0, -"selection": false, +"row": 17, +"scroll_position": 0.0, +"selection": true, +"selection_from_column": 9, +"selection_from_line": 17, +"selection_to_column": 14, +"selection_to_line": 17, "syntax_highlighter": "GDScript" } @@ -31,11 +35,11 @@ state={ state={ "bookmarks": PackedInt32Array(), "breakpoints": PackedInt32Array(), -"column": 17, +"column": 33, "folded_lines": PackedInt32Array(), "h_scroll_position": 0, -"row": 117, -"scroll_position": 156.0, +"row": 9, +"scroll_position": 1.5287992, "selection": false, "syntax_highlighter": "GDScript" } diff --git a/.godot/shader_cache/SceneForwardClusteredShaderRD/1d8f9fd61c770da8fbf2a971b3e81a1e4b82130a464dd2919dd0df65d3f4d4a6/321e42e1280eb440cb08d0ceb1689cb32a542119.metal.cache b/.godot/shader_cache/SceneForwardClusteredShaderRD/1d8f9fd61c770da8fbf2a971b3e81a1e4b82130a464dd2919dd0df65d3f4d4a6/321e42e1280eb440cb08d0ceb1689cb32a542119.metal.cache new file mode 100644 index 0000000..70c8d9f Binary files /dev/null and b/.godot/shader_cache/SceneForwardClusteredShaderRD/1d8f9fd61c770da8fbf2a971b3e81a1e4b82130a464dd2919dd0df65d3f4d4a6/321e42e1280eb440cb08d0ceb1689cb32a542119.metal.cache differ diff --git a/scenes/Enemy.tscn b/scenes/Enemy.tscn index d44ec51..5c9beb7 100644 --- a/scenes/Enemy.tscn +++ b/scenes/Enemy.tscn @@ -1,6 +1,25 @@ -[gd_scene load_steps=2 format=3 uid="uid://cxk2mn5oab341"] +[gd_scene format=3 uid="uid://cxk2mn5oab341"] -[ext_resource type="Script" path="res://scripts/Enemy.gd" id="1_enemy"] +[ext_resource type="Script" uid="uid://ujlvt8u71hg1" path="res://scripts/Enemy.gd" id="1_enemy"] -[node name="Enemy" type="CharacterBody3D"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"] +albedo_color = Color(1, 0.28, 0.18, 1) +roughness = 0.8 + +[sub_resource type="BoxMesh" id="BoxMesh_1"] +size = Vector3(0.85, 0.85, 0.85) + +[sub_resource type="BoxShape3D" id="BoxShape3D_1"] +size = Vector3(0.85, 0.85, 0.85) + +[node name="Enemy" type="CharacterBody3D" unique_id=1639801124] script = ExtResource("1_enemy") + +[node name="BodyMesh" type="MeshInstance3D" parent="." unique_id=68242945] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.425, 0) +material_override = SubResource("StandardMaterial3D_1") +mesh = SubResource("BoxMesh_1") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=379819225] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.425, 0) +shape = SubResource("BoxShape3D_1") diff --git a/scenes/Player.tscn b/scenes/Player.tscn index 38c5b6d..f745634 100644 --- a/scenes/Player.tscn +++ b/scenes/Player.tscn @@ -1,6 +1,30 @@ -[gd_scene load_steps=2 format=3 uid="uid://bpq8lf4mcvhw5"] +[gd_scene load_steps=5 format=3 uid="uid://bpq8lf4mcvhw5"] [ext_resource type="Script" path="res://scripts/Player.gd" id="1_player"] +[sub_resource type="CapsuleMesh" id="CapsuleMesh_1"] +radius = 0.4 +height = 1.0 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_1"] +albedo_color = Color(0.2, 0.55, 1, 1) +metallic = 0.2 +roughness = 0.6 + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1"] +radius = 0.4 +height = 1.0 + [node name="Player" type="CharacterBody3D"] script = ExtResource("1_player") + +[node name="BodyMesh" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +mesh = SubResource("CapsuleMesh_1") +material_override = SubResource("StandardMaterial3D_1") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +shape = SubResource("CapsuleShape3D_1") + +[node name="KickIndicator" type="MeshInstance3D" parent="."] diff --git a/scripts/Enemy.gd b/scripts/Enemy.gd index 0bdcfd9..1129fa5 100644 --- a/scripts/Enemy.gd +++ b/scripts/Enemy.gd @@ -19,30 +19,32 @@ var stun_timer: float = 0.0 var contact_timer: float = 0.0 var target: Node3D = null -var mesh_node: MeshInstance3D +@onready var mesh_node: MeshInstance3D = $BodyMesh var mat: StandardMaterial3D -var COLOR_CHASE = Color(1.0, 0.28, 0.18) -var COLOR_FLY = Color(1.0, 0.85, 0.1) -var COLOR_STUN = Color(0.55, 0.55, 0.65) +var COLOR_CHASE = Color(1.0, 0.28, 0.18) +var COLOR_FLY = Color(1.0, 0.85, 0.1) +var COLOR_STUN = Color(0.55, 0.55, 0.65) + const CONTACT_CD = 0.7 const AIR_FRICTION = 0.86 func _ready() -> void: add_to_group("enemies") - _build_mesh() - _build_collider() + mat = mesh_node.material_override.duplicate() as StandardMaterial3D + mesh_node.material_override = mat + COLOR_CHASE = mat.albedo_color func setup(type: String, wave: int) -> void: match type: "slime": move_speed = 2.8 + wave * 0.12 - health = 28 + wave * 4 + health = 28 + wave * 4 score_value = 10 damage_to_player = 8 "bat": move_speed = 5.5 + wave * 0.15 - health = 14 + wave * 2 + health = 14 + wave * 2 score_value = 15 damage_to_player = 6 base_scale = 0.7 @@ -51,7 +53,7 @@ func setup(type: String, wave: int) -> void: mat.albedo_color = COLOR_CHASE "ogre": move_speed = 1.8 + wave * 0.08 - health = 80 + wave * 12 + health = 80 + wave * 12 score_value = 25 damage_to_player = 18 base_scale = 1.5 @@ -59,26 +61,6 @@ func setup(type: String, wave: int) -> void: COLOR_CHASE = Color(0.3, 0.7, 0.3) mat.albedo_color = COLOR_CHASE -func _build_mesh() -> void: - mesh_node = MeshInstance3D.new() - var box := BoxMesh.new() - box.size = Vector3(0.85, 0.85, 0.85) - mesh_node.mesh = box - mesh_node.position.y = 0.425 - mat = StandardMaterial3D.new() - mat.albedo_color = COLOR_CHASE - mat.roughness = 0.8 - mesh_node.material_override = mat - add_child(mesh_node) - -func _build_collider() -> void: - var col := CollisionShape3D.new() - var shape := BoxShape3D.new() - shape.size = Vector3(0.85, 0.85, 0.85) - col.shape = shape - col.position.y = 0.425 - add_child(col) - func _physics_process(delta: float) -> void: match state: State.CHASING: _chase(delta) @@ -90,16 +72,13 @@ func _chase(delta: float) -> void: if not is_instance_valid(target): return contact_timer = max(0.0, contact_timer - delta) - var diff := target.global_position - global_position diff.y = 0.0 var dist := diff.length() - if dist < 1.0 and contact_timer <= 0.0: contact_timer = CONTACT_CD if target.has_method("take_damage"): target.take_damage(damage_to_player) - if dist > 0.05: var dir := diff.normalized() velocity.x = dir.x * move_speed @@ -120,10 +99,8 @@ func _fly(delta: float) -> void: var col3d := col.get_collider() as Node3D if col3d == null: continue - if col3d.has_meta("is_wall"): - var dmg := int(speed_now * wall_damage_mult) - _take_hit(dmg) + _take_hit(int(speed_now * wall_damage_mult)) _wall_impact_effect() fly_vel = Vector3.ZERO velocity = Vector3.ZERO @@ -145,7 +122,6 @@ func _fly(delta: float) -> void: if Vector2(fly_vel.x, fly_vel.z).length() < 0.4: _enter_chase() - # Spin while airborne mesh_node.rotation.y += delta * 10.0 func _stun_tick(delta: float) -> void: diff --git a/scripts/Main.gd b/scripts/Main.gd index c9d0abc..2a6e731 100644 --- a/scripts/Main.gd +++ b/scripts/Main.gd @@ -209,7 +209,7 @@ func _on_spawn_timer() -> void: if not game_active or upgrading: return _spawn_enemy() - spawn_timer.wait_time = max(0.25, 1.4 - wave * 0.07) + spawn_timer.wait_time = 10 # max(0.25, 1.4 - wave * 0.07) func _spawn_enemy() -> void: var enemy := ENEMY_SCENE.instantiate() as CharacterBody3D diff --git a/scripts/Player.gd b/scripts/Player.gd index 9de3a49..c4e2ab4 100644 --- a/scripts/Player.gd +++ b/scripts/Player.gd @@ -5,9 +5,9 @@ signal health_changed(current: int, maximum: int) @export var move_speed: float = 7.0 @export var kick_range: float = 3.5 -@export var kick_force: float = 22.0 +@export var kick_force: float = 60.0 @export var kick_cooldown: float = 0.6 -@export var kick_angle: float = 120.0 +@export var kick_angle: float = 60.0 @export var max_health: int = 100 var health: int = max_health @@ -16,9 +16,10 @@ var invincible_timer: float = 0.0 var is_alive: bool = true var last_move_dir: Vector3 = Vector3.FORWARD -var mesh_node: MeshInstance3D +@onready var mesh_node: MeshInstance3D = $BodyMesh +@onready var indicator_node: MeshInstance3D = $KickIndicator + var player_mat: StandardMaterial3D -var indicator_node: MeshInstance3D var indicator_mat: StandardMaterial3D const IFRAMES_DURATION := 0.6 @@ -26,27 +27,13 @@ const BASE_COLOR := Color(0.2, 0.55, 1.0) func _ready() -> void: add_to_group("player") - _build_visuals() - _build_collider() - -func _build_visuals() -> void: - mesh_node = MeshInstance3D.new() - var capsule := CapsuleMesh.new() - capsule.radius = 0.4 - capsule.height = 1.0 - mesh_node.mesh = capsule - mesh_node.position.y = 0.5 - player_mat = StandardMaterial3D.new() - player_mat.albedo_color = BASE_COLOR - player_mat.roughness = 0.6 - player_mat.metallic = 0.2 + player_mat = mesh_node.material_override.duplicate() as StandardMaterial3D mesh_node.material_override = player_mat - add_child(mesh_node) + _setup_indicator() - # Kick arc indicator (sector/fan mesh on floor) - indicator_node = MeshInstance3D.new() - indicator_node.mesh = _make_kick_arc_mesh() +func _setup_indicator() -> void: indicator_node.position.y = 0.02 + indicator_node.mesh = _make_kick_arc_mesh() indicator_mat = StandardMaterial3D.new() indicator_mat.albedo_color = Color(1.0, 0.85, 0.1, 0.2) indicator_mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA @@ -54,7 +41,6 @@ func _build_visuals() -> void: indicator_mat.no_depth_test = true indicator_mat.cull_mode = BaseMaterial3D.CULL_DISABLED indicator_node.material_override = indicator_mat - add_child(indicator_node) func _make_kick_arc_mesh() -> ArrayMesh: var verts := PackedVector3Array() @@ -65,39 +51,25 @@ func _make_kick_arc_mesh() -> ArrayMesh: var t: float = float(i) / float(SEGS) var a: float = lerpf(-half_rad, half_rad, t) verts.append(Vector3(sin(a) * kick_range, 0.0, -cos(a) * kick_range)) - var indices := PackedInt32Array() for i in range(SEGS): indices.append(0) indices.append(i + 1) indices.append(i + 2) - var arrays: Array = [] arrays.resize(Mesh.ARRAY_MAX) arrays[Mesh.ARRAY_VERTEX] = verts arrays[Mesh.ARRAY_INDEX] = indices - var mesh := ArrayMesh.new() mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays) return mesh -func _build_collider() -> void: - var col := CollisionShape3D.new() - var shape := CapsuleShape3D.new() - shape.radius = 0.4 - shape.height = 1.0 - col.shape = shape - col.position.y = 0.5 - add_child(col) - func _physics_process(delta: float) -> void: if not is_alive: return - _handle_movement(delta) _handle_kick(delta) _handle_iframes(delta) - if Input.is_action_just_pressed("ui_accept") and kick_timer <= 0.0: _do_kick() @@ -110,24 +82,14 @@ func _handle_movement(delta: float) -> void: float(Input.is_key_pressed(KEY_S) or Input.is_key_pressed(KEY_DOWN)) - float(Input.is_key_pressed(KEY_W) or Input.is_key_pressed(KEY_UP)) ) - - # Camera-relative movement: camera is independent (mouse-controlled), no feedback loop var cam := get_viewport().get_camera_3d() if (abs(input_x) > 0.0 or abs(input_z) > 0.0) and cam != null: var cam_fwd := -cam.global_transform.basis.z cam_fwd.y = 0.0 - if cam_fwd.length() > 0.01: - cam_fwd = cam_fwd.normalized() - else: - cam_fwd = Vector3(0.0, 0.0, -1.0) - + cam_fwd = cam_fwd.normalized() if cam_fwd.length() > 0.01 else Vector3(0.0, 0.0, -1.0) var cam_right := cam.global_transform.basis.x cam_right.y = 0.0 - if cam_right.length() > 0.01: - cam_right = cam_right.normalized() - else: - cam_right = Vector3(1.0, 0.0, 0.0) - + cam_right = cam_right.normalized() if cam_right.length() > 0.01 else Vector3(1.0, 0.0, 0.0) var move := cam_fwd * (-input_z) + cam_right * input_x if move.length() > 0.01: move = move.normalized() @@ -139,7 +101,6 @@ func _handle_movement(delta: float) -> void: else: velocity.x = move_toward(velocity.x, 0.0, move_speed * 12.0 * delta) velocity.z = move_toward(velocity.z, 0.0, move_speed * 12.0 * delta) - velocity.y = 0.0 move_and_slide() @@ -158,16 +119,10 @@ func _handle_iframes(delta: float) -> void: func _do_kick() -> void: kick_timer = kick_cooldown - var forward := -global_transform.basis.z forward.y = 0.0 - if forward.length() > 0.01: - forward = forward.normalized() - else: - forward = Vector3(0, 0, -1) - + forward = forward.normalized() if forward.length() > 0.01 else Vector3(0.0, 0.0, -1.0) var half_cos: float = cos(deg_to_rad(kick_angle * 0.5)) - var enemies := get_tree().get_nodes_in_group("enemies") var kicked_any := false for e in enemies: @@ -181,11 +136,9 @@ func _do_kick() -> void: var dist := diff.length() if dist < 0.1 or dist > kick_range: continue - var dir_to_enemy := diff / dist - if dir_to_enemy.dot(forward) >= half_cos: - en.call("receive_kick", dir_to_enemy, kick_force) + if (diff / dist).dot(forward) >= half_cos: + en.call("receive_kick", diff / dist, kick_force) kicked_any = true - if kicked_any: _squish_effect() @@ -198,15 +151,13 @@ func take_damage(amount: int) -> void: if not is_alive or invincible_timer > 0.0: return invincible_timer = IFRAMES_DURATION - health = max(0, health - amount) - emit_signal("health_changed", health, max_health) - - var tw := create_tween() - tw.tween_property(player_mat, "albedo_color", Color.RED, 0.08) - tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.25) - - if health <= 0: - _die() + #health = max(0, health - amount) + #emit_signal("health_changed", health, max_health) + #var tw := create_tween() + #tw.tween_property(player_mat, "albedo_color", Color.RED, 0.08) + #tw.tween_property(player_mat, "albedo_color", BASE_COLOR, 0.25) + #if health <= 0: + #_die() func _die() -> void: is_alive = false @@ -216,15 +167,12 @@ func _die() -> void: func apply_upgrade(id: String) -> void: match id: - "kick_force": - kick_force += 6.0 + "kick_force": kick_force += 6.0 "kick_range": kick_range += 0.7 indicator_node.mesh = _make_kick_arc_mesh() - "kick_cooldown": - kick_cooldown = max(0.12, kick_cooldown - 0.09) - "move_speed": - move_speed += 1.2 + "kick_cooldown": kick_cooldown = max(0.12, kick_cooldown - 0.09) + "move_speed": move_speed += 1.2 "max_health": max_health += 30 health = min(health + 30, max_health)