Compare commits

..

2 Commits

11 changed files with 192 additions and 121 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@ -0,0 +1,40 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cw1lcd672mq87"
path="res://.godot/imported/未命名作品(3).png-5152e47ab8192492e0d911592bc8c8f5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://_asset/ksw/未命名作品(3).png"
dest_files=["res://.godot/imported/未命名作品(3).png-5152e47ab8192492e0d911592bc8c8f5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
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=true
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=1

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=18 format=3 uid="uid://3vc8ojbiyy5w"] [gd_scene load_steps=15 format=3 uid="uid://3vc8ojbiyy5w"]
[ext_resource type="Script" uid="uid://crgac4manhoud" path="res://_game/game.gd" id="1_yksyv"] [ext_resource type="Script" uid="uid://crgac4manhoud" path="res://_game/game.gd" id="1_yksyv"]
[ext_resource type="PackedScene" uid="uid://cvqehvdjpoar4" path="res://_player/player_controller.tscn" id="2_x2i0j"] [ext_resource type="PackedScene" uid="uid://cvqehvdjpoar4" path="res://_player/player_controller.tscn" id="2_x2i0j"]
@ -14,26 +14,6 @@
[ext_resource type="PackedScene" uid="uid://2d457ndb7toe" path="res://_scene/level1/l1_s8.tscn" id="11_ktxjv"] [ext_resource type="PackedScene" uid="uid://2d457ndb7toe" path="res://_scene/level1/l1_s8.tscn" id="11_ktxjv"]
[ext_resource type="PackedScene" uid="uid://dcoq4q3brnkw6" path="res://_scene/level1/l1_s9.tscn" id="12_enubi"] [ext_resource type="PackedScene" uid="uid://dcoq4q3brnkw6" path="res://_scene/level1/l1_s9.tscn" id="12_enubi"]
[ext_resource type="PackedScene" uid="uid://dsw3o2bhc8bve" path="res://_scene/level1/l1_s10.tscn" id="13_53pmm"] [ext_resource type="PackedScene" uid="uid://dsw3o2bhc8bve" path="res://_scene/level1/l1_s10.tscn" id="13_53pmm"]
[ext_resource type="Script" uid="uid://c5in610cunjn2" path="res://_game/water_warp_controller.gd" id="15_jibn5"]
[ext_resource type="Shader" uid="uid://ccpo4346to8ka" path="res://_shader/ripple2.gdshader" id="16_ef7py"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_5vsgs"]
shader = ExtResource("16_ef7py")
shader_parameter/debug_show = false
shader_parameter/obj_uv = Vector2(0.5, 0.5)
shader_parameter/obj_dir = Vector2(1, 0)
shader_parameter/obj_speed = 1.0
shader_parameter/lane_half_width = 0.085
shader_parameter/edge_width = 0.04
shader_parameter/trail_length = 0.55
shader_parameter/push_strength = 0.075
shader_parameter/drag_strength = 0.045
shader_parameter/suck_strength = 0.03
shader_parameter/curl_strength = 0.07
shader_parameter/foam_strength = 0.45
shader_parameter/noise_scale = 3.5
shader_parameter/noise_advect = 0.5
shader_parameter/chroma_shift = 0.6
[node name="Game" type="Node2D" groups=["PLAYER_RESPAWN"]] [node name="Game" type="Node2D" groups=["PLAYER_RESPAWN"]]
script = ExtResource("1_yksyv") script = ExtResource("1_yksyv")
@ -63,15 +43,3 @@ script = ExtResource("1_yksyv")
[node name="L1_S9" parent="." instance=ExtResource("12_enubi")] [node name="L1_S9" parent="." instance=ExtResource("12_enubi")]
[node name="L1_S10" parent="." instance=ExtResource("13_53pmm")] [node name="L1_S10" parent="." instance=ExtResource("13_53pmm")]
[node name="WaterWarp" type="CanvasLayer" parent="." node_paths=PackedStringArray("target")]
script = ExtResource("15_jibn5")
target = NodePath("../PlayerController")
[node name="ColorRect" type="ColorRect" parent="WaterWarp"]
material = SubResource("ShaderMaterial_5vsgs")
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2

View File

@ -57,6 +57,12 @@ func _physics_process(delta: float) -> void:
velocity = direction * pull_speed velocity = direction * pull_speed
move_and_slide() move_and_slide()
func get_attraction_force(pos: Vector2) -> Vector2:
# 返回 (direction, strength) 格式
var dir := (global_position - pos).normalized()
var strength := 1500 # 调整这个值控制吸引力转向速度
return dir * strength
##如果玩家进入收集区域,则切换为已收集状态。 ##如果玩家进入收集区域,则切换为已收集状态。
func _on_player_collected(body:CharacterBody2D) -> void: func _on_player_collected(body:CharacterBody2D) -> void:
if body is Player: if body is Player:

View File

@ -17,6 +17,7 @@ radius = 34.0147
collision_layer = 16 collision_layer = 16
collision_mask = 2 collision_mask = 2
script = ExtResource("1_8vsnl") script = ExtResource("1_8vsnl")
pull_speed = null
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
@ -36,7 +37,7 @@ debug_color = Color(0.19215687, 0.6431373, 0, 0)
[node name="HookAttractVolumn" type="Area2D" parent="."] [node name="HookAttractVolumn" type="Area2D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
collision_layer = 16 collision_layer = 32
collision_mask = 0 collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="HookAttractVolumn"] [node name="CollisionShape2D" type="CollisionShape2D" parent="HookAttractVolumn"]

View File

@ -225,12 +225,16 @@ tile_set = ExtResource("24_uiy5k")
[node name="DarkMaterialBall" parent="." instance=ExtResource("30_mu7ca")] [node name="DarkMaterialBall" parent="." instance=ExtResource("30_mu7ca")]
position = Vector2(-164, 1283) position = Vector2(-164, 1283)
pull_speed = 800.0
[node name="DarkMaterialBall2" parent="." instance=ExtResource("30_mu7ca")] [node name="DarkMaterialBall2" parent="." instance=ExtResource("30_mu7ca")]
position = Vector2(116, 1076) position = Vector2(116, 1076)
pull_speed = 800.0
[node name="DarkMaterialBall3" parent="." instance=ExtResource("30_mu7ca")] [node name="DarkMaterialBall3" parent="." instance=ExtResource("30_mu7ca")]
position = Vector2(33, 1188) position = Vector2(33, 1188)
pull_speed = 800.0
[node name="DarkMaterialBall4" parent="." instance=ExtResource("30_mu7ca")] [node name="DarkMaterialBall4" parent="." instance=ExtResource("30_mu7ca")]
position = Vector2(-78, 1192) position = Vector2(-78, 1192)
pull_speed = 800.0

File diff suppressed because one or more lines are too long

View File

@ -1,92 +1,78 @@
[gd_resource type="TileSet" load_steps=7 format=3 uid="uid://cup1q1upvp18h"] [gd_resource type="TileSet" load_steps=5 format=3 uid="uid://cup1q1upvp18h"]
[ext_resource type="Texture2D" uid="uid://7psxuet3jk1p" path="res://_asset/ksw/basicTile.png" id="1_ln1fl"]
[ext_resource type="Texture2D" uid="uid://dd622t4mw5vva" path="res://_asset/ksw/basicTile01.png" id="2_mucy5"] [ext_resource type="Texture2D" uid="uid://dd622t4mw5vva" path="res://_asset/ksw/basicTile01.png" id="2_mucy5"]
[ext_resource type="Texture2D" uid="uid://cwet2kw1mngmf" path="res://_asset/ksw/basicTile02.png" id="3_u6jqb"] [ext_resource type="Texture2D" uid="uid://cwet2kw1mngmf" path="res://_asset/ksw/basicTile02.png" id="3_u6jqb"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_ln1fl"]
texture = ExtResource("1_ln1fl")
texture_region_size = Vector2i(96, 96)
1:1/0 = 0
2:1/0 = 0
2:2/0 = 0
3:2/0 = 0
3:3/0 = 0
3:1/0 = 0
1:2/0 = 0
1:3/0 = 0
2:3/0 = 0
6:1/0 = 0
7:1/0 = 0
8:1/0 = 0
8:2/0 = 0
8:3/0 = 0
7:3/0 = 0
6:3/0 = 0
6:2/0 = 0
7:2/0 = 0
10:1/0 = 0
11:1/0 = 0
12:1/0 = 0
9:5/0 = 0
10:6/0 = 0
11:5/0 = 0
10:5/0 = 0
9:6/0 = 0
11:6/0 = 0
7:5/0 = 0
7:6/0 = 0
6:6/0 = 0
6:5/0 = 0
3:5/0 = 0
3:6/0 = 0
4:6/0 = 0
4:5/0 = 0
1:5/0 = 0
1:6/0 = 0
1:7/0 = 0
1:9/0 = 0
1:10/0 = 0
2:10/0 = 0
2:9/0 = 0
1:8/0 = 0
4:9/0 = 0
4:10/0 = 0
5:10/0 = 0
5:9/0 = 0
5:8/0 = 0
7:8/0 = 0
8:8/0 = 0
8:9/0 = 0
8:10/0 = 0
7:9/0 = 0
6:9/0 = 0
10:9/0 = 0
11:9/0 = 0
11:10/0 = 0
10:10/0 = 0
9:9/0 = 0
9:10/0 = 0
10:8/0 = 0
11:8/0 = 0
8:5/0 = 0
9:4/0 = 0
11:4/0 = 0
7:4/0 = 0
3:4/0 = 0
1:4/0 = 0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_u6jqb"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_u6jqb"]
texture = ExtResource("2_mucy5") texture = ExtResource("2_mucy5")
texture_region_size = Vector2i(96, 96) texture_region_size = Vector2i(96, 96)
3:1/0 = 0
3:2/0 = 0
2:2/0 = 0
5:1/0 = 0
5:2/0 = 0
6:2/0 = 0
8:1/0 = 0
8:2/0 = 0
9:1/0 = 0
11:1/0 = 0
12:1/0 = 0
12:2/0 = 0
12:4/0 = 0
12:5/0 = 0
12:6/0 = 0
10:6/0 = 0
10:5/0 = 0
9:5/0 = 0
9:6/0 = 0
7:5/0 = 0
6:5/0 = 0
6:6/0 = 0
7:6/0 = 0
4:6/0 = 0
4:5/0 = 0
3:5/0 = 0
2:5/0 = 0
2:6/0 = 0
3:6/0 = 0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_wtljp"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_wtljp"]
texture = ExtResource("3_u6jqb") texture = ExtResource("3_u6jqb")
texture_region_size = Vector2i(96, 96) texture_region_size = Vector2i(96, 96)
10:6/0 = 0 10:6/0 = 0
6:1/0 = 0
6:2/0 = 0
6:3/0 = 0
6:4/0 = 0
7:2/0 = 0
7:3/0 = 0
11:1/0 = 0
12:1/0 = 0
12:2/0 = 0
12:3/0 = 0
12:4/0 = 0
11:4/0 = 0
9:6/0 = 0
8:6/0 = 0
5:8/0 = 0
5:9/0 = 0
5:10/0 = 0
6:10/0 = 0
7:10/0 = 0
7:9/0 = 0
7:8/0 = 0
6:8/0 = 0
10:8/0 = 0
11:8/0 = 0
12:8/0 = 0
12:9/0 = 0
12:10/0 = 0
11:10/0 = 0
10:10/0 = 0
10:9/0 = 0
11:9/0 = 0
[resource] [resource]
tile_size = Vector2i(96, 96) tile_size = Vector2i(96, 96)
sources/0 = SubResource("TileSetAtlasSource_ln1fl")
sources/1 = SubResource("TileSetAtlasSource_u6jqb") sources/1 = SubResource("TileSetAtlasSource_u6jqb")
sources/2 = SubResource("TileSetAtlasSource_wtljp") sources/2 = SubResource("TileSetAtlasSource_wtljp")

