first update.

This commit is contained in:
jkboy 2025-05-10 23:19:52 +08:00
parent 3f104c8fa5
commit a78a801157
497 changed files with 14195 additions and 62 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Normalize EOL for all files that Git considers text files.
* text=auto eol=lf

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Godot 4+ specific ignores
.godot/
/android/

View File

@ -0,0 +1,87 @@
extends Node
## 用于控制时间速度和屏幕变暗效果的自动加载单例
const DEFAULT_TIME_SCALE := 1.0
const FADE_DURATION := 0.03 # 渐变效果持续时间
const SLOW_DURATION := 0.05 # 减速效果持续时间(当前未使用,保留)
const MAX_DARKNESS := 0.5 # 最大变暗程度0.0完全透明1.0完全黑)
var _current_time_scale := DEFAULT_TIME_SCALE
var _fade_overlay: ColorRect
var _is_fading := false
var _current_tween: Tween
var _should_maintain_slow := false # 是否保持减速状态
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
_setup_fade_overlay()
func _setup_fade_overlay() -> void:
var canvas_layer := CanvasLayer.new()
canvas_layer.layer = 128
add_child(canvas_layer)
_fade_overlay = ColorRect.new()
_fade_overlay.color = Color(0, 0, 0, 0)
_fade_overlay.set_anchors_preset(Control.PRESET_FULL_RECT)
canvas_layer.add_child(_fade_overlay)
## 主控制函数:同时控制减速和变暗效果
## @param slow_time_scale: 时间缩放值1.0为正常速度小于1.0为减速)
## @param fade: 是否启用变暗效果
func execute_effects(slow_time_scale: float, fade: bool) -> void:
_kill_current_tween()
if slow_time_scale != DEFAULT_TIME_SCALE:
_slow_time(slow_time_scale)
else:
_reset_time()
_fade_to(MAX_DARKNESS if fade else 0.0)
## 立即恢复所有效果到正常状态
func reset_all() -> void:
_kill_current_tween()
_reset_time()
_is_fading = false
_fade_overlay.color.a = 0.0
# region 内部工具函数
func _kill_current_tween() -> void:
if _current_tween and _current_tween.is_valid():
_current_tween.kill()
func _set_time_scale(scale: float) -> void:
_current_time_scale = scale
Engine.time_scale = scale
func _slow_time(scale: float) -> void:
_set_time_scale(scale)
_should_maintain_slow = true
func _reset_time() -> void:
_set_time_scale(DEFAULT_TIME_SCALE)
_should_maintain_slow = false
func _fade_to(target_alpha: float) -> void:
if _is_fading:
return
_is_fading = true
_current_tween = create_tween()
_current_tween.tween_property(_fade_overlay, "color:a", target_alpha, FADE_DURATION)
_current_tween.tween_callback(func(): _is_fading = false)
# endregion
## 获取当前时间缩放值
func get_current_time_scale() -> float:
return _current_time_scale
## 检查是否正在执行渐变
func is_fading() -> bool:
return _is_fading
## 检查是否处于减速状态
func is_time_slowed() -> bool:
return _should_maintain_slow

View File

@ -0,0 +1 @@
uid://lapr5splvajf

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dd7k3qbsw1bhq"]
[ext_resource type="Script" path="res://Char/Char_Components/After_Image/after_image_component.gd" id="1_c5t65"]
[node name="After_Image_Component" type="Node"]
script = ExtResource("1_c5t65")

View File

@ -0,0 +1,65 @@
[gd_scene load_steps=4 format=3 uid="uid://ce7d2uw5710fo"]
[sub_resource type="Animation" id="Animation_i6syn"]
resource_name = "Fading"
length = 0.1
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:self_modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [Color(0.197937, 0.197937, 0.197937, 0.588235), Color(1, 1, 1, 0)]
}
tracks/1/type = "method"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0.1),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"queue_free"
}]
}
[sub_resource type="Animation" id="Animation_28t5o"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:self_modulate")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0.197937, 0.197937, 0.197937, 0.588235)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_s12ut"]
_data = {
&"Fading": SubResource("Animation_i6syn"),
&"RESET": SubResource("Animation_28t5o")
}
[node name="After_Image" type="Node2D" groups=["After_Image"]]
self_modulate = Color(0.196078, 0.196078, 0.196078, 0.588235)
[node name="Sprite2D" type="Sprite2D" parent="."]
self_modulate = Color(0.197937, 0.197937, 0.197937, 0.588235)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_s12ut")
}
autoplay = "Fading"

View File

@ -0,0 +1,175 @@
extends Node
var can_spawn = true
var spawn_frequency = 0.01
var base_scale = 0.9
var min_velocity = 5.0
var is_active = false
var after_image_material: ShaderMaterial
var after_image_scene = preload("res://Char/Char_Components/After_Image/after_image.tscn")
@onready var player = get_parent()
@onready var owner_sprite = player.get_node("Body_Animation/Sprite2D")
@onready var owner_anim = player.get_node("Body_Animation/AnimationPlayer")
func _ready():
if !after_image_material:
var new_material = ShaderMaterial.new()
new_material.shader = load("res://Char/Char_Components/After_Image/player_dash.gdshader")
after_image_material = new_material
after_image_material.set_shader_parameter("effect_mixture", 0.0)
after_image_material.set_shader_parameter("alpha_multiplier", 1.0)
after_image_material.set_shader_parameter("color_offset", 0.0)
after_image_material.set_shader_parameter("glow_intensity", 1.2)
reset_spawn_timer()
func _physics_process(_delta):
if is_active and can_spawn:
var velocity = owner.velocity if owner.has_method("get_velocity") else Vector2.ZERO
if velocity.length() >= min_velocity:
spawn_after_image()
func clear_shader():
after_image_material = null
func init_shader(shader_path: String, params: Dictionary = {}):
after_image_material = ShaderMaterial.new()
after_image_material.shader = load(shader_path)
for param_name in params:
after_image_material.set_shader_parameter(param_name, params[param_name])
func reset_spawn_timer():
can_spawn = false
await get_tree().create_timer(spawn_frequency).timeout
can_spawn = true
func spawn_after_image():
var level = get_tree().get_first_node_in_group("Level")
if !level:
return
var effect_group = level.get_node("Effect_Group")
if !effect_group:
return
var after_image = after_image_scene.instantiate()
after_image.position = owner_sprite.global_position
after_image.scale = owner_sprite.scale * base_scale
var after_image_sprite:Sprite2D = after_image.get_node("Sprite2D")
after_image_sprite.texture = owner_sprite.texture
after_image_sprite.region_enabled = true
after_image_sprite.region_rect = owner_sprite.region_rect
after_image.scale.x *= owner.get_node("Body_Animation").scale.x
if after_image_material:
var current_material = ShaderMaterial.new()
current_material.shader = after_image_material.shader
current_material.set_shader_parameter("rainbow_width",
after_image_material.get_shader_parameter("rainbow_width"))
current_material.set_shader_parameter("rainbow_speed",
after_image_material.get_shader_parameter("rainbow_speed"))
after_image_sprite.material = current_material
after_image.z_index = 5
effect_group.add_child(after_image)
reset_spawn_timer()
func start():
is_active = true
can_spawn = true
func stop():
is_active = false
can_spawn = false
clear_shader()
func set_shader_parameter(param_name: String, value):
if after_image_material:
after_image_material.set_shader_parameter(param_name, value)
func configure(config: Dictionary):
if config.has("spawn_frequency"):
spawn_frequency = config.spawn_frequency
if config.has("base_scale"):
base_scale = config.base_scale
if config.has("min_velocity"):
min_velocity = config.min_velocity
clear_shader()
func spawn_trail_between_points(start_pos: Vector2, end_pos: Vector2, num_images: int = 16, shader:bool = true, after_image_texture: Texture = null, after_image_rect: Rect2 = Rect2()):
var level = get_tree().get_first_node_in_group("Level")
if !level:
return
var effect_group = level.get_node("Effect_Group")
if !effect_group:
return
var total_distance = start_pos.distance_to(end_pos)
var direction = (end_pos - start_pos).normalized()
# 定义透明度范围
var alpha_start = 0.1 # 起始透明度
var alpha_end = 0.8 # 结束透明度
if shader and !after_image_material:
var new_material = ShaderMaterial.new()
new_material.shader = load("res://Char/Char_Components/After_Image/player_dash.gdshader")
after_image_material = new_material
after_image_material.set_shader_parameter("effect_mixture", 1.0)
after_image_material.set_shader_parameter("alpha_multiplier", 1.0)
after_image_material.set_shader_parameter("color_offset", 0.0)
after_image_material.set_shader_parameter("glow_intensity", 1.2)
for i in range(num_images):
var progress = float(i) / float(num_images - 1)
var adjusted_progress = 1.0 - pow(1.0 - progress, 1.5)
var current_pos = start_pos + direction * (total_distance * adjusted_progress)
var after_image = after_image_scene.instantiate()
var after_image_sprite = after_image.get_node("Sprite2D")
after_image_sprite.texture = after_image_texture
if after_image_rect != Rect2():
after_image_sprite.region_enabled = true
after_image_sprite.region_rect = after_image_rect
if end_pos.x < start_pos.x:
after_image_sprite.set_flip_h(true)
else:
after_image_sprite.set_flip_h(false)
after_image.position = current_pos + owner_sprite.position
after_image.scale = owner_sprite.scale * base_scale
# 计算当前的透明度
var current_alpha = lerp(alpha_start, alpha_end, progress)
if shader and after_image_material:
var current_material = after_image_material.duplicate()
current_material.set_shader_parameter("effect_mixture", 1.0)
# 使用统一的透明度计算
current_material.set_shader_parameter("alpha_multiplier", current_alpha)
current_material.set_shader_parameter("color_offset", 1.0 - progress)
after_image_sprite.material = current_material
# 如果需要同时使用modulate和shader效果
after_image_sprite.modulate = Color(1, 1, 1, current_alpha)
else:
# 非shader情况下的透明度处理
after_image_sprite.modulate = Color(1, 1, 1, current_alpha)
after_image.z_index = 5
effect_group.add_child(after_image)
if shader:
clear_shader()

