v0.2.2
This commit is contained in:
parent
4334f4a4b0
commit
b306abb739
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,44 @@
|
||||||
|
'''
|
||||||
|
此类为工具体积类,主要为检测玩家是否进入了检测体积。
|
||||||
|
'''
|
||||||
|
class_name PlayerTriggerVolumn
|
||||||
|
extends Area2D
|
||||||
|
|
||||||
|
@export var debug_print: bool = false
|
||||||
|
|
||||||
|
signal player_entered(body:CharacterBody2D)
|
||||||
|
signal player_exit(body:CharacterBody2D)
|
||||||
|
|
||||||
|
var _cached_player : Player
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
self.body_entered.connect(_on_body_enter)
|
||||||
|
self.body_exited.connect(_on_body_exit)
|
||||||
|
|
||||||
|
func _on_body_enter(body:Node2D) -> void:
|
||||||
|
if not body.is_in_group("PLAYER"):
|
||||||
|
return
|
||||||
|
|
||||||
|
var p = body as Player
|
||||||
|
if not p: return
|
||||||
|
|
||||||
|
if debug_print:
|
||||||
|
print("[TiggerVolumn]: Player Entered")
|
||||||
|
|
||||||
|
_cached_player = p
|
||||||
|
player_entered.emit(p)
|
||||||
|
|
||||||
|
func _on_body_exit(body:Node2D) -> void:
|
||||||
|
if not _cached_player: return
|
||||||
|
|
||||||
|
if not body.is_in_group("PLAYER"):
|
||||||
|
return
|
||||||
|
|
||||||
|
var p = body as Player
|
||||||
|
if not p: return
|
||||||
|
|
||||||
|
if debug_print:
|
||||||
|
print("[TiggerVolumn]: Player Exited")
|
||||||
|
|
||||||
|
_cached_player = null
|
||||||
|
player_exit.emit(p)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://c25ea2nypjah7
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bonrls3iuhdqb"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://c25ea2nypjah7" path="res://_props/tools/player_trigger_volumn.gd" id="1_qrafk"]
|
||||||
|
|
||||||
|
[node name="PlayerTriggerVolumn" type="Area2D"]
|
||||||
|
editor_description = "此类在检测到玩家时会发出signal,可以与其他的需要检测玩家的scene组合使用。
|
||||||
|
"
|
||||||
|
collision_layer = 0
|
||||||
|
collision_mask = 2
|
||||||
|
script = ExtResource("1_qrafk")
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
class_name Rock
|
||||||
|
extends CharacterBody2D
|
||||||
|
|
||||||
|
## ===== 配置 =====
|
||||||
|
@export var falling_gravity: float = 2000.0
|
||||||
|
@export var max_fall_speed: float = 3000.0
|
||||||
|
@export var kill_y: float = 10000000.0
|
||||||
|
|
||||||
|
@export var shake_x := 2.0
|
||||||
|
@export var shake_y := 2.0
|
||||||
|
@export var step_time := 0.034
|
||||||
|
|
||||||
|
@export var binded_rock_texture: Node2D
|
||||||
|
|
||||||
|
## ===== 常量 =====
|
||||||
|
const NO_TARGET_Y: float = 1e20
|
||||||
|
|
||||||
|
## ===== 状态 =====
|
||||||
|
var is_falling: bool = false
|
||||||
|
var fall_target_y: float = NO_TARGET_Y
|
||||||
|
|
||||||
|
## ===== 抖动量 =====
|
||||||
|
var _shake_tween: Tween
|
||||||
|
var _shake_origin_pos: Vector2
|
||||||
|
|
||||||
|
##岩石开始抖动
|
||||||
|
func start_shaking() -> void:
|
||||||
|
var sprite := $Sprite2D
|
||||||
|
|
||||||
|
if binded_rock_texture: sprite = binded_rock_texture
|
||||||
|
if not sprite:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 防止重复启动
|
||||||
|
if _shake_tween and _shake_tween.is_running():
|
||||||
|
return
|
||||||
|
|
||||||
|
_shake_origin_pos = sprite.position
|
||||||
|
|
||||||
|
_shake_tween = create_tween()
|
||||||
|
_shake_tween.set_loops() # 无限循环
|
||||||
|
_shake_tween.set_trans(Tween.TRANS_SINE)
|
||||||
|
_shake_tween.set_ease(Tween.EASE_IN_OUT)
|
||||||
|
|
||||||
|
# 左上 → 右下 → 左下 → 右上(循环更自然)
|
||||||
|
_shake_tween.tween_property(
|
||||||
|
sprite,
|
||||||
|
"position",
|
||||||
|
_shake_origin_pos + Vector2(-shake_x, -shake_y),
|
||||||
|
step_time
|
||||||
|
)
|
||||||
|
_shake_tween.tween_property(
|
||||||
|
sprite,
|
||||||
|
"position",
|
||||||
|
_shake_origin_pos + Vector2(shake_x, shake_y),
|
||||||
|
step_time
|
||||||
|
)
|
||||||
|
_shake_tween.tween_property(
|
||||||
|
sprite,
|
||||||
|
"position",
|
||||||
|
_shake_origin_pos + Vector2(-shake_x, shake_y),
|
||||||
|
step_time
|
||||||
|
)
|
||||||
|
_shake_tween.tween_property(
|
||||||
|
sprite,
|
||||||
|
"position",
|
||||||
|
_shake_origin_pos + Vector2(shake_x, -shake_y),
|
||||||
|
step_time
|
||||||
|
)
|
||||||
|
|
||||||
|
##岩石结束抖动
|
||||||
|
func stop_shaking() -> void:
|
||||||
|
var sprite := $Sprite2D
|
||||||
|
if not sprite:
|
||||||
|
return
|
||||||
|
|
||||||
|
if _shake_tween:
|
||||||
|
_shake_tween.kill()
|
||||||
|
_shake_tween = null
|
||||||
|
|
||||||
|
# 强制回到原位,防止残留偏移
|
||||||
|
sprite.position = _shake_origin_pos
|
||||||
|
|
||||||
|
## 开始下落(可指定目标)
|
||||||
|
func start_falling(target_y: float = NO_TARGET_Y) -> void:
|
||||||
|
is_falling = true
|
||||||
|
fall_target_y = target_y
|
||||||
|
velocity = Vector2.ZERO
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
|
if not is_falling:
|
||||||
|
return
|
||||||
|
|
||||||
|
_update_fall(delta)
|
||||||
|
|
||||||
|
|
||||||
|
func _update_fall(delta: float) -> void:
|
||||||
|
## 速度积分
|
||||||
|
velocity.y += falling_gravity * delta
|
||||||
|
velocity.y = min(velocity.y, max_fall_speed)
|
||||||
|
|
||||||
|
## 预测下一帧位置
|
||||||
|
var next_y: float = global_position.y + velocity.y * delta
|
||||||
|
|
||||||
|
## 到达目标 / kill
|
||||||
|
var limit_y: float = min(fall_target_y, kill_y)
|
||||||
|
if next_y >= limit_y:
|
||||||
|
global_position.y = limit_y
|
||||||
|
_on_fall_finished()
|
||||||
|
return
|
||||||
|
|
||||||
|
move_and_slide()
|
||||||
|
|
||||||
|
func _on_fall_finished() -> void:
|
||||||
|
is_falling = false
|
||||||
|
queue_free() # 或者变成平台 / 播动画
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://hme2aiy2gff7
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="CharacterBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
sync_to_physics = false
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
kill = null
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
sync_to_physics = false
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
kill = null
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
sync_to_physics = false
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
kill = null
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
sync_to_physics = false
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
kill = null
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
sync_to_physics = false
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
kill = null
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cmjwk4gr1nfns"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://hme2aiy2gff7" path="res://_props/tools/rock.gd" id="1_60pcp"]
|
||||||
|
|
||||||
|
[node name="rock" type="AnimatableBody2D"]
|
||||||
|
collision_layer = 4
|
||||||
|
collision_mask = 4
|
||||||
|
sync_to_physics = false
|
||||||
|
script = ExtResource("1_60pcp")
|
||||||
|
falling_gravity = 400.0
|
||||||
|
kill = null
|
||||||
|
max_fall_speed = 600.0
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
@export var binded_rock: Rock
|
||||||
|
@export var binded_volumn: PlayerTriggerVolumn
|
||||||
|
|
||||||
|
var _rock : Rock
|
||||||
|
var _volumn : PlayerTriggerVolumn
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
_rock = binded_rock if binded_rock != null else _find_first_rock(self)
|
||||||
|
_volumn = binded_volumn if binded_volumn != null else _find_first_volumn(self)
|
||||||
|
|
||||||
|
if not _volumn or not _rock: return
|
||||||
|
|
||||||
|
_volumn.player_entered.connect(_on_rock_start_shake,CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
func _on_rock_start_shake(player: Player) -> void:
|
||||||
|
if not _rock: return
|
||||||
|
|
||||||
|
_rock.start_shaking()
|
||||||
|
$Timer.start()
|
||||||
|
$Timer.timeout.connect(_on_rock_falling)
|
||||||
|
|
||||||
|
func _on_rock_falling() -> void:
|
||||||
|
_rock.stop_shaking()
|
||||||
|
_rock.start_falling()
|
||||||
|
|
||||||
|
|
||||||
|
## ================================
|
||||||
|
## 查找工具函数(强类型)
|
||||||
|
## ================================
|
||||||
|
|
||||||
|
func _find_first_rock(root: Node) -> Rock:
|
||||||
|
var found: Node = _find_first_child_matching(root, func(n: Node) -> bool: return n is Rock)
|
||||||
|
return found as Rock
|
||||||
|
|
||||||
|
|
||||||
|
func _find_first_volumn(root: Node) -> PlayerTriggerVolumn:
|
||||||
|
var found: Node = _find_first_child_matching(root, func(n: Node) -> bool: return n is PlayerTriggerVolumn)
|
||||||
|
return found as PlayerTriggerVolumn
|
||||||
|
|
||||||
|
|
||||||
|
func _find_first_child_matching(root: Node, predicate: Callable) -> Node:
|
||||||
|
for child: Node in root.get_children():
|
||||||
|
# predicate.call() 返回值在类型系统里可能是 Variant,所以别用 := 推断
|
||||||
|
var ok: bool = bool(predicate.call(child))
|
||||||
|
if ok:
|
||||||
|
return child
|
||||||
|
|
||||||
|
var deeper: Node = _find_first_child_matching(child, predicate)
|
||||||
|
if deeper != null:
|
||||||
|
return deeper
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
uid://b8yl6l3tlam86
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
[gd_scene load_steps=7 format=3 uid="uid://knrcnoedxvm6"]
|
||||||
|
|
||||||
|
[ext_resource type="PackedScene" uid="uid://bonrls3iuhdqb" path="res://_props/tools/player_trigger_volumn.tscn" id="1_mvp6g"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://cmjwk4gr1nfns" path="res://_props/tools/rock.tscn" id="1_nh18e"]
|
||||||
|
[ext_resource type="Script" uid="uid://b8yl6l3tlam86" path="res://_props/trigger_fall_rock/trigger_fall_rock.gd" id="1_vv0hj"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://c673bap4b12fx" path="res://icon.svg" id="2_xilvp"]
|
||||||
|
|
||||||
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_vv0hj"]
|
||||||
|
size = Vector2(52, 51)
|
||||||
|
|
||||||
|
[sub_resource type="RectangleShape2D" id="RectangleShape2D_mvp6g"]
|
||||||
|
size = Vector2(52, 108.5)
|
||||||
|
|
||||||
|
[node name="TriggerFallRock" type="Node2D"]
|
||||||
|
script = ExtResource("1_vv0hj")
|
||||||
|
|
||||||
|
[node name="rock" parent="." instance=ExtResource("1_nh18e")]
|
||||||
|
position = Vector2(0, -82)
|
||||||
|
falling_gravity = 100.0
|
||||||
|
|
||||||
|
[node name="Sprite2D" type="Sprite2D" parent="rock"]
|
||||||
|
scale = Vector2(0.4, 0.4)
|
||||||
|
texture = ExtResource("2_xilvp")
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="rock"]
|
||||||
|
position = Vector2(0, -0.5)
|
||||||
|
shape = SubResource("RectangleShape2D_vv0hj")
|
||||||
|
debug_color = Color(0.99629647, 0, 0.19810504, 0.41960785)
|
||||||
|
|
||||||
|
[node name="PlayerTriggerVolumn" parent="." instance=ExtResource("1_mvp6g")]
|
||||||
|
debug_print = true
|
||||||
|
|
||||||
|
[node name="CollisionShape2D" type="CollisionShape2D" parent="PlayerTriggerVolumn"]
|
||||||
|
position = Vector2(0, -54)
|
||||||
|
shape = SubResource("RectangleShape2D_mvp6g")
|
||||||
|
|
||||||
|
[node name="Timer" type="Timer" parent="."]
|
||||||
|
wait_time = 0.8
|
||||||
|
one_shot = true
|
||||||
Binary file not shown.
|
|
@ -81,7 +81,6 @@ func enable_movement() -> void:
|
||||||
func _physics_process(delta: float) -> void:
|
func _physics_process(delta: float) -> void:
|
||||||
if !_can_move :
|
if !_can_move :
|
||||||
return #不允许移动,直接停止退出
|
return #不允许移动,直接停止退出
|
||||||
print("Loco 更新中")
|
|
||||||
|
|
||||||
_update_movement(delta) #更新移动输入
|
_update_movement(delta) #更新移动输入
|
||||||
_update_gravity(delta) #更新重力
|
_update_gravity(delta) #更新重力
|
||||||
|
|
|
||||||
21
update.md
21
update.md
|
|
@ -18,7 +18,16 @@ v0.1.3
|
||||||
|
|
||||||
v0.2.1
|
v0.2.1
|
||||||
|
|
||||||
-
|
- 添加了全局的特效管理器,添加了全局的特效层,现在所有的特效在一个单独的Canvas Layer上播放。
|
||||||
|
- 添加了全局的音效管理器
|
||||||
|
|
||||||
|
v0.2.2
|
||||||
|
|
||||||
|
- 添加了基础的TriggerVolumn,可以定向的检测Player的碰撞,然后绑定到对应的组件上触发对应的效果
|
||||||
|
- 添加了落石的基础类,可以实现,开始抖动,结束抖动,移动,结束移动,移动到目标点等一系列操作
|
||||||
|
- 添加了一个落石的基础案例,可以在此案例的基础上对落石功能进行拓展和修改
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 更新计划
|
## 更新计划
|
||||||
|
|
||||||
|
|
@ -53,11 +62,11 @@ V0.2
|
||||||
- [ ] 相机功能
|
- [ ] 相机功能
|
||||||
- [ ] 相机追随
|
- [ ] 相机追随
|
||||||
- [ ] 相机震动
|
- [ ] 相机震动
|
||||||
|
|
||||||
- [ ] 地图功能
|
- [ ] 地图功能
|
||||||
- [ ] 地图美术功能
|
- [ ] 地图美术功能
|
||||||
- [ ] 地图物件功能
|
- [ ] 地图物件功能
|
||||||
|
- [ ] 落石
|
||||||
|
- [ ] 移动跟随平台
|
||||||
- [ ] 玩家死亡和重生的逻辑
|
- [ ] 玩家死亡和重生的逻辑
|
||||||
- [ ] Room功能:一个Level由n个Room组成,Room存在一个Entrance,玩家进入Entrance会让Entrance向上传输消息给Room并让镜头切换到对应的Room
|
- [ ] Room功能:一个Level由n个Room组成,Room存在一个Entrance,玩家进入Entrance会让Entrance向上传输消息给Room并让镜头切换到对应的Room
|
||||||
- [ ] entrance的对应不同的复活点,从不同的entrance进入会让玩家死亡后在不同的复活点复活
|
- [ ] entrance的对应不同的复活点,从不同的entrance进入会让玩家死亡后在不同的复活点复活
|
||||||
|
|
@ -71,11 +80,11 @@ V0.3
|
||||||
|
|
||||||
- [x] VFX Manager
|
- [x] VFX Manager
|
||||||
- [x] 可以實現在場景中根據預設播放VFX
|
- [x] 可以實現在場景中根據預設播放VFX
|
||||||
- [ ] 將所有的VFX放置在一個插件專屬的Layer
|
- [x] 將所有的VFX放置在一個插件專屬的Layer
|
||||||
|
|
||||||
- [ ] SFX Manager
|
- [x] SFX Manager
|
||||||
- [ ] 可以實現在場景中根據預設播放SFX
|
- [ ] 可以實現在場景中根據預設播放SFX
|
||||||
- [ ] 可以播放一個隨機的SFX Asset
|
- [x] 可以播放一個隨機的SFX Asset
|
||||||
- [ ] 不同的SFX預設
|
- [ ] 不同的SFX預設
|
||||||
|
|
||||||
- [ ] CameraShake Manager
|
- [ ] CameraShake Manager
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue