From 3b2ba7440c06c5047a4a1f5bdc6581ac31483a31 Mon Sep 17 00:00:00 2001 From: Cold-Mint Date: Mon, 12 Aug 2024 22:30:13 +0800 Subject: [PATCH] =?UTF-8?q?Improved=20the=20collision=20logic=20of=20bulle?= =?UTF-8?q?ts.=20=E6=94=B9=E8=BF=9B=E5=AD=90=E5=BC=B9=E7=9A=84=E7=A2=B0?= =?UTF-8?q?=E6=92=9E=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prefab/entitys/Character.tscn | 4 +- prefab/projectile/Catapult.tscn | 12 ++- prefab/projectile/curseOfTheUndead.tscn | 2 +- project.godot | 3 +- scripts/Config.cs | 3 +- scripts/character/CharacterTemplate.cs | 12 ++- scripts/projectile/Projectile.cs | 111 +++++++++++------------- tileSets/dungeon.tres | 15 ++-- 8 files changed, 87 insertions(+), 75 deletions(-) diff --git a/prefab/entitys/Character.tscn b/prefab/entitys/Character.tscn index 60c295b..2dbf806 100644 --- a/prefab/entitys/Character.tscn +++ b/prefab/entitys/Character.tscn @@ -24,7 +24,9 @@ animations = [{ [node name="Player" type="CharacterBody2D"] collision_layer = 4 -collision_mask = 34 +collision_mask = 162 +platform_floor_layers = 4294967042 +platform_wall_layers = 128 script = ExtResource("1_1dlls") MaxHp = 32 CampId = "Default" diff --git a/prefab/projectile/Catapult.tscn b/prefab/projectile/Catapult.tscn index e5f7ee5..7903949 100644 --- a/prefab/projectile/Catapult.tscn +++ b/prefab/projectile/Catapult.tscn @@ -9,16 +9,20 @@ radius = 11.0 [node name="curseOfTheUndead" type="CharacterBody2D"] -collision_layer = 0 -collision_mask = 0 +collision_layer = 16 +collision_mask = 102 +slide_on_ceiling = false +platform_floor_layers = 4294967042 +platform_wall_layers = 32 script = ExtResource("1_ib3qh") Life = 5000 -Durability = 1.0 +Durability = 3.0 MaxDamage = 3 MinDamage = 10 DamageType = 2 KnockbackForce = Vector2(2, -3) -Speed = 500.0 +Speed = 300.0 +EnableBounce = true [node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource("CircleShape2D_dgro2") diff --git a/prefab/projectile/curseOfTheUndead.tscn b/prefab/projectile/curseOfTheUndead.tscn index 36c5bbb..e658bdc 100644 --- a/prefab/projectile/curseOfTheUndead.tscn +++ b/prefab/projectile/curseOfTheUndead.tscn @@ -28,7 +28,7 @@ shape = SubResource("CircleShape2D_dgro2") [node name="CollisionDetectionArea" type="Area2D" parent="."] collision_layer = 16 -collision_mask = 78 +collision_mask = 206 [node name="CollisionShape2D" type="CollisionShape2D" parent="CollisionDetectionArea"] shape = SubResource("CircleShape2D_8117d") diff --git a/project.godot b/project.godot index ec84ba7..97dc7fa 100644 --- a/project.godot +++ b/project.godot @@ -151,12 +151,13 @@ locale/translations=PackedStringArray("res://locals/DeathInfo.en.translation", " [layer_names] 2d_physics/layer_1="RoomArea" -2d_physics/layer_2="Ground" +2d_physics/layer_2="Floor" 2d_physics/layer_3="Player" 2d_physics/layer_4="PickAbleItem" 2d_physics/layer_5="Projectile" 2d_physics/layer_6="Platform" 2d_physics/layer_7="Mob" +2d_physics/layer_8="Wall" [physics] diff --git a/scripts/Config.cs b/scripts/Config.cs index 516705c..5e2c0dd 100644 --- a/scripts/Config.cs +++ b/scripts/Config.cs @@ -425,12 +425,13 @@ public static class Config public static class LayerNumber { public const int RoomArea = 1; - public const int Ground = 2; + public const int Floor = 2; public const int Player = 3; public const int PickAbleItem = 4; public const int Projectile = 5; public const int Platform = 6; public const int Mob = 7; + public const int Wall = 8; } /// diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs index 76485a1..3840a01 100644 --- a/scripts/character/CharacterTemplate.cs +++ b/scripts/character/CharacterTemplate.cs @@ -286,7 +286,6 @@ public partial class CharacterTemplate : CharacterBody2D _healthBar.MaxValue = MaxHp; } - ItemMarker2D = GetNode("ItemMarker2D"); _itemMarkerOriginalX = ItemMarker2D.Position.X; _animatedSprite2D = GetNode("AnimatedSprite2D"); @@ -303,6 +302,11 @@ public partial class CharacterTemplate : CharacterBody2D _pickingArea.BodyEntered += EnterThePickingRangeBody; _pickingArea.BodyExited += ExitThePickingRangeBody; } + + //The character cannot pass through the wall and floor + //角色不能穿过墙壁和地板 + SetCollisionMaskValue(Config.LayerNumber.Wall, true); + SetCollisionMaskValue(Config.LayerNumber.Floor, true); } /// @@ -389,7 +393,8 @@ public partial class CharacterTemplate : CharacterBody2D pickAbleTemplate.Owner = this; pickAbleTemplate.Picked = true; pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, false); - pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, false); + pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Floor, false); + pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Wall, false); LogCat.Log("item_pickup_disables_collision_damage", LogCat.LogLabel.ContactInjury); pickAbleTemplate.EnableContactInjury = false; pickAbleTemplate.Sleeping = true; @@ -759,7 +764,8 @@ public partial class CharacterTemplate : CharacterBody2D //仍出武器时,我们不能立即恢复物理碰撞,立即恢复会导致武器更早的与地面和平台碰撞,阻止武器的飞行。 pickAbleTemplate.EnableContactInjury = true; LogCat.Log("item_thrown_restore_collision_damage", LogCat.LogLabel.ContactInjury); - pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Ground, true); + pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Floor, true); + pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Wall, true); pickAbleTemplate.SetCollisionMaskValue(Config.LayerNumber.Platform, true); timer.QueueFree(); }; diff --git a/scripts/projectile/Projectile.cs b/scripts/projectile/Projectile.cs index 050c73d..d43975f 100644 --- a/scripts/projectile/Projectile.cs +++ b/scripts/projectile/Projectile.cs @@ -19,8 +19,7 @@ public partial class Projectile : CharacterBody2D /// life(ms) /// 子弹的存在时间(毫秒) /// - [Export] - public long Life; + [Export] public long Life; //The durability of the projectile //抛射体的耐久度 @@ -38,13 +37,6 @@ public partial class Projectile : CharacterBody2D /// private DateTime? _destructionTime; - - /// - /// The impact area of the bullet - /// 子弹的碰撞区域 - /// - private Area2D? _area2D; - /// /// knockback /// 击退 @@ -53,11 +45,22 @@ public partial class Projectile : CharacterBody2D ///How much force does it have when hitting the character? Unit: Number of cells,The X direction of the force is inferred automatically. ///当击中角色时带有多大的力?单位:格数,力的X方向是自动推断的。 /// - [Export] - public Vector2 KnockbackForce; + [Export] public Vector2 KnockbackForce; [Export] public float Speed; + /// + /// Whether it bounces back after hitting an enemy or a wall + /// 是否撞到敌人或墙壁后反弹 + /// + [Export] public bool EnableBounce; + + /// + /// Can it penetrate the wall + /// 是否可以穿透墙壁 + /// + [Export] public bool IgnoreWall; + private List? _projectileDecorators; @@ -69,12 +72,6 @@ public partial class Projectile : CharacterBody2D public override void _Ready() { - //The bullet's impact detection area - //子弹的碰撞检测区域 - _area2D = GetNode("CollisionDetectionArea"); - _area2D.Monitoring = true; - _area2D.BodyEntered += OnBodyEnter; - _area2D.BodyExited += OnBodyExited; //If the existence time is less than or equal to 0, then it is set to exist for 10 seconds, and projectiles that exist indefinitely are prohibited //如果存在时间小于等于0,那么设置为存在10秒,禁止无限期存在的抛射体 if (Life <= 0) @@ -83,6 +80,11 @@ public partial class Projectile : CharacterBody2D } _destructionTime = DateTime.Now.AddMilliseconds(Life); + SetCollisionMaskValue(Config.LayerNumber.Wall, !IgnoreWall); + SetCollisionMaskValue(Config.LayerNumber.Floor, !IgnoreWall); + //Platform collision layer is not allowed to collide + //平台碰撞层不可碰撞 + SetCollisionMaskValue(Config.LayerNumber.Platform, false); } /// @@ -140,7 +142,7 @@ public partial class Projectile : CharacterBody2D //撞击到瓦片时,我们返回true,是为了防止子弹穿透瓦片。 return true; } - + if (target is PickAbleTemplate pickAbleTemplate) { //The picked-up item cannot resist the bullet. @@ -247,45 +249,6 @@ public partial class Projectile : CharacterBody2D } } - /// - /// When the bullet is in contact with the node - /// 当子弹与节点接触时 - /// - /// - protected virtual void OnBodyEnter(Node2D node) - { - //Here we test whether harm is allowed, notice that for TileMap, we directly allow harm. - //这里我们检测是否允许造成伤害,注意对于TileMap,我们直接允许造成伤害。 - var canCauseHarm = CanCauseHarm(Owner, node); - if (!canCauseHarm) - { - return; - } - - DoDamage(Owner, node); - //Please specify in the Mask who the bullet will collide with - //请在Mask内配置子弹会和谁碰撞 - //When a bullet hits an object, its durability decreases - //子弹撞击到物体时,耐久度减少 - Durability--; - if (Durability <= 0) - { - //When the durability is less than or equal to 0, destroy the bullet - //当耐久度小于等于0时,销毁子弹 - QueueFree(); - } - } - - /// - /// When the bullet leaves the node - /// 当子弹离开节点时 - /// - /// - protected virtual void OnBodyExited(Node2D node) - { - } - - /// /// When beyond the time of existence /// 当超过存在时间 @@ -307,6 +270,38 @@ public partial class Projectile : CharacterBody2D public override void _PhysicsProcess(double delta) { - MoveAndSlide(); + var collisionInfo = MoveAndCollide(Velocity * (float)delta); + if (collisionInfo != null) + { + //Bump into other objects. + //撞到其他对象。 + if (EnableBounce) + { + Velocity = Velocity.Bounce(collisionInfo.GetNormal()); + } + + //Here we test whether harm is allowed, notice that for TileMap, we directly allow harm. + //这里我们检测是否允许造成伤害,注意对于TileMap,我们直接允许造成伤害。 + var godotObject = collisionInfo.GetCollider(); + var node = (Node2D)godotObject; + var canCauseHarm = CanCauseHarm(Owner, node); + if (!canCauseHarm) + { + return; + } + + DoDamage(Owner, node); + //Please specify in the Mask who the bullet will collide with + //请在Mask内配置子弹会和谁碰撞 + //When a bullet hits an object, its durability decreases + //子弹撞击到物体时,耐久度减少 + Durability--; + if (Durability <= 0) + { + //When the durability is less than or equal to 0, destroy the bullet + //当耐久度小于等于0时,销毁子弹 + QueueFree(); + } + } } } \ No newline at end of file diff --git a/tileSets/dungeon.tres b/tileSets/dungeon.tres index 7739c8b..d792279 100644 --- a/tileSets/dungeon.tres +++ b/tileSets/dungeon.tres @@ -6,14 +6,14 @@ texture = ExtResource("1_4c2am") texture_region_size = Vector2i(32, 32) 0:0/0 = 0 -0:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +0:0/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 1:0/0 = 0 1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 1:1/0 = 0 2:1/0 = 0 -2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +2:1/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 2:2/0 = 0 -2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +2:2/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 3:2/0 = 0 3:4/0 = 0 3:4/0/physics_layer_1/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, -6.75, 8.25, -6, 7, -2.25, 1, -2, -16, 16) @@ -27,17 +27,18 @@ texture_region_size = Vector2i(32, 32) 1:3/0 = 0 1:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 1:2/0 = 0 -1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +1:2/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 0:2/0 = 0 0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +0:2/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 0:1/0 = 0 -0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +0:1/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 2:3/0 = 0 2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 3:1/0 = 0 3:0/0 = 0 2:0/0 = 0 -2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) +2:0/0/physics_layer_2/polygon_0/points = PackedVector2Array(-16, -16, 16, -16, 16, 16, -16, 16) 4:0/0 = 0 4:1/0 = 0 5:0/0 = 0 @@ -86,4 +87,6 @@ physics_layer_0/collision_layer = 2 physics_layer_0/collision_mask = 0 physics_layer_1/collision_layer = 32 physics_layer_1/collision_mask = 0 +physics_layer_2/collision_layer = 128 +physics_layer_2/collision_mask = 0 sources/1 = SubResource("TileSetAtlasSource_abxy2")