diff --git a/DungeonShooting_Godot/prefab/effect/weapon/BulletDisappear.tscn b/DungeonShooting_Godot/prefab/effect/weapon/BulletDisappear.tscn
index 54549a1..6572e0c 100644
--- a/DungeonShooting_Godot/prefab/effect/weapon/BulletDisappear.tscn
+++ b/DungeonShooting_Godot/prefab/effect/weapon/BulletDisappear.tscn
@@ -1,8 +1,8 @@
-[gd_scene load_steps=15 format=3]
+[gd_scene load_steps=13 format=3 uid="uid://c6mmikwchwt"]
[ext_resource type="Texture2D" uid="uid://d8ot2wrdoe4j" path="res://resource/sprite/effects/Explosion.png" id="1_qqm6c"]
-[ext_resource type="Texture2D" uid="uid://h7hkgbwj1li" path="res://resource/sprite/effects/Smoke.png" id="1_ybsvf"]
-
+[ext_resource type="Texture2D" uid="uid://h7hkgbwj1li" path="res://resource/sprite/effects/common/Smoke.png" id="1_ybsvf"]
+[ext_resource type="Script" path="res://src/game/effects/AutoDestroySprite.cs" id="2_l2qlq"]
[sub_resource type="AtlasTexture" id="AtlasTexture_tscb3"]
atlas = ExtResource("1_qqm6c")
@@ -69,63 +69,15 @@
color = Color(0.909804, 0.909804, 0.909804, 0.380392)
anim_offset_max = 1.0
-[sub_resource type="Animation" id="Animation_jnfgg"]
-resource_name = "Start"
-length = 0.3
-tracks/0/type = "value"
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/path = NodePath(".:emitting")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/keys = {
-"times": PackedFloat32Array(0),
-"transitions": PackedFloat32Array(1),
-"update": 1,
-"values": [true]
-}
-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.3),
-"transitions": PackedFloat32Array(1),
-"values": [{
-"args": [],
-"method": &"queue_free"
-}]
-}
-
-[sub_resource type="Animation" id="Animation_yr61b"]
-length = 0.001
-tracks/0/type = "value"
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/path = NodePath(".:emitting")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/keys = {
-"times": PackedFloat32Array(0),
-"transitions": PackedFloat32Array(1),
-"update": 1,
-"values": [false]
-}
-
-[sub_resource type="AnimationLibrary" id="AnimationLibrary_1spnw"]
-_data = {
-"RESET": SubResource("Animation_yr61b"),
-"Start": SubResource("Animation_jnfgg")
-}
-
-[node name="BulletDisappear" type="AnimatedSprite2D"]
+[node name="BulletDisappear" type="AnimatedSprite2D" node_paths=PackedStringArray("Particles2D")]
modulate = Color(1, 1, 1, 0.784314)
z_index = -4
scale = Vector2(0.5, 0.5)
sprite_frames = SubResource("SpriteFrames_ub3cw")
autoplay = "default"
+script = ExtResource("2_l2qlq")
+DelayTime = 0.3
+Particles2D = [NodePath("GPUParticles2D")]
[node name="GPUParticles2D" type="GPUParticles2D" parent="."]
material = SubResource("CanvasItemMaterial_4bd3q")
@@ -136,10 +88,3 @@
one_shot = true
explosiveness = 0.9
fixed_fps = 20
-
-[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
-root_node = NodePath("../GPUParticles2D")
-autoplay = "Start"
-libraries = {
-"": SubResource("AnimationLibrary_1spnw")
-}
diff --git a/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs
index 0794389..b57041b 100644
--- a/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs
+++ b/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs
@@ -13,6 +13,15 @@
public Area2D CollisionArea { get; set; }
///
+ /// 攻击的层级
+ ///
+ public uint AttackLayer
+ {
+ get => CollisionArea.CollisionMask;
+ set => CollisionArea.CollisionMask = value;
+ }
+
+ ///
/// 发射该子弹的武器
///
public Weapon Weapon { get; private set; }
@@ -55,7 +64,7 @@
{
Weapon = weapon;
Role = weapon.Master;
- CollisionArea.CollisionMask = targetLayer;
+ AttackLayer = targetLayer;
CollisionArea.AreaEntered += OnArea2dEntered;
//只有玩家使用该武器才能获得正常速度的子弹
@@ -81,6 +90,17 @@
// }
}
+ ///
+ /// 播放子弹消失的特效
+ ///
+ public virtual void PlayDisappearEffect()
+ {
+ var packedScene = ResourceManager.Load(ResourcePath.prefab_effect_weapon_BulletDisappear_tscn);
+ var node = packedScene.Instantiate();
+ node.GlobalPosition = GlobalPosition;
+ node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
+ }
+
protected override void PhysicsProcessOver(float delta)
{
//移动
@@ -102,15 +122,11 @@
CurrFlyDistance += FlySpeed * delta;
if (CurrFlyDistance >= MaxDistance)
{
- var packedScene = ResourceManager.Load(ResourcePath.prefab_effect_weapon_BulletDisappear_tscn);
- var node = packedScene.Instantiate();
- node.GlobalPosition = GlobalPosition;
- node.AddToActivityRoot(RoomLayerEnum.YSortLayer);
-
+ PlayDisappearEffect();
Destroy();
}
}
-
+
private void OnArea2dEntered(Area2D other)
{
var role = other.AsActivityObject();
diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs
index c37cd51..0f52874 100644
--- a/DungeonShooting_Godot/src/game/activity/role/Role.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs
@@ -1117,7 +1117,7 @@
MeleeAttackAngle,
6
);
- MeleeAttackArea.CollisionMask = AttackLayer;
+ MeleeAttackArea.CollisionMask = AttackLayer | PhysicsLayer.Bullet;
}
}
@@ -1134,12 +1134,21 @@
var activityObject = body.AsActivityObject();
if (activityObject != null)
{
- if (activityObject is Role role)
+ if (activityObject is Role role) //攻击角色
{
var damage = Utils.Random.RandomConfigRange(activeWeapon.Attribute.MeleeAttackHarmRange);
damage = RoleState.CallCalcDamageEvent(damage);
role.CallDeferred(nameof(Hurt), damage, (role.GetCenterPosition() - GlobalPosition).Angle());
}
+ else if (activityObject is Bullet bullet) //攻击子弹
+ {
+ var attackLayer = bullet.AttackLayer;
+ if (CollisionWithMask(attackLayer)) //是攻击玩家的子弹
+ {
+ bullet.PlayDisappearEffect();
+ bullet.Destroy();
+ }
+ }
}
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs b/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs
index 977c5ef..8de62e5 100644
--- a/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/Role_Animation.cs
@@ -19,9 +19,9 @@
var tween = CreateTween();
tween.SetParallel();
- tween.TweenProperty(MountPoint, "rotation_degrees", r - MeleeAttackAngle / 2f, 0.12);
- tween.TweenProperty(MountPoint, "position", p2, 0.12);
- tween.TweenProperty(MountPoint, "position", p2, 0.12);
+ tween.TweenProperty(MountPoint, "rotation_degrees", r - MeleeAttackAngle / 2f, 0.1);
+ tween.TweenProperty(MountPoint, "position", p2, 0.1);
+ tween.TweenProperty(MountPoint, "position", p2, 0.1);
tween.Chain();
tween.TweenCallback(Callable.From(() =>
diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
index 0cc4c41..abc4a4d 100644
--- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
+++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
@@ -135,6 +135,11 @@
///
public bool IsAutoPlaySpriteFrames { get; set; } = true;
+ ///
+ /// 在没有所属 Master 的时候是否可以触发扳机
+ ///
+ public bool NoMasterCanTrigger { get; set; } = true;
+
//--------------------------------------------------------------------------------------------
//触发按下扳机的角色
@@ -663,6 +668,9 @@
/// 按下扳机的角色, 如果传 null, 则视为走火
public void Trigger(Role trigger)
{
+ //不能触发扳机
+ if (!NoMasterCanTrigger && Master == null) return;
+
//这一帧已经按过了, 不需要再按下
if (_triggerFlag) return;
diff --git a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs
index 5c6f5ed..f8d56f1 100644
--- a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs
+++ b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs
@@ -26,7 +26,9 @@
public override void OnInit()
{
base.OnInit();
-
+
+ //没有Master时不能触发开火
+ NoMasterCanTrigger = false;
_hitArea = GetNode("HitArea");
_collisionPolygon = new CollisionPolygon2D();
var a = Mathf.Abs(-BeginChargeAngle + Attribute.UpliftAngle);
@@ -72,7 +74,7 @@
{
GD.Print("近战武器攻击! 蓄力时长: " + GetTriggerChargeTime() + ", 扳机按下时长: " + GetTriggerDownTime());
//更新碰撞层级
- _hitArea.CollisionMask = GetAttackLayer();
+ _hitArea.CollisionMask = GetAttackLayer() | PhysicsLayer.Bullet;
//启用碰撞
_hitArea.Monitoring = true;
_attackIndex = 0;
@@ -125,7 +127,7 @@
var activityObject = body.AsActivityObject();
if (activityObject != null)
{
- if (activityObject is Role role)
+ if (activityObject is Role role) //碰到角色
{
var damage = Utils.Random.RandomConfigRange(Attribute.HarmRange);
if (Master != null)
@@ -135,6 +137,17 @@
role.CallDeferred(nameof(Role.Hurt), damage, (role.GetCenterPosition() - GlobalPosition).Angle());
}
+ else if (activityObject is Bullet bullet) //攻击子弹
+ {
+ var attackLayer = bullet.AttackLayer;
+ if (Master.CollisionWithMask(attackLayer)) //是攻击玩家的子弹
+ {
+ bullet.PlayDisappearEffect();
+ bullet.BasisVelocity = bullet.BasisVelocity.Rotated(Mathf.Pi);
+ bullet.Rotation += Mathf.Pi;
+ bullet.AttackLayer = Master.AttackLayer;
+ }
+ }
}
}
}
diff --git a/DungeonShooting_Godot/src/game/effects/AutoDestroySprite.cs b/DungeonShooting_Godot/src/game/effects/AutoDestroySprite.cs
index 857819d..a24db0c 100644
--- a/DungeonShooting_Godot/src/game/effects/AutoDestroySprite.cs
+++ b/DungeonShooting_Godot/src/game/effects/AutoDestroySprite.cs
@@ -1,4 +1,5 @@
using Godot;
+using Godot.Collections;
///
/// 到期自动销毁的帧动画
@@ -11,9 +12,22 @@
[Export]
public float DelayTime { get; set; } = 1f;
+ ///
+ /// 子节点包含的例子特效, 在创建完成后自动播放
+ ///
+ [Export]
+ public Array Particles2D { get; set; }
+
public override async void _Ready()
{
var sceneTreeTimer = GetTree().CreateTimer(DelayTime);
+ if (Particles2D != null)
+ {
+ foreach (var gpuParticles2D in Particles2D)
+ {
+ gpuParticles2D.Emitting = true;
+ }
+ }
await ToSignal(sceneTreeTimer, Timer.SignalName.Timeout);
QueueFree();
}