View File

@ -0,0 +1 @@
uid://gw5o7qlfk82k

View File

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dd7k3qbsw1bhq"]
[ext_resource type="Script" uid="uid://gw5o7qlfk82k" path="res://Char/Char_Components/After_Image/after_image_component.gd" id="1_c5t65"]
[node name="After_Image_Component" type="Node"]
script = ExtResource("1_c5t65")

View File

@ -0,0 +1,78 @@
shader_type canvas_item;
uniform bool time_slowed = false;
uniform float effect_mixture : hint_range(0.0, 1.0) = 0.0;
uniform float alpha_multiplier = 1.0;
uniform float color_offset = 0.0; // 颜色偏移值
uniform float glow_intensity = 1.2;
uniform float inner_glow_width = 0.5;
uniform float outer_glow_width = 2.0;
uniform float pulse_speed = 2.0;
uniform float pulse_strength = 0.2;
uniform bool high_quality = true; // 性能开关
// HSV转RGB函数
vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
void fragment() {
vec4 texture_color = texture(TEXTURE, UV);
if (texture_color.a > 0.0) {
vec3 blue_base = vec3(0.2, 0.6, 1.5);
float luminance = dot(texture_color.rgb, vec3(0.299, 0.587, 0.114));
// 脉冲动画效果
float pulse = (sin(TIME * pulse_speed) * 0.5 + 0.5) * pulse_strength;
// 内发光效果
float inner_glow = pow(luminance, inner_glow_width) * glow_intensity;
// 外发光效果
float outer_glow = 0.0;
if (high_quality) {
// 高质量模式 - 完整采样
vec2 size = 1.0 / TEXTURE_PIXEL_SIZE;
vec2 pixel_size = 1.0 / size;
for(float x = -outer_glow_width; x <= outer_glow_width; x += 1.0) {
for(float y = -outer_glow_width; y <= outer_glow_width; y += 1.0) {
vec2 offset = vec2(x, y) * pixel_size;
float sample_alpha = texture(TEXTURE, UV + offset).a;
float distance = length(vec2(x, y)) / outer_glow_width;
outer_glow += sample_alpha * (1.0 - distance);
}
}
outer_glow = outer_glow / (outer_glow_width * outer_glow_width * 4.0);
} else {
// 性能模式 - 简化采样
float sample_distance = outer_glow_width * 0.5;
vec2 pixel_size = 1.0 / (1.0 / TEXTURE_PIXEL_SIZE);
for(float i = 0.0; i < 4.0; i++) {
float angle = i * PI * 0.5;
vec2 offset = vec2(cos(angle), sin(angle)) * sample_distance * pixel_size;
outer_glow += texture(TEXTURE, UV + offset).a;
}
outer_glow = outer_glow * 0.25;
}
float total_glow = inner_glow + outer_glow + pulse;
// 基于color_offset生成颜色范围集中在黄色系
float hue = fract(color_offset) * 0.4 + 0.1; // 0.1-0.5范围,集中在黄色区域
vec3 rainbow_color = hsv2rgb(vec3(hue, 0.9, 0.95)); // 高饱和度,稍微降低亮度
// 混合发光效果
vec3 final_color = mix(blue_base, rainbow_color, total_glow);
final_color += rainbow_color * total_glow * 0.5;
// 最终颜色混合
vec3 mixed_color = mix(texture_color.rgb, final_color, effect_mixture);
COLOR = vec4(mixed_color, texture_color.a * alpha_multiplier);
} else {
COLOR = vec4(texture_color.rgb, texture_color.a * alpha_multiplier);
}
}

View File

