diff --git a/DungeonShooting_Godot/src/framework/common/Utils.cs b/DungeonShooting_Godot/src/framework/common/Utils.cs
index 7c58641..b102450 100644
--- a/DungeonShooting_Godot/src/framework/common/Utils.cs
+++ b/DungeonShooting_Godot/src/framework/common/Utils.cs
@@ -290,4 +290,20 @@
return isInside;
}
+
+ ///
+ /// 根据法线翻转向量
+ ///
+ public static Vector2 ReflectByNormal(Vector2 vector, Vector2 normal)
+ {
+ return vector.Reflect(normal.Rotated(Mathf.Pi * 0.5f));
+ }
+
+ ///
+ /// 根据法线翻转角度, 弧度制
+ ///
+ public static float ReflectByNormal(float rotation, Vector2 normal)
+ {
+ return ReflectByNormal(Vector2.FromAngle(rotation), normal).Angle();
+ }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs
index 20db6e4..56735dd 100644
--- a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs
+++ b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs
@@ -10,6 +10,11 @@
public partial class Laser : Area2D, IBullet
{
///
+ /// 激光默认宽度
+ ///
+ public const float LaserDefaultWidth = 3f;
+
+ ///
/// 子节点包含的例子特效, 在创建完成后自动播放
///
[Export]
@@ -46,7 +51,7 @@
public void InitData(BulletData data, uint attackLayer)
{
- InitData(data, attackLayer, 5);
+ InitData(data, attackLayer, LaserDefaultWidth);
}
public void InitData(BulletData data, uint attackLayer, float width)
@@ -75,11 +80,17 @@
var parameters = PhysicsRayQueryParameters2D.Create(data.Position, targetPosition, PhysicsLayer.Wall);
var result = GetWorld2D().DirectSpaceState.IntersectRay(parameters);
float distance;
- if (result != null && result.TryGetValue("position", out var point))
+ var doRebound = false; //是否需要执行反弹
+ Vector2? reboundPosition = null;
+ Vector2? reboundNormal = null;
+ if (result != null && result.TryGetValue("position", out var point)) //撞到墙壁
{
- distance = Position.DistanceTo((Vector2)point);
+ doRebound = true;
+ reboundPosition = (Vector2)point;
+ reboundNormal = (Vector2)result["normal"];
+ distance = Position.DistanceTo(reboundPosition.Value);
}
- else
+ else //没撞到墙壁
{
distance = data.MaxDistance;
}
@@ -113,6 +124,11 @@
// tween.Chain();
_tween.TweenCallback(Callable.From(() =>
{
+ //执行反弹
+ if (doRebound)
+ {
+ OnRebound(reboundPosition.Value, reboundNormal.Value);
+ }
Collision.SetDeferred(CollisionShape2D.PropertyName.Disabled, false);
}));
_tween.Chain();
@@ -148,6 +164,34 @@
QueueFree();
}
+
+ //激光撞墙反弹逻辑
+ private void OnRebound(Vector2 position, Vector2 normal)
+ {
+ if (BulletData.BounceCount > 0)
+ {
+ var newDistance = BulletData.MaxDistance - BulletData.Position.DistanceTo(position);
+ if (newDistance > 0)
+ {
+ float rotation;
+ if (normal.X == 0 && normal.Y == 0)
+ {
+ rotation = (BulletData.Rotation + Mathf.Pi) % (Mathf.Pi * 2);
+ }
+ else
+ {
+ rotation = Utils.ReflectByNormal(BulletData.Rotation, normal);
+ }
+
+ var bulletData = BulletData.Clone();
+ bulletData.Position = position;
+ bulletData.BounceCount -= 1;
+ bulletData.MaxDistance = newDistance;
+ bulletData.Rotation = rotation;
+ FireManager.ShootBullet(bulletData, AttackLayer);
+ }
+ }
+ }
private void OnArea2dEntered(Area2D other)
{
diff --git a/DungeonShooting_Godot/src/game/manager/FireManager.cs b/DungeonShooting_Godot/src/game/manager/FireManager.cs
index 1a77262..65e7fa8 100644
--- a/DungeonShooting_Godot/src/game/manager/FireManager.cs
+++ b/DungeonShooting_Godot/src/game/manager/FireManager.cs
@@ -78,6 +78,9 @@
return null;
}
+ ///
+ /// 计算进行抛物线运动的子弹击中目标所需要的速度等数据, 并设置
+ ///
public static void SetParabolaTarget(BulletData bulletData, Vector2 targetPosition)
{
var distance = bulletData.Position.DistanceTo(targetPosition);
@@ -161,7 +164,7 @@
//创建激光
var laser = ObjectManager.GetLaser(bulletData.BulletBase.Prefab);
laser.AddToActivityRoot(RoomLayerEnum.YSortLayer);
- laser.InitData(bulletData, attackLayer, 3);
+ laser.InitData(bulletData, attackLayer, Laser.LaserDefaultWidth);
return laser;
}