View File

@ -1,7 +1,10 @@
[gd_scene load_steps=2 format=3 uid="uid://ddwoxlqluxiq5"] [gd_scene load_steps=3 format=3 uid="uid://ddwoxlqluxiq5"]
[ext_resource type="Script" uid="uid://bvxgviq7l64ck" path="res://addons/reedcomponent/grap_hook/garpping_hook_v_2.gd" id="1_jrg4x"] [ext_resource type="Script" uid="uid://bvxgviq7l64ck" path="res://addons/reedcomponent/grap_hook/garpping_hook_v_2.gd" id="1_jrg4x"]
[sub_resource type="CircleShape2D" id="CircleShape2D_jrg4x"]
radius = 5.0990195
[node name="GarppingHookV2" type="Node2D"] [node name="GarppingHookV2" type="Node2D"]
script = ExtResource("1_jrg4x") script = ExtResource("1_jrg4x")
@ -15,3 +18,12 @@ unique_name_in_owner = true
target_position = Vector2(80, 0) target_position = Vector2(80, 0)
collision_mask = 20 collision_mask = 20
collide_with_areas = true collide_with_areas = true
[node name="TipDetector" type="Area2D" parent="."]
position = Vector2(80, 0)
collision_layer = 0
collision_mask = 32
[node name="CollisionShape2D" type="CollisionShape2D" parent="TipDetector"]
shape = SubResource("CircleShape2D_jrg4x")
debug_color = Color(0, 0.6, 0.69803923, 0)