@ -0,0 +1 @@
uid://yqf4d8jhe08n

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ckeych64pqat5"
path="res://.godot/imported/blood_stain_1.png-fa41647d084c0f93ca6ca680f0f9e558.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/blood_stain_1.png"
dest_files=["res://.godot/imported/blood_stain_1.png-fa41647d084c0f93ca6ca680f0f9e558.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

@ -0,0 +1,9 @@
[gd_scene load_steps=2 format=3 uid="uid://cvo81ftpraiox"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_q1ejx"]
[node name="blood_stain_1_01" type="Sprite2D"]
self_modulate = Color(0.584314, 0.584314, 0.584314, 0.792157)
texture = ExtResource("1_q1ejx")
region_enabled = true
region_rect = Rect2(6, 12, 18, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://njyayfryqw4t"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_3pwwm"]
[node name="blood_stain_1_02" type="Sprite2D"]
texture = ExtResource("1_3pwwm")
region_enabled = true
region_rect = Rect2(42, 12, 18, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bufiuix6cnf47"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_trp84"]
[node name="blood_stain_1_03" type="Sprite2D"]
texture = ExtResource("1_trp84")
region_enabled = true
region_rect = Rect2(72, 6, 18, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bseih617jgpn7"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_q5o66"]
[node name="blood_stain_1_04" type="Sprite2D"]
texture = ExtResource("1_q5o66")
region_enabled = true
region_rect = Rect2(108, 6, 12, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dcvfvishu32o"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_l8egl"]
[node name="blood_stain_1_05" type="Sprite2D"]
texture = ExtResource("1_l8egl")
region_enabled = true
region_rect = Rect2(138, 6, 18, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://cf0qk5x0d1aao"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_glts2"]
[node name="blood_stain_1_06" type="Sprite2D"]
texture = ExtResource("1_glts2")
region_enabled = true
region_rect = Rect2(168, 6, 18, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://c7ym7k205dp7g"]
[ext_resource type="Texture2D" uid="uid://ckeych64pqat5" path="res://Char/Char_Components/Blood/Art/blood_stain_1.png" id="1_odg3f"]
[node name="blood_stain_1_07" type="Sprite2D"]
texture = ExtResource("1_odg3f")
region_enabled = true
region_rect = Rect2(204, 12, 12, 12)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://1e5r5c6bsoo"
path="res://.godot/imported/blood_stain_2.png-32689891efbd2668df399cb281736924.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/blood_stain_2.png"
dest_files=["res://.godot/imported/blood_stain_2.png-32689891efbd2668df399cb281736924.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dv342saiudbuw"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_xyws2"]
[node name="blood_stain_2_01" type="Sprite2D"]
texture = ExtResource("1_xyws2")
region_enabled = true
region_rect = Rect2(6, 12, 30, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://ds30a70uwl4iu"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_krthc"]
[node name="blood_stain_2_02" type="Sprite2D"]
texture = ExtResource("1_krthc")
region_enabled = true
region_rect = Rect2(48, 12, 30, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bdryepy5bm282"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_esujp"]
[node name="blood_stain_2_03" type="Sprite2D"]
texture = ExtResource("1_esujp")
region_enabled = true
region_rect = Rect2(90, 12, 36, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dhovjxccg2mqm"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_srjcf"]
[node name="blood_stain_2_04" type="Sprite2D"]
texture = ExtResource("1_srjcf")
region_enabled = true
region_rect = Rect2(132, 12, 30, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bthfgajr33gh7"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_tygqj"]
[node name="blood_stain_2_05" type="Sprite2D"]
texture = ExtResource("1_tygqj")
region_enabled = true
region_rect = Rect2(6, 42, 30, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://cmbgju0i610ps"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_x3bik"]
[node name="blood_stain_2_06" type="Sprite2D"]
texture = ExtResource("1_x3bik")
region_enabled = true
region_rect = Rect2(48, 42, 36, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://orh0bway7jr2"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_0hg8m"]
[node name="blood_stain_2_07" type="Sprite2D"]
texture = ExtResource("1_0hg8m")
region_enabled = true
region_rect = Rect2(96, 42, 30, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bfn2671b38alp"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_prppv"]
[node name="blood_stain_2_08" type="Sprite2D"]
texture = ExtResource("1_prppv")
region_enabled = true
region_rect = Rect2(132, 42, 30, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://bfhsqlvxufqqj"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_146v3"]
[node name="blood_stain_2_09" type="Sprite2D"]
texture = ExtResource("1_146v3")
region_enabled = true
region_rect = Rect2(6, 72, 36, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://dex00007ea3h1"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_vvnj2"]
[node name="blood_stain_2_10" type="Sprite2D"]
texture = ExtResource("1_vvnj2")
region_enabled = true
region_rect = Rect2(48, 78, 36, 12)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://di40o3c74hsw6"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_1m0gx"]
[node name="blood_stain_2_11" type="Sprite2D"]
texture = ExtResource("1_1m0gx")
region_enabled = true
region_rect = Rect2(90, 72, 36, 18)

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://b573pp1o23j4y"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_0if4e"]
[node name="blood_stain_2_12" type="Sprite2D"]
texture = ExtResource("1_0if4e")
region_enabled = true
region_rect = Rect2(132, 78, 30, 12)

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://411dga7lbi6i"
path="res://.godot/imported/spr_blood2_0.png-b8c515ae7d2fdc5e8c799f6b03dc93f8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood2_0.png"
dest_files=["res://.godot/imported/spr_blood2_0.png-b8c515ae7d2fdc5e8c799f6b03dc93f8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cywd468wrclbi"
path="res://.godot/imported/spr_blood2_1.png-12727a417ecdfa178b003ef534820aec.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood2_1.png"
dest_files=["res://.godot/imported/spr_blood2_1.png-12727a417ecdfa178b003ef534820aec.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ylmx7ejlfje"
path="res://.godot/imported/spr_blood2_2.png-274862736b0b23a346364a798321ffaa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood2_2.png"
dest_files=["res://.godot/imported/spr_blood2_2.png-274862736b0b23a346364a798321ffaa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://va4x1qryhleq"
path="res://.godot/imported/spr_blood2_3.png-d73d746830595aff3132d0188eafaf4e.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood2_3.png"
dest_files=["res://.godot/imported/spr_blood2_3.png-d73d746830595aff3132d0188eafaf4e.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://de3nomyhghkvi"
path="res://.godot/imported/spr_blood2_4.png-5c69b4d1ff3d78a2d681ddad82c542c3.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood2_4.png"
dest_files=["res://.godot/imported/spr_blood2_4.png-5c69b4d1ff3d78a2d681ddad82c542c3.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cudohua7dtpks"
path="res://.godot/imported/spr_blood2_5.png-d3c33a718bbf819dea1f7569d03b16ca.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood2_5.png"
dest_files=["res://.godot/imported/spr_blood2_5.png-d3c33a718bbf819dea1f7569d03b16ca.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bqtct1nxe724a"
path="res://.godot/imported/spr_blood3_0.png-0b7491352704b0cf612a755b89012e94.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood3_0.png"
dest_files=["res://.godot/imported/spr_blood3_0.png-0b7491352704b0cf612a755b89012e94.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dbx7xette0hx7"
path="res://.godot/imported/spr_blood3_1.png-dc2ed1d778183c37b39e826d07829e8c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood3_1.png"
dest_files=["res://.godot/imported/spr_blood3_1.png-dc2ed1d778183c37b39e826d07829e8c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c6g0dm5hm7t3"
path="res://.godot/imported/spr_blood3_2.png-6b3b1e9d88f100e4a18dcc1254fbb3db.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood3_2.png"
dest_files=["res://.godot/imported/spr_blood3_2.png-6b3b1e9d88f100e4a18dcc1254fbb3db.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bi6nm4qdr1at6"
path="res://.godot/imported/spr_blood3_3.png-42efb0c0a85df4110fa91d3e059dd4fa.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood3_3.png"
dest_files=["res://.godot/imported/spr_blood3_3.png-42efb0c0a85df4110fa91d3e059dd4fa.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dosr0uksuoqdf"
path="res://.godot/imported/spr_blood3_4.png-2c985ec843feec3959c998f45398b9a8.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood3_4.png"
dest_files=["res://.godot/imported/spr_blood3_4.png-2c985ec843feec3959c998f45398b9a8.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cuo001phdjlds"
path="res://.godot/imported/spr_blood3_5.png-81576a7871265b57c0fe2e5e1bea23bf.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Blood/Art/spr_blood3_5.png"
dest_files=["res://.godot/imported/spr_blood3_5.png-81576a7871265b57c0fe2e5e1bea23bf.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

@ -0,0 +1,283 @@
extends Node2D
@export var min_rays := 5
@export var max_rays := 12
@export var min_length := 60.0
@export var max_length := 160.0
var spread_angle := randf_range(20,30)
var _last_sprite_index: int = -1 # 记录上一次使用的精灵索引
var blood_part_2_enabled = false
#func _ready() -> void:
#create_part1_blood(Vector2(1,0))
func _physics_process(_delta: float) -> void:
if blood_part_2_enabled and randf() > 0.5:
var pos = global_position
var dir = get_parent().velocity.normalized()
spawn_blood_part_2(pos,dir)
#region 初始涂墙
func create_part1_blood(direction):
var current_rays = generate_rays(direction)
for each_ray in current_rays:
create_two_segment_sprite_line(each_ray["start"], each_ray["middle_point"], each_ray["end"], randi_range(10,30),randi_range(1,3))
func generate_rays(direction: Vector2) -> Array:
var current_rays: Array = []
direction = direction.normalized()
var ray_count = randi_range(min_rays, max_rays)
# 1. 计算角度范围
var base_angle = direction.angle()
var max_deviation = deg_to_rad(spread_angle)
var section_size = (max_deviation * 2) / (ray_count + 1)
var start_angle = base_angle - max_deviation
# 2. 创建所有射线
var raycasts: Array[RayCast2D] = []
for i in ray_count:
var section_start = start_angle + section_size * i
var section_end = section_start + section_size
var final_angle = randf_range(section_start, section_end)
var raycast = RayCast2D.new()
add_child(raycast)
raycasts.append(raycast)
raycast.position = Vector2.ZERO
var ray_direction = Vector2(cos(final_angle), sin(final_angle))
var ray_length = randf_range(min_length, max_length)
raycast.target_position = ray_direction * ray_length
raycast.collision_mask = 0
for layer in [20,22,23,24,25]:
raycast.set_collision_mask_value(layer, true)
raycast.enabled = true
raycast.force_raycast_update()
# 3. 处理射线结果
for i in ray_count:
var raycast = raycasts[i]
var ray_direction = raycast.target_position.normalized()
var intended_length = raycast.target_position.length()
# 生成60%-80%之间的随机比例
var middle_ratio = randf_range(0.5, 0.8)
if raycast.is_colliding():
var global_collision_point = raycast.get_collision_point()
var distance_to_collision = global_position.distance_to(global_collision_point)
if distance_to_collision <= intended_length:
# 计算中间点(在实际碰撞点之前)
var middle_point = global_position.lerp(global_collision_point, middle_ratio)
current_rays.append({
"start": global_position,
"end": global_collision_point,
"middle_point": middle_point,
"collision": true,
"out_of_range_collision": false,
"intended_length": intended_length
})
else:
var global_clamped_end = global_position + (ray_direction * intended_length)
var middle_point = global_position.lerp(global_clamped_end, middle_ratio)
current_rays.append({
"start": global_position,
"end": global_clamped_end,
"middle_point": middle_point,
"collision": false,
"out_of_range_collision": true,
"intended_length": intended_length
})
else:
var global_intended_end = global_position + (ray_direction * intended_length)
var middle_point = global_position.lerp(global_intended_end, middle_ratio)
current_rays.append({
"start": global_position,
"end": global_intended_end,
"middle_point": middle_point,
"collision": false,
"out_of_range_collision": false,
"intended_length": intended_length
})
raycast.queue_free()
return current_rays
# 主函数:生成三点两段的精灵线
func create_two_segment_sprite_line(
start_pos: Vector2,
middle_pos: Vector2,
end_pos: Vector2,
first_segment_count: int,
second_segment_count: int,
) -> void:
var sprite_scene_group_1: Array[PackedScene] = [
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_01.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_02.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_03.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_04.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_05.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_06.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_07.tscn")
]
var sprite_scene_group_2: Array[PackedScene] = [
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_01.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_02.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_03.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_04.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_05.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_06.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_07.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_08.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_09.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_10.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_12.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_11.tscn")
]
_last_sprite_index = -1 # 重置上一次的索引
# 生成两段
create_sprite_line_segment(start_pos, middle_pos, first_segment_count, 1.1, 1.0, sprite_scene_group_1)
_last_sprite_index = -1 # 两段之间重置,让两段独立
create_sprite_line_segment(middle_pos, end_pos, second_segment_count, 0.8, 0.6, sprite_scene_group_2)
# 生成单段精灵线
func create_sprite_line_segment(
start_pos: Vector2,
end_pos: Vector2,
sprite_count: int,
start_scale: float,
end_scale: float,
_sprite_scene_group: Array[PackedScene]
) -> void:
var parent = get_tree().get_first_node_in_group("Effect_Group")
if not parent:
push_warning("未找到Effect_Group组的节点")
return
sprite_count = maxi(1, sprite_count)
var direction = end_pos - start_pos
for i in range(sprite_count):
var progress = float(i) / (sprite_count - 1) if sprite_count > 1 else 0.0
var _current_pos = start_pos.lerp(end_pos, progress)
var _scale_value = lerp(start_scale, end_scale, progress)
var _rotation = direction.angle()
# 随机选择一个场景(避免重复)
#var selected_scene = _get_random_sprite_scene(sprite_scene_group)
#_create_single_sprite(current_pos, _rotation, scale_value, parent, selected_scene)
var blood_impulse_percent = randf()
if blood_impulse_percent > 0.9:
spawn_blood_part_1(start_pos,end_pos)
blood_part_2_enabled = true
# 随机选择场景(避免与上次重复)
func _get_random_sprite_scene(sprite_scene_group: Array[PackedScene]) -> PackedScene:
var group_size = sprite_scene_group.size()
if group_size == 1:
return sprite_scene_group[0]
# 生成可用索引列表(排除上次使用的索引)
var available_indices: Array[int] = []
for i in range(group_size):
if i != _last_sprite_index:
available_indices.append(i)
# 随机选择一个新索引
var random_index = available_indices[randi() % available_indices.size()]
_last_sprite_index = random_index # 更新上次使用的索引
return sprite_scene_group[random_index]
# 创建单个精灵
func _create_single_sprite(pos: Vector2, _rotation: float, scale_value: float, parent: Node, sprite_scene: PackedScene) -> void:
var sprite = sprite_scene.instantiate() as Sprite2D
if not sprite:
push_warning("场景实例化失败!")
return
sprite.position = pos
sprite.rotation = _rotation
sprite.scale = Vector2(scale_value, scale_value)
sprite.self_modulate = Color.from_string("959595ca", Color.WHITE)
parent.add_child(sprite)
#region End
func spawn_blood_part_1(start_pos: Vector2, end_pos: Vector2) -> void:
var effect_scene = preload("res://Char/Char_Components/Blood/blood_part.tscn")
# 计算方向向量(标准化)
var dir = (end_pos - start_pos).normalized()
# 随机选择生成位置
var spawn_pos = start_pos if randi() % 2 == 0 else end_pos
# 实例化场景
var effect_instance = effect_scene.instantiate()
# 设置位置和旋转
effect_instance.global_position = spawn_pos
effect_instance.rotation = dir.angle()
effect_instance.can_stain = true
effect_instance.z_index = 2
# 设置速度 (假设effect_instance继承自CharacterBody2D)
effect_instance.velocity = dir * randf_range(100,200)
# 添加到效果组的第一个节点下
var effect_parent = get_tree().get_first_node_in_group("Effect_Group")
if effect_parent:
effect_parent.add_child(effect_instance)
func spawn_blood_part_2(pos: Vector2, dir: Vector2) -> void:
var PROJECTILE_SPEED = 80.0
var scene = preload("res://Char/Char_Components/Blood/blood_part.tscn")
# 确保方向向量有效
if dir.length_squared() == 0:
dir = Vector2(0,1)
# 获取特定组的父节点
var parent = get_tree().get_first_node_in_group("Effect_Group")
if not parent:
push_error("Cannot find Effect_Group node")
return
# 标准化方向向量
var normalized_dir = dir.normalized()
# 实例化场景
var instance = scene.instantiate() as CharacterBody2D
if not instance:
push_error("Failed to instantiate scene or invalid type")
return
# 添加到场景树
parent.add_child(instance)
# 计算基础角度和随机偏移
var base_angle = (-normalized_dir).angle()
var random_offset = deg_to_rad(randf_range(-3.0, 3.0)) # 转换度数为弧度
var final_angle = base_angle + random_offset
# 设置位置和朝向
instance.global_position = pos
instance.rotation = final_angle
instance.scale.y *= 1 if randf() < 0.5 else -1 #血液喷出动画左右镜像
instance.can_stain = true
instance.z_index = 2
# 根据最终角度计算速度方向
var final_dir = Vector2.from_angle(final_angle + PI) # 加PI是因为我们要反方向
# 设置初始速度
instance.velocity = final_dir * PROJECTILE_SPEED

View File

@ -0,0 +1 @@
uid://5h4w13512vya

View File

@ -0,0 +1,136 @@
[gd_scene load_steps=12 format=3 uid="uid://bj7ycp6aj85je"]
[ext_resource type="Script" uid="uid://5h4w13512vya" path="res://Char/Char_Components/Blood/Blood_Component.gd" id="1_d6wdq"]
[ext_resource type="Texture2D" uid="uid://bqtct1nxe724a" path="res://Char/Char_Components/Blood/Art/spr_blood3_0.png" id="2_n46qh"]
[ext_resource type="Texture2D" uid="uid://dbx7xette0hx7" path="res://Char/Char_Components/Blood/Art/spr_blood3_1.png" id="3_fyp4q"]
[ext_resource type="Texture2D" uid="uid://bi6nm4qdr1at6" path="res://Char/Char_Components/Blood/Art/spr_blood3_3.png" id="4_3tgul"]
[ext_resource type="Texture2D" uid="uid://dosr0uksuoqdf" path="res://Char/Char_Components/Blood/Art/spr_blood3_4.png" id="5_jpkhl"]
[ext_resource type="Texture2D" uid="uid://cuo001phdjlds" path="res://Char/Char_Components/Blood/Art/spr_blood3_5.png" id="6_g8yvn"]
[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_bxxjd"]
[sub_resource type="Animation" id="Animation_rbj3g"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [SubResource("CompressedTexture2D_bxxjd")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(10, 1)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [-0.165806]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite2D:self_modulate")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(0.92549, 0, 0, 0)]
}
[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_0ycfe"]
[sub_resource type="Animation" id="Animation_xwo6r"]
resource_name = "blood_hurt_begin"
length = 0.6
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("2_n46qh"), ExtResource("3_fyp4q"), SubResource("CompressedTexture2D_0ycfe"), ExtResource("4_3tgul"), ExtResource("5_jpkhl"), ExtResource("6_g8yvn")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.3, 0.4),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 1,
"values": [Vector2(10, 1), Vector2(10, -1), Vector2(10, -3)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:rotation")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.3, 0.4, 0.5),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [0.0, -0.165806, -0.296706, -0.986111]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("Sprite2D:self_modulate")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0, 0.5, 0.6),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(0.923959, 4.86121e-06, 1.34766e-06, 1), Color(0.923959, 4.86121e-06, 1.34766e-06, 1), Color(0.92549, 0, 0, 0)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_uoogr"]
_data = {
&"RESET": SubResource("Animation_rbj3g"),
&"blood_hurt_begin": SubResource("Animation_xwo6r")
}
[node name="Blood_Component" type="Node2D"]
script = ExtResource("1_d6wdq")
[node name="Sprite2D" type="Sprite2D" parent="."]
self_modulate = Color(0.92549, 0, 0, 0)
position = Vector2(10, 1)
rotation = -0.165806
texture = SubResource("CompressedTexture2D_bxxjd")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_uoogr")
}

View File

@ -0,0 +1,12 @@
// mask_shader.gdshader
shader_type canvas_item;
uniform sampler2D mask_texture;
void fragment() {
vec4 sprite_color = texture(TEXTURE, UV);
vec4 mask_color = texture(mask_texture, SCREEN_UV);
COLOR = sprite_color;
COLOR.a *= mask_color.r;
}

View File

@ -0,0 +1 @@
uid://ft0ftw3xf13d

View File

@ -0,0 +1,113 @@
extends CharacterBody2D
var can_stain = false
# 所有可用的动画名称(方便后续添加新动画)
const AVAILABLE_ANIMATIONS = [
"impulse_1",
"impulse_2",
# 未来可以直接在这里添加新的动画名称
# "impulse_3",
# "impulse_4",
]
func _ready() -> void:
var anim_player = $AnimationPlayer
anim_player.speed_scale = randf_range(0.8,1.2)
# 确保有可用的动画
if AVAILABLE_ANIMATIONS.is_empty():
push_warning("没有可用的动画!")
queue_free()
return
# 随机选择一个动画名称
var random_index = randi() % AVAILABLE_ANIMATIONS.size()
var chosen_anim = AVAILABLE_ANIMATIONS[random_index]
# 验证动画是否存在
if not anim_player.has_animation(chosen_anim):
push_warning("动画 %s 不存在!" % chosen_anim)
queue_free()
return
# 播放选中的动画
anim_player.play(chosen_anim)
func _physics_process(_delta: float) -> void:
move_and_slide()
func spawn_random_effect() -> Node2D:
if not can_stain:
return
var pos = global_position
var dir = velocity.normalized()
var group_1: Array[PackedScene] = [
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_01.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_02.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_03.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_04.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_05.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_06.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_1_07.tscn")
]
var group_2: Array[PackedScene] = [
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_01.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_02.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_03.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_04.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_05.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_06.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_07.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_08.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_09.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_10.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_12.tscn"),
preload("res://Char/Char_Components/Blood/Art/blood_stain_2_11.tscn")
]
# 随机选择使用哪个组50%概率)
var selected_group: Array[PackedScene]
var is_group_1: bool = randf() < 0.5
selected_group = group_1 if is_group_1 else group_2
# 如果选中的组是空的,使用另一个组
if selected_group.is_empty():
selected_group = group_2 if is_group_1 else group_1
is_group_1 = !is_group_1
# 随机选择场景并实例化
var random_scene: PackedScene = selected_group[randi() % selected_group.size()]
var instance = random_scene.instantiate() as Node2D
if not instance:
push_error("Failed to instantiate scene!")
return null
# 设置位置
instance.global_position = pos
instance.self_modulate = Color.from_string("959595ca", Color.WHITE)
instance.z_index = 2
# 根据组别应用不同的变换
if is_group_1:
# 对group_1随机旋转
instance.rotation = randf_range(0, TAU) # TAU = 2π
#随机缩放
var random_scale = randf_range(1.1, 1.6)
instance.scale = Vector2(random_scale, random_scale)
else:
# 对group_2设置指定朝向
instance.transform = Transform2D(dir.angle(), pos)
#随机缩放
var random_scale = randf_range(0.8, 1)
instance.scale = Vector2(random_scale, random_scale)
# 添加到效果组
var effect_group = get_tree().get_first_node_in_group("Effect_Group")
if effect_group:
effect_group.add_child(instance)
else:
push_error("Effect_Group not found!")
instance.queue_free()
return null
return instance

View File

@ -0,0 +1 @@
uid://bxpdshv4vrg5g

View File

@ -0,0 +1,194 @@
[gd_scene load_steps=18 format=3 uid="uid://bqrjt8yb6bl27"]
[ext_resource type="Script" uid="uid://bxpdshv4vrg5g" path="res://Char/Char_Components/Blood/blood_part.gd" id="1_vga13"]
[ext_resource type="Texture2D" uid="uid://bqtct1nxe724a" path="res://Char/Char_Components/Blood/Art/spr_blood3_0.png" id="2_scf3e"]
[ext_resource type="Texture2D" uid="uid://dbx7xette0hx7" path="res://Char/Char_Components/Blood/Art/spr_blood3_1.png" id="3_5dmvv"]
[ext_resource type="Texture2D" uid="uid://c6g0dm5hm7t3" path="res://Char/Char_Components/Blood/Art/spr_blood3_2.png" id="4_7rq5f"]
[ext_resource type="Texture2D" uid="uid://bi6nm4qdr1at6" path="res://Char/Char_Components/Blood/Art/spr_blood3_3.png" id="5_p06en"]
[ext_resource type="Texture2D" uid="uid://dosr0uksuoqdf" path="res://Char/Char_Components/Blood/Art/spr_blood3_4.png" id="6_hc7gt"]
[ext_resource type="Texture2D" uid="uid://cuo001phdjlds" path="res://Char/Char_Components/Blood/Art/spr_blood3_5.png" id="7_32u30"]
[ext_resource type="Texture2D" uid="uid://411dga7lbi6i" path="res://Char/Char_Components/Blood/Art/spr_blood2_0.png" id="8_nl6dm"]
[ext_resource type="Texture2D" uid="uid://cywd468wrclbi" path="res://Char/Char_Components/Blood/Art/spr_blood2_1.png" id="9_e20gj"]
[ext_resource type="Texture2D" uid="uid://ylmx7ejlfje" path="res://Char/Char_Components/Blood/Art/spr_blood2_2.png" id="10_6jt12"]
[ext_resource type="Texture2D" uid="uid://va4x1qryhleq" path="res://Char/Char_Components/Blood/Art/spr_blood2_3.png" id="11_ntuc6"]
[ext_resource type="Texture2D" uid="uid://de3nomyhghkvi" path="res://Char/Char_Components/Blood/Art/spr_blood2_4.png" id="12_abujt"]
[ext_resource type="Texture2D" uid="uid://cudohua7dtpks" path="res://Char/Char_Components/Blood/Art/spr_blood2_5.png" id="13_bba02"]
[sub_resource type="Animation" id="Animation_g3m3s"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_scf3e")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(10, 1)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:self_modulate")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 0)]
}
[sub_resource type="Animation" id="Animation_n86p7"]
resource_name = "impulse_1"
length = 0.45
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.05, 0.1, 0.15, 0.25, 0.35),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("2_scf3e"), ExtResource("3_5dmvv"), ExtResource("4_7rq5f"), ExtResource("5_p06en"), ExtResource("6_hc7gt"), ExtResource("7_32u30")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.05, 0.1, 0.15),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [Vector2(10, 1), Vector2(9, 1), Vector2(8, 1), Vector2(7, 1)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:self_modulate")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.35, 0.45),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(0.643137, 0.0392157, 0.0392157, 1), Color(0.643137, 0.0392157, 0.0392157, 1), Color(1, 1, 1, 0)]
}
tracks/3/type = "method"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath(".")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0.2, 0.45),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"spawn_random_effect"
}, {
"args": [],
"method": &"queue_free"
}]
}
[sub_resource type="Animation" id="Animation_ri227"]
resource_name = "impulse_2"
length = 0.45
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.05, 0.1, 0.15, 0.25, 0.35),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("8_nl6dm"), ExtResource("9_e20gj"), ExtResource("10_6jt12"), ExtResource("11_ntuc6"), ExtResource("12_abujt"), ExtResource("13_bba02")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.05, 0.1, 0.15),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [Vector2(11, 1), Vector2(9, 1), Vector2(8, 1), Vector2(7, 1)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("Sprite2D:self_modulate")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.35, 0.45),
"transitions": PackedFloat32Array(1, 1, 1),
"update": 0,
"values": [Color(0.643137, 0.0392157, 0.0392157, 1), Color(0.643137, 0.0392157, 0.0392157, 1), Color(1, 1, 1, 0)]
}
tracks/3/type = "method"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath(".")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0.2, 0.45),
"transitions": PackedFloat32Array(1, 1),
"values": [{
"args": [],
"method": &"spawn_random_effect"
}, {
"args": [],
"method": &"queue_free"
}]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_64yuh"]
_data = {
&"RESET": SubResource("Animation_g3m3s"),
&"impulse_1": SubResource("Animation_n86p7"),
&"impulse_2": SubResource("Animation_ri227")
}
[node name="Blood_Part" type="CharacterBody2D"]
z_index = 2
script = ExtResource("1_vga13")
[node name="Sprite2D" type="Sprite2D" parent="."]
self_modulate = Color(1, 1, 1, 0)
light_mask = 2
visibility_layer = 2
position = Vector2(10, 1)
scale = Vector2(1.8, 1.8)
texture = ExtResource("2_scf3e")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_64yuh")
}

View File

@ -0,0 +1,147 @@
extends Sprite2D
@onready var tile_group = get_tree().get_first_node_in_group("Tile_Group")
var mask_viewport: SubViewport
var mask_texture: ViewportTexture
var is_queued_for_update := false
var camera: Camera2D
var last_camera_position := Vector2.ZERO
var last_camera_offset := Vector2.ZERO # 新增:跟踪相机偏移量
class MaskRenderer extends Node2D:
var is_queued_for_update := false
func _draw():
var tile_group = get_tree().get_first_node_in_group("Tile_Group")
if not tile_group or tile_group.tilemaplayers.is_empty():
return
var reference_layer = tile_group.tilemaplayers[0]
for info in tile_group.mask_tile_info:
var base_pos = reference_layer.map_to_local(info.position)
for shape in info.shapes:
match shape.type:
"polygon":
var transformed_points = PackedVector2Array()
for point in shape.points:
transformed_points.append(base_pos + point)
draw_colored_polygon(transformed_points, Color.WHITE)
"rect":
var pos = base_pos - shape.size/2
var rect = Rect2(pos, shape.size)
draw_rect(rect, Color.WHITE, true)
func queue_update():
if not is_queued_for_update:
is_queued_for_update = true
RenderingServer.frame_post_draw.connect(_on_frame_post_draw, CONNECT_ONE_SHOT)
func _on_frame_post_draw():
is_queued_for_update = false
queue_redraw()
func _ready():
# 设置 SubViewport
_setup_viewport()
# 设置着色器
_setup_shader()
# 订阅信号
tile_group.mask_tiles_updated.connect(_on_mask_tiles_updated)
# 寻找并跟踪相机
_find_and_track_camera()
await RenderingServer.frame_post_draw
_update_viewport_for_camera()
material.set_shader_parameter("mask_texture", mask_viewport.get_texture())
func _setup_viewport():
mask_viewport = SubViewport.new()
mask_viewport.transparent_bg = true
mask_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
add_child(mask_viewport)
var mask_renderer = MaskRenderer.new()
mask_viewport.add_child(mask_renderer)
func _setup_shader():
var shader_material = ShaderMaterial.new()
shader_material.shader = preload("res://Char/Char_Components/Blood/blood_mask.gdshader")
material = shader_material
func _find_and_track_camera():
# 寻找场景中的相机
var level = get_tree().get_first_node_in_group("Level")
if level:
camera = level.get_node_or_null("Player/Camera2D")
if camera:
last_camera_position = camera.get_screen_center_position()
func _process(_delta):
if not camera:
return
var current_pos = camera.get_screen_center_position()
var current_offset = camera.offset
# 检查相机位置或偏移量是否发生变化
if current_pos != last_camera_position or current_offset != last_camera_offset:
last_camera_position = current_pos
last_camera_offset = current_offset
_update_viewport_for_camera()
func _update_viewport_for_camera():
if not camera:
return
# 获取相机的视口大小和缩放
var viewport_rect = get_viewport_rect()
var zoom = camera.zoom
var screen_size = viewport_rect.size
# 计算实际需要的视口大小(考虑缩放)
var actual_size = screen_size / zoom
# 更新 SubViewport 大小
mask_viewport.size = actual_size
# 获取相机的全局位置和偏移量
var camera_global_pos = camera.get_screen_center_position()
var camera_offset = camera.offset
# 计算实际的相机中心位置(考虑偏移量)
var effective_camera_center = camera_global_pos + camera_offset * zoom
# 计算视口的左上角位置
var top_left = effective_camera_center - (actual_size / 2)
# 更新 MaskRenderer 的位置以对齐相机
if mask_viewport.get_child(0) is MaskRenderer:
var mask_renderer = mask_viewport.get_child(0)
mask_renderer.position = -top_left
# 触发一次更新
_update_mask()
func _update_mask():
if mask_viewport and mask_viewport.get_child(0) is MaskRenderer:
var mask_renderer = mask_viewport.get_child(0) as MaskRenderer
mask_renderer.queue_update()
func _on_mask_tiles_updated():
if not is_queued_for_update:
is_queued_for_update = true
RenderingServer.frame_post_draw.connect(_update_mask_deferred, CONNECT_ONE_SHOT)
func _update_mask_deferred():
is_queued_for_update = false
_update_mask()
func cleanup():
if tile_group and tile_group.mask_tiles_updated.is_connected(_on_mask_tiles_updated):
tile_group.mask_tiles_updated.disconnect(_on_mask_tiles_updated)
func _exit_tree():
cleanup()

View File

@ -0,0 +1 @@
uid://dxm1qly14lxs8

View File

@ -0,0 +1,16 @@
[gd_scene load_steps=5 format=3 uid="uid://cqvw1nk6yco4e"]
[ext_resource type="Texture2D" uid="uid://1e5r5c6bsoo" path="res://Char/Char_Components/Blood/Art/blood_stain_2.png" id="1_ed4nt"]
[ext_resource type="Shader" uid="uid://ft0ftw3xf13d" path="res://Char/Char_Components/Blood/blood_mask.gdshader" id="1_mxfgm"]
[ext_resource type="Script" uid="uid://dxm1qly14lxs8" path="res://Char/Char_Components/Blood/blood_stain.gd" id="2_bsbek"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_qkvmt"]
shader = ExtResource("1_mxfgm")
[node name="Blood_Stain_Trail" type="Sprite2D"]
material = SubResource("ShaderMaterial_qkvmt")
position = Vector2(0, 1)
texture = ExtResource("1_ed4nt")
region_enabled = true
region_rect = Rect2(6, 12, 30, 12)
script = ExtResource("2_bsbek")

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://mgg5rhiwrtfv"
path="res://.godot/imported/spr_dustcloud_0.png-cf721bc582f42b0b8e0bca3a856efe6a.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_0.png"
dest_files=["res://.godot/imported/spr_dustcloud_0.png-cf721bc582f42b0b8e0bca3a856efe6a.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ldao777f1qy"
path="res://.godot/imported/spr_dustcloud_1.png-f0f610d743fbc2cfbf0c3929609c2a42.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_1.png"
dest_files=["res://.godot/imported/spr_dustcloud_1.png-f0f610d743fbc2cfbf0c3929609c2a42.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dwdp4kv4d755p"
path="res://.godot/imported/spr_dustcloud_2.png-e04b8801496146bb4a2e2decf55e2ae5.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_2.png"
dest_files=["res://.godot/imported/spr_dustcloud_2.png-e04b8801496146bb4a2e2decf55e2ae5.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://biteusit4sfay"
path="res://.godot/imported/spr_dustcloud_3.png-8bc1b91b162b276106bad5efb9712c65.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_3.png"
dest_files=["res://.godot/imported/spr_dustcloud_3.png-8bc1b91b162b276106bad5efb9712c65.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://u18w5owa3bf3"
path="res://.godot/imported/spr_dustcloud_4.png-669cecba10ce98f3d7c8f9b93f9d2a8b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_4.png"
dest_files=["res://.godot/imported/spr_dustcloud_4.png-669cecba10ce98f3d7c8f9b93f9d2a8b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://spc3qs84aqyq"
path="res://.godot/imported/spr_dustcloud_5.png-4995857e45ed75a3c63401d3cb45d441.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_5.png"
dest_files=["res://.godot/imported/spr_dustcloud_5.png-4995857e45ed75a3c63401d3cb45d441.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d254kptg1uq2w"
path="res://.godot/imported/spr_dustcloud_6.png-9d0bb8000eea446aef8fb8c90488fafb.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_6.png"
dest_files=["res://.godot/imported/spr_dustcloud_6.png-9d0bb8000eea446aef8fb8c90488fafb.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dy02ipw3ha3ru"
path="res://.godot/imported/spr_jumpcloud_0.png-92c1688a67cf151cc937fc82c77657d9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_0.png"
dest_files=["res://.godot/imported/spr_jumpcloud_0.png-92c1688a67cf151cc937fc82c77657d9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c80dr8q21xva0"
path="res://.godot/imported/spr_jumpcloud_1.png-9961f2d78357fc38465ad572d734e6bf.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_1.png"
dest_files=["res://.godot/imported/spr_jumpcloud_1.png-9961f2d78357fc38465ad572d734e6bf.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://du12drqa16gwq"
path="res://.godot/imported/spr_jumpcloud_2.png-01e4e3192fef7c8254f57435c46e6e7c.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_2.png"
dest_files=["res://.godot/imported/spr_jumpcloud_2.png-01e4e3192fef7c8254f57435c46e6e7c.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://by1ow45esdky3"
path="res://.godot/imported/spr_jumpcloud_3.png-9e5a9c6f02e97250fbdd84962e5e98dd.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_3.png"
dest_files=["res://.godot/imported/spr_jumpcloud_3.png-9e5a9c6f02e97250fbdd84962e5e98dd.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

@ -0,0 +1,304 @@
[gd_scene load_steps=11 format=3 uid="uid://ciaxr6undqtgm"]
[ext_resource type="Texture2D" uid="uid://mgg5rhiwrtfv" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_0.png" id="1_8ruvd"]
[ext_resource type="Texture2D" uid="uid://ldao777f1qy" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_1.png" id="2_cooot"]
[ext_resource type="Texture2D" uid="uid://dwdp4kv4d755p" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_2.png" id="3_60cn2"]
[ext_resource type="Texture2D" uid="uid://biteusit4sfay" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_3.png" id="4_fr2oo"]
[ext_resource type="Texture2D" uid="uid://u18w5owa3bf3" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_4.png" id="5_ia5nt"]
[ext_resource type="Texture2D" uid="uid://spc3qs84aqyq" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_5.png" id="6_d302j"]
[ext_resource type="Texture2D" uid="uid://d254kptg1uq2w" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_dustcloud_6.png" id="7_ma365"]
[sub_resource type="Animation" id="Animation_uehnd"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_cooot")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:self_modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath(".:position")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(-3, -1)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("../AnimationPlayer:speed_scale")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [1.0]
}
tracks/4/type = "value"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("../Sprite2D_2:self_modulate")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 1)]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("../Sprite2D_2:texture")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("1_8ruvd")]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("../Sprite2D_2:position")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(5, -1)]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("../Sprite2D_3:self_modulate")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Color(1, 1, 1, 0)]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("../Sprite2D_3:texture")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("2_cooot")]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("../Sprite2D_3:position")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(-2, -1)]
}
[sub_resource type="Animation" id="Animation_jjwqk"]
resource_name = "floor_dust"
length = 0.9
step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("1_8ruvd"), ExtResource("2_cooot"), ExtResource("3_60cn2"), ExtResource("4_fr2oo"), ExtResource("5_ia5nt"), ExtResource("6_d302j"), ExtResource("7_ma365")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath(".:self_modulate")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.1, 0.4, 0.9),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath(".:position")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.9),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Vector2(0, 0), Vector2(-33, -2), Vector2(-46, -12), Vector2(-53, -14)]
}
tracks/3/type = "value"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath("../AnimationPlayer:speed_scale")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [2.0]
}
tracks/4/type = "method"
tracks/4/imported = false
tracks/4/enabled = true
tracks/4/path = NodePath("..")
tracks/4/interp = 1
tracks/4/loop_wrap = true
tracks/4/keys = {
"times": PackedFloat32Array(0.9),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"queue_free"
}]
}
tracks/5/type = "value"
tracks/5/imported = false
tracks/5/enabled = true
tracks/5/path = NodePath("../Sprite2D_2:texture")
tracks/5/interp = 1
tracks/5/loop_wrap = true
tracks/5/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("1_8ruvd"), ExtResource("2_cooot"), ExtResource("3_60cn2"), ExtResource("4_fr2oo"), ExtResource("5_ia5nt"), ExtResource("6_d302j"), ExtResource("7_ma365")]
}
tracks/6/type = "value"
tracks/6/imported = false
tracks/6/enabled = true
tracks/6/path = NodePath("../Sprite2D_2:self_modulate")
tracks/6/interp = 1
tracks/6/loop_wrap = true
tracks/6/keys = {
"times": PackedFloat32Array(0, 0.1, 0.4, 0.7),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
tracks/7/type = "value"
tracks/7/imported = false
tracks/7/enabled = true
tracks/7/path = NodePath("../Sprite2D_2:position")
tracks/7/interp = 1
tracks/7/loop_wrap = true
tracks/7/keys = {
"times": PackedFloat32Array(0, 0.2, 0.5, 0.7),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Vector2(5, 0), Vector2(5, 2), Vector2(5, -6), Vector2(5, -9)]
}
tracks/8/type = "value"
tracks/8/imported = false
tracks/8/enabled = true
tracks/8/path = NodePath("../Sprite2D_3:texture")
tracks/8/interp = 1
tracks/8/loop_wrap = true
tracks/8/keys = {
"times": PackedFloat32Array(0, 0.1, 0.3, 0.4, 0.5, 0.6, 0.7),
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1, 1),
"update": 1,
"values": [ExtResource("1_8ruvd"), ExtResource("2_cooot"), ExtResource("3_60cn2"), ExtResource("4_fr2oo"), ExtResource("5_ia5nt"), ExtResource("6_d302j"), ExtResource("7_ma365")]
}
tracks/9/type = "value"
tracks/9/imported = false
tracks/9/enabled = true
tracks/9/path = NodePath("../Sprite2D_3:self_modulate")
tracks/9/interp = 1
tracks/9/loop_wrap = true
tracks/9/keys = {
"times": PackedFloat32Array(0, 0.1, 0.6, 0.9),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
}
tracks/10/type = "value"
tracks/10/imported = false
tracks/10/enabled = true
tracks/10/path = NodePath("../Sprite2D_3:position")
tracks/10/interp = 1
tracks/10/loop_wrap = true
tracks/10/keys = {
"times": PackedFloat32Array(0, 0.2, 0.5, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 0,
"values": [Vector2(19, 0), Vector2(22, -2), Vector2(23, -10), Vector2(22, -13)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_5tpx7"]
_data = {
&"RESET": SubResource("Animation_uehnd"),
&"floor_dust": SubResource("Animation_jjwqk")
}
[node name="floor_dust" type="Node2D" groups=["FX"]]
z_index = 2
[node name="Sprite2D_1" type="Sprite2D" parent="."]
self_modulate = Color(1, 1, 1, 0)
position = Vector2(-3, -1)
texture = ExtResource("2_cooot")
offset = Vector2(0, 3)
[node name="Sprite2D_2" type="Sprite2D" parent="."]
position = Vector2(5, -1)
texture = ExtResource("1_8ruvd")
offset = Vector2(0, 3)
[node name="Sprite2D_3" type="Sprite2D" parent="."]
self_modulate = Color(1, 1, 1, 0)
position = Vector2(-2, -1)
texture = ExtResource("2_cooot")
offset = Vector2(0, 3)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
root_node = NodePath("../Sprite2D_1")
libraries = {
"": SubResource("AnimationLibrary_5tpx7")
}
autoplay = "floor_dust"

View File

@ -0,0 +1,109 @@
[gd_scene load_steps=8 format=3 uid="uid://dnm32l0ymread"]
[ext_resource type="Texture2D" uid="uid://by1ow45esdky3" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_3.png" id="1_bgkyd"]
[ext_resource type="Texture2D" uid="uid://dy02ipw3ha3ru" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_0.png" id="2_um0fq"]
[ext_resource type="Texture2D" uid="uid://c80dr8q21xva0" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_1.png" id="3_vushu"]
[ext_resource type="Texture2D" uid="uid://du12drqa16gwq" path="res://Char/Char_Components/Floor_Wall_FX/Art/spr_jumpcloud_2.png" id="4_mhn4l"]
[sub_resource type="Animation" id="Animation_io5gk"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 1,
"values": [ExtResource("3_vushu")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(-3, 0)]
}
[sub_resource type="Animation" id="Animation_n5fpk"]
resource_name = "wall_jump_dust"
length = 0.4
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Sprite2D:texture")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.1, 0.2, 0.3),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [ExtResource("2_um0fq"), ExtResource("3_vushu"), ExtResource("4_mhn4l"), ExtResource("1_bgkyd")]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Sprite2D:position")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Vector2(-3, 0)]
}
tracks/2/type = "value"
tracks/2/imported = false
tracks/2/enabled = true
tracks/2/path = NodePath("AnimationPlayer:speed_scale")
tracks/2/interp = 1
tracks/2/loop_wrap = true
tracks/2/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [2.0]
}
tracks/3/type = "method"
tracks/3/imported = false
tracks/3/enabled = true
tracks/3/path = NodePath(".")
tracks/3/interp = 1
tracks/3/loop_wrap = true
tracks/3/keys = {
"times": PackedFloat32Array(0.4),
"transitions": PackedFloat32Array(1),
"values": [{
"args": [],
"method": &"queue_free"
}]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_clrdw"]
_data = {
&"RESET": SubResource("Animation_io5gk"),
&"wall_jump_dust": SubResource("Animation_n5fpk")
}
[node name="wall_jump_dust" type="Node2D" groups=["FX"]]
z_index = 2
[node name="Sprite2D" type="Sprite2D" parent="."]
position = Vector2(-3, 0)
rotation = -1.5708
texture = ExtResource("3_vushu")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
"": SubResource("AnimationLibrary_clrdw")
}
autoplay = "wall_jump_dust"
speed_scale = 2.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c2ncysl2v71nn"
path="res://.godot/imported/Sakura.png-f3726873e9009fc93cd029d0af4dc755.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Char/Char_Components/Petals_Leaves/Sakura.png"
dest_files=["res://.godot/imported/Sakura.png-f3726873e9009fc93cd029d0af4dc755.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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

@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://dkgg53dn8lr3k"]
[ext_resource type="Script" uid="uid://ra8s8ac2gvb0" path="res://Char/Char_Components/Petals_Leaves/sakura_component.gd" id="1_qmr48"]
[node name="Sakura_Component" type="Node"]
script = ExtResource("1_qmr48")

View File

@ -0,0 +1,64 @@
[gd_scene load_steps=6 format=3 uid="uid://dkdigqo1emefi"]
[ext_resource type="Script" uid="uid://bdhb15mqnjfg2" path="res://Char/Char_Components/Petals_Leaves/sakura_fall.gd" id="2_2mj48"]
[ext_resource type="Texture2D" uid="uid://c2ncysl2v71nn" path="res://Char/Char_Components/Petals_Leaves/Sakura.png" id="2_4qm7o"]
[sub_resource type="Animation" id="Animation_cppck"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:region_rect")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [Rect2(0, 0, 6, 6)]
}
[sub_resource type="Animation" id="Animation_630tj"]
resource_name = "move"
length = 0.6
loop_mode = 2
step = 0.1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:region_rect")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.2, 0.4, 0.6),
"transitions": PackedFloat32Array(1, 1, 1, 1),
"update": 1,
"values": [Rect2(0, 0, 6, 6), Rect2(6, 0, 6, 6), Rect2(12, 0, 6, 6), Rect2(18, 0, 6, 6)]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_hi3eq"]
_data = {
&"RESET": SubResource("Animation_cppck"),
&"move": SubResource("Animation_630tj")
}
[node name="Sakura_Fall" type="Node2D"]
z_index = 3
script = ExtResource("2_2mj48")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("2_4qm7o")
region_enabled = true
region_rect = Rect2(0, 0, 6, 6)
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
root_node = NodePath("../Sprite2D")
libraries = {
"": SubResource("AnimationLibrary_hi3eq")
}
autoplay = "move"
[node name="RayCast2D" type="RayCast2D" parent="."]
target_position = Vector2(0, 3)
collision_mask = 23592960
hit_from_inside = true

View File

@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=3 uid="uid://bg1ufqdro4aie"]
[ext_resource type="Script" uid="uid://bwknlix5qpg3i" path="res://Char/Char_Components/Petals_Leaves/sakura_impulse.gd" id="1_s7d1x"]
[ext_resource type="Texture2D" uid="uid://c2ncysl2v71nn" path="res://Char/Char_Components/Petals_Leaves/Sakura.png" id="1_vlpkf"]
[node name="Sakura_Impulse" type="Node2D"]
z_index = 3
script = ExtResource("1_s7d1x")
[node name="Sprite2D" type="Sprite2D" parent="."]
scale = Vector2(0.6, 0.6)
texture = ExtResource("1_vlpkf")
region_enabled = true
region_rect = Rect2(6, 0, 6, 6)

View File

@ -0,0 +1,62 @@
extends Node
const sakura_impulse = preload("res://Char/Char_Components/Petals_Leaves/Sakura_Impulse.tscn")
const sakura_fall = preload("res://Char/Char_Components/Petals_Leaves/Sakura_Fall.tscn")
# 距离线的最大偏移距离
var max_offset: float = 60.0
# 生成一批樱花
func spawn_sakura_impulse(start_position: Vector2, end_position: Vector2, batch_size: int = 20):
if not sakura_impulse:
return
for i in batch_size:
var sakura = sakura_impulse.instantiate()
# 计算线段上的随机点
var t = randf()
var line_point = start_position.lerp(end_position, t)
# 计算线段的垂直方向(始终保持向上)
var line_direction = (end_position - start_position).normalized()
var perpendicular = Vector2(-line_direction.y, line_direction.x)
# 确保垂直向量始终指向上方
if perpendicular.y > 0:
perpendicular = -perpendicular
# 在垂直方向上随机偏移
var offset = randf_range(-max_offset, max_offset)
var final_position = line_point + (perpendicular * offset)
sakura.position = final_position
var random_dir = Vector2(randf_range(-1,1), randf_range(-1,1))
var random_speed = randf_range(10,30)
sakura.initialize(random_dir, random_speed)
get_tree().get_first_node_in_group("Effect_Group").add_child(sakura)
func spawn_sakura_fall(start_position: Vector2, end_position: Vector2, batch_size: int = 20):
if not sakura_fall:
return
for i in batch_size:
var sakura = sakura_fall.instantiate()
# 计算线段上的随机点
var t = randf()
var line_point = start_position.lerp(end_position, t)
# 计算线段的垂直方向(始终保持向上)
var line_direction = (end_position - start_position).normalized()
var perpendicular = Vector2(-line_direction.y, line_direction.x)
# 确保垂直向量始终指向上方
if perpendicular.y > 0:
perpendicular = -perpendicular
# 在垂直方向上随机偏移
var offset = randf_range(0, max_offset)
var final_position = line_point + (perpendicular * offset)
sakura.position = final_position
get_tree().get_first_node_in_group("Effect_Group").add_child(sakura)

View File

@ -0,0 +1 @@
uid://ra8s8ac2gvb0

Some files were not shown because too many files have changed in this diff Show More