From e7603c5c8fd4dd57c0a808a30ba0379c9259781e Mon Sep 17 00:00:00 2001 From: Panxuc Date: Mon, 30 Oct 2023 22:27:30 +0800 Subject: [PATCH] feat: :sparkles: attack & resource --- logic/GameClass/GameObj/Areas/Resource.cs | 42 ++++++++++++ logic/GameClass/GameObj/BombedBullet.cs | 22 +++++++ logic/GameClass/GameObj/Team.cs | 21 +++++- logic/Gaming/ActionManager.cs | 79 +++++++++++++++++++++++ logic/Gaming/AttackManager.cs | 58 ++++++++++++++++- logic/Preparation/Utility/EnumType.cs | 15 ++--- 6 files changed, 227 insertions(+), 10 deletions(-) create mode 100644 logic/GameClass/GameObj/BombedBullet.cs diff --git a/logic/GameClass/GameObj/Areas/Resource.cs b/logic/GameClass/GameObj/Areas/Resource.cs index 5879665d..07c7c96a 100644 --- a/logic/GameClass/GameObj/Areas/Resource.cs +++ b/logic/GameClass/GameObj/Areas/Resource.cs @@ -1,12 +1,54 @@ using Preparation.Utility; using System; +using System.Threading; namespace GameClass.GameObj.Areas; public class Resource : Immovable { + public LongInTheVariableRange HP => throw new NotImplementedException(); public override bool IsRigid => true; public override ShapeType Shape => ShapeType.Square; + private int producingNum = 0; + public int ProducingNum + { + get => Interlocked.CompareExchange(ref producingNum, 0, 0); + } + public void AddProducingNum() + { + Interlocked.Increment(ref producingNum); + } + public void SubProducingNum() + { + Interlocked.Decrement(ref producingNum); + } + public bool Produce(int produceSpeed, Ship ship) + { + long orgHP, value; + lock (gameObjLock) + { + if (HP == 0) + { + return false; + } + orgHP = HP.GetValue(); + HP.SubV(produceSpeed); + if (HP > HP.GetMaxV()) + { + HP.SetV(HP.GetMaxV()); + } + else if (HP < 0) + { + HP.SetV(0); + } + value = HP.GetValue(); + } + if (value < orgHP) + { + if (value == 0) return true; + } + return false; + } public Resource(XY initPos) : base(initPos, GameData.NumOfPosGridPerCell / 2, GameObjType.Resource) { diff --git a/logic/GameClass/GameObj/BombedBullet.cs b/logic/GameClass/GameObj/BombedBullet.cs new file mode 100644 index 00000000..8f3f3270 --- /dev/null +++ b/logic/GameClass/GameObj/BombedBullet.cs @@ -0,0 +1,22 @@ +using Preparation.Utility; + +namespace GameClass.GameObj +{ + // 为方便界面组做子弹爆炸特效,现引入“爆炸中的子弹”,在每帧发送给界面组 + public sealed class BombedBullet : Immovable + { + public override ShapeType Shape => ShapeType.Circle; + public override bool IsRigid => false; + public long MappingID { get; } + public readonly Bullet bulletHasBombed; + public readonly XY facingDirection; + + public BombedBullet(Bullet bullet) : + base(bullet.Position, bullet.Radius, GameObjType.BombedBullet) + { + this.bulletHasBombed = bullet; + this.MappingID = bullet.ID; + this.facingDirection = bullet.FacingDirection; + } + } +} diff --git a/logic/GameClass/GameObj/Team.cs b/logic/GameClass/GameObj/Team.cs index d9a0e0fe..b08385e0 100644 --- a/logic/GameClass/GameObj/Team.cs +++ b/logic/GameClass/GameObj/Team.cs @@ -1,6 +1,7 @@ using GameClass.GameObj.Areas; using Preparation.Utility; using System.Collections.Generic; +using System.Threading; namespace GameClass.GameObj { @@ -16,7 +17,16 @@ public class Team private readonly Dictionary birthPointList; public Dictionary BirthPointList => birthPointList; private Home home; - public int Score { get; private set; } = 0; + private long score = 0; + public long Score + { + get => Interlocked.Read(ref score); + } + private long totalScore; + public long TotalScore + { + get => Interlocked.Read(ref totalScore); + } public Ship? GetShip(long shipID) { foreach (Ship ship in shipList) @@ -48,6 +58,15 @@ public bool AddShip(Ship ship) shipList.Add(ship); return true; } + public void AddScore(long add) + { + Interlocked.Add(ref score, add); + Interlocked.Add(ref totalScore, add); + } + public void SubScore(long sub) + { + Interlocked.Add(ref score, -sub); + } public void SetHome(Home home) { this.home = home; diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 807a1d0d..394b46cd 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -1,6 +1,7 @@ using System; using System.Threading; using GameClass.GameObj; +using GameClass.GameObj.Areas; using GameEngine; using Preparation.Utility; using Protobuf; @@ -13,7 +14,39 @@ public partial class Game private readonly ActionManager actionManager; private class ActionManager { + private readonly Map gameMap; + private readonly ShipManager shipManager; public readonly MoveEngine moveEngine; + public ActionManager(Map gameMap, ShipManager shipManager) + { + this.gameMap = gameMap; + this.shipManager = shipManager; + this.moveEngine = new MoveEngine( + gameMap: gameMap, + OnCollision: (obj, collisionObj, moveVec) => + { + Ship ship = (Ship)obj; + switch (collisionObj.Type) + { + case GameObjType.Bullet: + if (((Bullet)collisionObj).Parent != ship) + { + // TODO + gameMap.Remove((GameObj)collisionObj); + } + break; + default: + break; + } + return MoveEngine.AfterCollision.MoveMax; + }, + EndMove: obj => + { + obj.ThreadNum.Release(); + } + ); + this.shipManager = shipManager; + } public bool MoveShip(Ship shipToMove, int moveTimeInMilliseconds, double moveDirection) { if (moveTimeInMilliseconds < 5) @@ -57,6 +90,52 @@ public static bool Stop(Ship ship) } public bool Produce(Ship ship) { + Resource? resource = (Resource?)gameMap.OneForInteract(ship.Position, GameObjType.Resource); + if (resource == null) + { + return false; + } + if (resource.HP == 0) + { + return false; + } + long stateNum = ship.SetShipState(RunningStateType.Waiting, ShipStateType.Producing); + if (stateNum == -1) + { + return false; + } + new Thread + ( + () => + { + ship.ThreadNum.WaitOne(); + if (!ship.StartThread(stateNum, RunningStateType.RunningActively)) + { + ship.ThreadNum.Release(); + return; + } + resource.AddProducingNum(); + Thread.Sleep(GameData.CheckInterval); + new FrameRateTaskExecutor + ( + loopCondition: () => stateNum == ship.StateNum && gameMap.Timer.IsGaming, + loopToDo: () => + { + if (resource.HP == 0) + { + ship.ResetShipState(stateNum); + return false; + } + return true; + }, + timeInterval: GameData.CheckInterval, + finallyReturn: () => 0 + ).Start(); + ship.ThreadNum.Release(); + resource.SubProducingNum(); + } + ) + { IsBackground = true }.Start(); return false; } public bool Construct(Ship ship) diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 1a0f56f8..fab35347 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -2,13 +2,69 @@ using System.Threading; using System.Collections.Generic; using GameClass.GameObj; +using GameClass.GameObj.Bullets; using Preparation.Utility; using GameEngine; using Preparation.Interface; +using Timothy.FrameRateTask; namespace Gaming { - internal class AttackManager + public partial class Game { + private readonly AttackManager attackManager; + private class AttackManager + { + readonly Map gameMap; + public readonly MoveEngine moveEngine; + readonly ShipManager shipManager; + public AttackManager(Map gameMap, ShipManager shipManager) + { + this.gameMap = gameMap; + moveEngine = new MoveEngine( + gameMap: gameMap, + OnCollision: (obj, collisionObj, moveVec) => + { + return MoveEngine.AfterCollision.Destroyed; + }, + EndMove: obj => + { + obj.CanMove.SetReturnOri(false); + } + ); + this.shipManager = shipManager; + } + public void ProduceBulletNaturally(BulletType bulletType, Ship ship, double angle, XY pos) + { + // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange + if (bulletType == BulletType.Null) return; + Bullet? bullet = BulletFactory.GetBullet(ship, pos, bulletType); + if (bullet == null) return; + gameMap.Add(bullet); + moveEngine.MoveObj(bullet, (int)(bullet.AttackDistance * 1000 / bullet.MoveSpeed), angle, ++bullet.StateNum); // 这里时间参数除出来的单位要是ms + } + public bool TryRemoveBullet(Bullet bullet) + { + if (gameMap.Remove(bullet)) + { + bullet.CanMove.SetReturnOri(false); + if (bullet.BulletBombRange > 0) + { + BombedBullet bombedBullet = new(bullet); + gameMap.Add(bombedBullet); + new Thread + (() => + { + Thread.Sleep(GameData.FrameDuration * 5); + gameMap.RemoveJustFromMap(bombedBullet); + } + ) + { IsBackground = true }.Start(); + } + return true; + } + else return false; + } + } } } diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index 53317c03..eb48241e 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -79,14 +79,13 @@ public enum GunType public enum PlaceType { Null = 0, - BirthPoint = 1, - Home = 2, - Ruin = 3, - Shadow = 4, - Asteroid = 5, - Resource = 6, - Construction = 7, - Wormhole = 8, + Ruin = 1, + Shadow = 2, + Asteroid = 3, + Resource = 4, + Construction = 5, + Wormhole = 6, + Home = 7, } /// /// 采集器类型