View File

@ -13,6 +13,7 @@ extends Node2D
@onready var line_2d: Line2D = %Line2D @onready var line_2d: Line2D = %Line2D
@onready var ray: RayCast2D = %RayCast2D @onready var ray: RayCast2D = %RayCast2D
@onready var tip_detector: Area2D = $TipDetector
var _tween: Tween var _tween: Tween
@ -57,7 +58,8 @@ func start_stretching(direction: Vector2) -> void:
_cached_cancel = false _cached_cancel = false
_stretching_dir = direction.normalized() _stretching_dir = direction.normalized()
_current_length = 0.0 _current_length = 0.0
_current_velocity = Vector2.ZERO # 重置速度
_dir_id = _get_direction_id(direction,8) _dir_id = _get_direction_id(direction,8)
func end_stretching(force_end: bool = false) -> bool: func end_stretching(force_end: bool = false) -> bool:
@ -68,6 +70,7 @@ func end_stretching(force_end: bool = false) -> bool:
_is_stretching = false _is_stretching = false
_stretching_dir = Vector2.ZERO _stretching_dir = Vector2.ZERO
_current_velocity = Vector2.ZERO # 重置速度
return true return true
func is_stretching() -> bool: func is_stretching() -> bool:
@ -97,16 +100,42 @@ func _process(_delta: float) -> void:
# Core Logic # Core Logic
# ================= # =================
## 钩爪当前速度
var _current_velocity: Vector2 = Vector2.ZERO
## 最大速度上限
@export var max_speed: float = 800.0
func _update_stretching(delta: float) -> void: func _update_stretching(delta: float) -> void:
# 先嘗試推進 # 检测前端点的吸引力 (direction, strength)
var next_length := _current_length + stretching_speed * delta var attract_config := _get_attraction_at(global_position + _current_velocity.normalized() * _current_length)
# 初始速度(沿当前方向持续向前)
if _current_velocity == Vector2.ZERO:
_current_velocity = get_stretching_dir() * stretching_speed
# 应用吸引力作为加速度
if attract_config.strength > 0:
var acceleration : Vector2 = attract_config.dir * attract_config.strength
_current_velocity += acceleration * delta
# 限制最大速度
if _current_velocity.length() > max_speed:
_current_velocity = _current_velocity.normalized() * max_speed
# 基于更新后的速度预测“下一帧累计长度”
var velocity_dir := _current_velocity.normalized()
var velocity_mag := _current_velocity.length()
var next_length := _current_length + velocity_mag * delta
next_length = min(next_length, max_length) next_length = min(next_length, max_length)
# 使用 getter 获取当前方向(允许外部复写) # 预测末端位置:起点 + 方向 * 累计长度
var current_dir := get_stretching_dir() var predicted_pos := global_position + velocity_dir * next_length
# 先用「下一幀長度」做 Ray tip_detector.global_position = predicted_pos
ray.target_position = current_dir * next_length
# RayCast 也应该射到“累计长度”
ray.target_position = velocity_dir * next_length
ray.force_raycast_update() ray.force_raycast_update()
# ===== 命中檢測(最高優先)===== # ===== 命中檢測(最高優先)=====
@ -114,13 +143,12 @@ func _update_stretching(delta: float) -> void:
var collider := ray.get_collider() var collider := ray.get_collider()
if collider is Node2D and collider.is_in_group(GRAPABLE_GROUP): if collider is Node2D and collider.is_in_group(GRAPABLE_GROUP):
var hit_pos := ray.get_collision_point() var hit_pos := ray.get_collision_point()
_current_length = global_position.distance_to(hit_pos) _current_length = global_position.distance_to(hit_pos)
ray.target_position = current_dir * _current_length ray.target_position = velocity_dir * _current_length
_handle_hit(collider as Node2D, hit_pos) _handle_hit(collider as Node2D, hit_pos)
return return
# ===== 命中,才正式推進 ===== # ===== 命中,才正式推進 =====
_current_length = next_length _current_length = next_length
# 取消邏輯 # 取消邏輯
@ -134,9 +162,33 @@ func _update_stretching(delta: float) -> void:
stretching_finished.emit(true, null) stretching_finished.emit(true, null)
end_stretching(true) end_stretching(true)
## 在指定位置检测吸引力,返回 {"dir": Vector2, "strength": float}
func _get_attraction_at(pos: Vector2) -> Dictionary:
var total_force := Vector2.ZERO
# 检测 Areas
for area in tip_detector.get_overlapping_areas():
if area is Node2D and area.has_method("get_attraction_force"):
total_force += area.get_attraction_force(pos)
elif area.owner is Node2D and area.owner.has_method("get_attraction_force"):
total_force += area.owner.get_attraction_force(pos)
# 检测 Bodies
for body in tip_detector.get_overlapping_bodies():
if body is Node2D and body.has_method("get_attraction_force"):
total_force += body.get_attraction_force(pos)
elif body.owner is Node2D and body.owner.has_method("get_attraction_force"):
total_force += body.owner.get_attraction_force(pos)
# 返回 {"dir": direction, "strength": magnitude}
if total_force != Vector2.ZERO:
return {"dir": total_force.normalized(), "strength": total_force.length()}
return {"dir": Vector2.ZERO, "strength": 0.0}
func _handle_hit(target: Node2D, hit_pos: Vector2) -> void: func _handle_hit(target: Node2D, hit_pos: Vector2) -> void:
_is_stretching = false _is_stretching = false
_stretching_dir = Vector2.ZERO _stretching_dir = Vector2.ZERO
_current_velocity = Vector2.ZERO # 重置速度
ray.target_position = to_local(hit_pos) ray.target_position = to_local(hit_pos)
@ -155,6 +207,7 @@ func _release_hook() -> void:
# 1. 停止拉伸(保險) # 1. 停止拉伸(保險)
_is_stretching = false _is_stretching = false
_stretching_dir = Vector2.ZERO _stretching_dir = Vector2.ZERO
_current_velocity = Vector2.ZERO # 重置速度
_cached_cancel = false _cached_cancel = false
_current_length = 0.0 _current_length = 0.0

View File

@ -97,3 +97,4 @@ grap_hook={
2d_physics/layer_3="Environment" 2d_physics/layer_3="Environment"
2d_physics/layer_4="Damage" 2d_physics/layer_4="Damage"
2d_physics/layer_5="Collectable" 2d_physics/layer_5="Collectable"
2d_physics/layer_6="Hook_Attract"