| @@ -1,7 +1,10 @@ | |||||
| for i in {1..10} | |||||
| SHELL_FOLDER=$(dirname $(readlink -f "$0")) | |||||
| cd $SHELL_FOLDER | |||||
| cd ../.. | |||||
| for i in {1..3} | |||||
| do | do | ||||
| find . -iname "*.cs" \ | |||||
| -or -iname "*.c" \ | |||||
| find . -iname "*.c" \ | |||||
| -or -iname "*.h" \ | -or -iname "*.h" \ | ||||
| -or -iname "*.C" \ | -or -iname "*.C" \ | ||||
| -or -iname "*.H" \ | -or -iname "*.H" \ | ||||
| @@ -19,3 +22,10 @@ find . -iname "*.cs" \ | |||||
| -or -iname "*.i++" \ | -or -iname "*.i++" \ | ||||
| | xargs clang-format -i | | xargs clang-format -i | ||||
| done | done | ||||
| pushd logic && dotnet format && popd | |||||
| pushd installer && dotnet format && popd | |||||
| pushd launcher && dotnet format && popd | |||||
| pushd playback && dotnet format && popd | |||||
| echo "Done!" | |||||
| @@ -1,5 +1,4 @@ | |||||
| using Preparation.GameData; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | using System; | ||||
| @@ -3,7 +3,6 @@ using System.Collections.Generic; | |||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
| using System.Threading; | using System.Threading; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -36,6 +36,22 @@ namespace GameClass.GameObj | |||||
| passiveSkill(this); | passiveSkill(this); | ||||
| return; | return; | ||||
| } | } | ||||
| public bool IsGhost() | |||||
| { | |||||
| return this.characterType switch | |||||
| { | |||||
| CharacterType.Vampire => true, | |||||
| CharacterType.Null => false, | |||||
| CharacterType.RecoverAfterBattle => false, | |||||
| CharacterType.SpeedUpWhenLeavingGrass => false, | |||||
| CharacterType.PSkill3 => false, | |||||
| CharacterType.PSkill4 => false, | |||||
| CharacterType.PSkill5 => false, | |||||
| _ => false, | |||||
| }; | |||||
| } | |||||
| public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType, ActiveSkillType commonSkillType) : | public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType, ActiveSkillType commonSkillType) : | ||||
| base(initPos, initRadius, initPlace, GameObjType.Character) | base(initPos, initRadius, initPlace, GameObjType.Character) | ||||
| { | { | ||||
| @@ -1,8 +1,8 @@ | |||||
| using Preparation.GameData; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Runtime.InteropServices; | |||||
| using System.Threading; | using System.Threading; | ||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| @@ -31,6 +31,27 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| public int OrgCD { get; protected set; } | public int OrgCD { get; protected set; } | ||||
| protected int fixSpeed; | |||||
| /// <summary> | |||||
| /// 修理电机速度 | |||||
| /// </summary> | |||||
| public int FixSpeed | |||||
| { | |||||
| get => fixSpeed; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| fixSpeed = value; | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// 原初修理电机速度 | |||||
| /// </summary> | |||||
| public int OrgFixSpeed { get; protected set; } | |||||
| protected int maxBulletNum; | protected int maxBulletNum; | ||||
| public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | ||||
| protected int bulletNum; | protected int bulletNum; | ||||
| @@ -47,8 +68,21 @@ namespace GameClass.GameObj | |||||
| hp = value <= MaxHp ? value : MaxHp; | hp = value <= MaxHp ? value : MaxHp; | ||||
| } | } | ||||
| } | } | ||||
| private int deathCount = 0; | |||||
| public int DeathCount => deathCount; // 玩家的死亡次数 | |||||
| private bool isEscaped=false; | |||||
| public bool IsEscaped | |||||
| { | |||||
| get => isEscaped; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| if(!isEscaped&&!IsGhost()) | |||||
| isEscaped = value; | |||||
| } | |||||
| } | |||||
| // private int deathCount = 0; | |||||
| // public int DeathCount => deathCount; // 玩家的死亡次数 | |||||
| private int score = 0; | private int score = 0; | ||||
| public int Score | public int Score | ||||
| @@ -249,7 +283,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /// <summary> | |||||
| /* /// <summary> | |||||
| /// 增加死亡次数 | /// 增加死亡次数 | ||||
| /// </summary> | /// </summary> | ||||
| /// <returns>当前死亡次数</returns> | /// <returns>当前死亡次数</returns> | ||||
| @@ -260,7 +294,7 @@ namespace GameClass.GameObj | |||||
| ++deathCount; | ++deathCount; | ||||
| return deathCount; | return deathCount; | ||||
| } | } | ||||
| } | |||||
| }*/ | |||||
| /// <summary> | /// <summary> | ||||
| /// 加分 | /// 加分 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -378,7 +412,7 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 角色携带的信息 | /// 角色携带的信息 | ||||
| /// </summary> | /// </summary> | ||||
| private string message = "THUAI5"; | |||||
| private string message = "THUAI6"; | |||||
| public string Message | public string Message | ||||
| { | { | ||||
| get => message; | get => message; | ||||
| @@ -447,18 +481,27 @@ namespace GameClass.GameObj | |||||
| #endregion | #endregion | ||||
| public override void Reset() // 要加锁吗? | public override void Reset() // 要加锁吗? | ||||
| { | { | ||||
| _ = AddDeathCount(); | |||||
| base.Reset(); | |||||
| this.MoveSpeed = OrgMoveSpeed; | |||||
| HP = MaxHp; | |||||
| PropInventory = null; | |||||
| BulletOfPlayer = OriBulletOfPlayer; | |||||
| lock (gameObjLock) | |||||
| bulletNum = maxBulletNum; | |||||
| lock (gameObjLock) | |||||
| { | |||||
| // _ = AddDeathCount(); | |||||
| base.Reset(); | |||||
| this.MoveSpeed = OrgMoveSpeed; | |||||
| HP = MaxHp; | |||||
| PropInventory = null; | |||||
| BulletOfPlayer = OriBulletOfPlayer; | |||||
| lock (gameObjLock) | |||||
| bulletNum = maxBulletNum; | |||||
| buffManeger.ClearAll(); | |||||
| IsInvisible = false; | |||||
| this.Vampire = this.OriVampire; | |||||
| } | |||||
| } | |||||
| buffManeger.ClearAll(); | |||||
| IsInvisible = false; | |||||
| this.Vampire = this.OriVampire; | |||||
| public void Escape() | |||||
| { | |||||
| lock (gameObjLock) | |||||
| IsResetting=IsEscaped=true; | |||||
| } | } | ||||
| public override bool IsRigid => true; | public override bool IsRigid => true; | ||||
| public override ShapeType Shape => ShapeType.Circle; | public override ShapeType Shape => ShapeType.Circle; | ||||
| @@ -123,16 +123,7 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 原初移动速度 | /// 原初移动速度 | ||||
| /// </summary> | /// </summary> | ||||
| private int orgMoveSpeed; | |||||
| public int OrgMoveSpeed | |||||
| { | |||||
| get => orgMoveSpeed; | |||||
| protected | |||||
| set | |||||
| { | |||||
| orgMoveSpeed = value; | |||||
| } | |||||
| } | |||||
| public int OrgMoveSpeed{ get; protected set; } | |||||
| // 移动,改变坐标 | // 移动,改变坐标 | ||||
| public long Move(XY moveVec) | public long Move(XY moveVec) | ||||
| @@ -1,6 +1,5 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -0,0 +1,40 @@ | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| /// <summary> | |||||
| /// 出口 | |||||
| /// </summary> | |||||
| public class Doorway : GameObj | |||||
| { | |||||
| public Doorway(XY initPos) : | |||||
| base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.Doorway) | |||||
| { | |||||
| this.CanMove = false; | |||||
| } | |||||
| public override bool IsRigid => true; | |||||
| public override ShapeType Shape => ShapeType.Square; | |||||
| protected override bool IgnoreCollideExecutor(IGameObj targetObj) | |||||
| { | |||||
| if (targetObj.Type != GameObjType.Character) | |||||
| return true; // 非玩家不碰撞 | |||||
| else if (!((Character)targetObj).IsGhost()) | |||||
| return true; // 不是鬼不碰撞 | |||||
| return false; | |||||
| } | |||||
| private bool powerSupply = false; | |||||
| public bool PowerSupply | |||||
| { | |||||
| get => powerSupply; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| powerSupply = value; | |||||
| } | |||||
| } | |||||
| public bool IsOpen => powerSupply; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,28 @@ | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| /// <summary> | |||||
| /// 紧急出口 | |||||
| /// </summary> | |||||
| public class EmergencyExit : GameObj | |||||
| { | |||||
| public EmergencyExit(XY initPos) : | |||||
| base(initPos, GameData.numOfPosGridPerCell / 2, PlaceType.Land, GameObjType.EmergencyExit) | |||||
| { | |||||
| this.CanMove = false; | |||||
| } | |||||
| public override bool IsRigid => true; | |||||
| public override ShapeType Shape => ShapeType.Square; | |||||
| protected override bool IgnoreCollideExecutor(IGameObj targetObj) | |||||
| { | |||||
| if (targetObj.Type != GameObjType.Character) | |||||
| return true; // 非玩家不碰撞 | |||||
| else if (!((Character)targetObj).IsGhost()) | |||||
| return true; // 不是鬼不碰撞 | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,5 +1,4 @@ | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -15,5 +14,29 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| public override bool IsRigid => true; | public override bool IsRigid => true; | ||||
| public override ShapeType Shape => ShapeType.Square; | public override ShapeType Shape => ShapeType.Square; | ||||
| private int degreeOfFRepair = 0; | |||||
| public int DegreeOfFRepair | |||||
| { | |||||
| get => degreeOfFRepair; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| { | |||||
| if(degreeOfFRepair<GameData.degreeOfFixedGenerator)//不允许正常破坏已经修好的发电机 | |||||
| if (value < 0) degreeOfFRepair = 0; | |||||
| else degreeOfFRepair =value>GameData.degreeOfFixedGenerator ? GameData.degreeOfFixedGenerator : value; | |||||
| } | |||||
| } | |||||
| } | |||||
| public bool Repair(int addDegree) | |||||
| { | |||||
| if (DegreeOfFRepair==GameData.degreeOfFixedGenerator) return false; | |||||
| DegreeOfFRepair+=addDegree; | |||||
| if (DegreeOfFRepair==GameData.degreeOfFixedGenerator) | |||||
| return true; | |||||
| else return false; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -2,7 +2,6 @@ | |||||
| using System.Threading; | using System.Threading; | ||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| using System; | using System; | ||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| @@ -13,10 +12,10 @@ namespace GameClass.GameObj | |||||
| private readonly Dictionary<uint, BirthPoint> birthPointList; // 出生点列表 | private readonly Dictionary<uint, BirthPoint> birthPointList; // 出生点列表 | ||||
| public Dictionary<uint, BirthPoint> BirthPointList => birthPointList; | public Dictionary<uint, BirthPoint> BirthPointList => birthPointList; | ||||
| private Dictionary<GameObjIdx, IList<IGameObj>> gameObjDict; | |||||
| public Dictionary<GameObjIdx, IList<IGameObj>> GameObjDict => gameObjDict; | |||||
| private Dictionary<GameObjIdx, ReaderWriterLockSlim> gameObjLockDict; | |||||
| public Dictionary<GameObjIdx, ReaderWriterLockSlim> GameObjLockDict => gameObjLockDict; | |||||
| private Dictionary<GameObjType, IList<IGameObj>> gameObjDict; | |||||
| public Dictionary<GameObjType, IList<IGameObj>> GameObjDict => gameObjDict; | |||||
| private Dictionary<GameObjType, ReaderWriterLockSlim> gameObjLockDict; | |||||
| public Dictionary<GameObjType, ReaderWriterLockSlim> GameObjLockDict => gameObjLockDict; | |||||
| public readonly uint[,] ProtoGameMap; | public readonly uint[,] ProtoGameMap; | ||||
| public PlaceType GetPlaceType(GameObj obj) | public PlaceType GetPlaceType(GameObj obj) | ||||
| @@ -73,10 +72,10 @@ namespace GameClass.GameObj | |||||
| public Character? FindPlayer(long playerID) | public Character? FindPlayer(long playerID) | ||||
| { | { | ||||
| Character? player = null; | Character? player = null; | ||||
| gameObjLockDict[GameObjIdx.Player].EnterReadLock(); | |||||
| gameObjLockDict[GameObjType.Character].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Character person in gameObjDict[GameObjIdx.Player]) | |||||
| foreach (Character person in gameObjDict[GameObjType.Character]) | |||||
| { | { | ||||
| if (playerID == person.ID) | if (playerID == person.ID) | ||||
| { | { | ||||
| @@ -87,17 +86,17 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameObjLockDict[GameObjIdx.Player].ExitReadLock(); | |||||
| gameObjLockDict[GameObjType.Character].ExitReadLock(); | |||||
| } | } | ||||
| return player; | return player; | ||||
| } | } | ||||
| public Map(uint[,] mapResource) | public Map(uint[,] mapResource) | ||||
| { | { | ||||
| gameObjDict = new Dictionary<GameObjIdx, IList<IGameObj>>(); | |||||
| gameObjLockDict = new Dictionary<GameObjIdx, ReaderWriterLockSlim>(); | |||||
| foreach (GameObjIdx idx in Enum.GetValues(typeof(GameObjIdx))) | |||||
| gameObjDict = new Dictionary<GameObjType, IList<IGameObj>>(); | |||||
| gameObjLockDict = new Dictionary<GameObjType, ReaderWriterLockSlim>(); | |||||
| foreach (GameObjType idx in Enum.GetValues(typeof(GameObjType))) | |||||
| { | { | ||||
| if (idx != GameObjIdx.None) | |||||
| if (idx != GameObjType.Null) | |||||
| { | { | ||||
| gameObjDict.Add(idx, new List<IGameObj>()); | gameObjDict.Add(idx, new List<IGameObj>()); | ||||
| gameObjLockDict.Add(idx, new ReaderWriterLockSlim()); | gameObjLockDict.Add(idx, new ReaderWriterLockSlim()); | ||||
| @@ -109,7 +108,6 @@ namespace GameClass.GameObj | |||||
| birthPointList = new Dictionary<uint, BirthPoint>(GameData.numOfBirthPoint); | birthPointList = new Dictionary<uint, BirthPoint>(GameData.numOfBirthPoint); | ||||
| // 将出生点插入 | |||||
| for (int i = 0; i < GameData.rows; ++i) | for (int i = 0; i < GameData.rows; ++i) | ||||
| { | { | ||||
| for (int j = 0; j < GameData.cols; ++j) | for (int j = 0; j < GameData.cols; ++j) | ||||
| @@ -118,14 +116,54 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| case (uint)MapInfoObjType.Wall: | case (uint)MapInfoObjType.Wall: | ||||
| { | { | ||||
| GameObjLockDict[GameObjIdx.Map].EnterWriteLock(); | |||||
| GameObjLockDict[GameObjType.Wall].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| GameObjDict[GameObjIdx.Map].Add(new Wall(GameData.GetCellCenterPos(i, j))); | |||||
| GameObjDict[GameObjType.Wall].Add(new Wall(GameData.GetCellCenterPos(i, j))); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| GameObjLockDict[GameObjIdx.Map].ExitWriteLock(); | |||||
| GameObjLockDict[GameObjType.Wall].ExitWriteLock(); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case (uint)MapInfoObjType.Doorway: | |||||
| { | |||||
| GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| GameObjDict[GameObjType.Doorway].Add(new Doorway(GameData.GetCellCenterPos(i, j))); | |||||
| } | |||||
| finally | |||||
| { | |||||
| GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case (uint)MapInfoObjType.EmergencyExit: | |||||
| { | |||||
| GameObjLockDict[GameObjType.EmergencyExit].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| GameObjDict[GameObjType.EmergencyExit].Add(new EmergencyExit(GameData.GetCellCenterPos(i, j))); | |||||
| } | |||||
| finally | |||||
| { | |||||
| GameObjLockDict[GameObjType.EmergencyExit].ExitWriteLock(); | |||||
| } | |||||
| break; | |||||
| } | |||||
| case (uint)MapInfoObjType.Generator: | |||||
| { | |||||
| GameObjLockDict[GameObjType.Generator].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| GameObjDict[GameObjType.Generator].Add(new Generator(GameData.GetCellCenterPos(i, j))); | |||||
| } | |||||
| finally | |||||
| { | |||||
| GameObjLockDict[GameObjType.Generator].ExitWriteLock(); | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| @@ -136,15 +174,15 @@ namespace GameClass.GameObj | |||||
| case (uint)MapInfoObjType.BirthPoint5: | case (uint)MapInfoObjType.BirthPoint5: | ||||
| { | { | ||||
| BirthPoint newBirthPoint = new BirthPoint(GameData.GetCellCenterPos(i, j)); | BirthPoint newBirthPoint = new BirthPoint(GameData.GetCellCenterPos(i, j)); | ||||
| birthPointList.Add(MapInfo.BirthPointEnumToIdx((MapInfoObjType)mapResource[i, j]), newBirthPoint); | |||||
| GameObjLockDict[GameObjIdx.Map].EnterWriteLock(); | |||||
| birthPointList.Add(mapResource[i, j], newBirthPoint); | |||||
| GameObjLockDict[GameObjType.BirthPoint].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| GameObjDict[GameObjIdx.Map].Add(newBirthPoint); | |||||
| GameObjDict[GameObjType.BirthPoint].Add(newBirthPoint); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| GameObjLockDict[GameObjIdx.Map].ExitWriteLock(); | |||||
| GameObjLockDict[GameObjType.BirthPoint].ExitWriteLock(); | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| @@ -11,15 +11,8 @@ namespace GameClass.GameObj | |||||
| /// <param name="obj"></param> | /// <param name="obj"></param> | ||||
| /// <returns></returns> | /// <returns></returns> | ||||
| public static uint BirthPointEnumToIdx(MapInfoObjType birthPointEnum) | |||||
| { | |||||
| uint tmp = (uint)birthPointEnum; | |||||
| // if (tmp < 5 || tmp > 12) throw new Exception("The parameter of BirthPointEnumToIdx is not a valid birth point enumeration value!"); | |||||
| return tmp - 5; | |||||
| } | |||||
| /// <summary> | /// <summary> | ||||
| /// 50*50 | /// 50*50 | ||||
| /// 1:Wall; 2:Grass1; 3:Grass2 ; 4:Grass3 ; 5~12:BirthPoint ; 13:GemWell | |||||
| /// </summary> | /// </summary> | ||||
| public static uint[,] defaultMap = new uint[,] { | public static uint[,] defaultMap = new uint[,] { | ||||
| { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||||
| @@ -1,5 +1,4 @@ | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -1,6 +1,5 @@ | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| @@ -33,16 +32,7 @@ namespace GameClass.GameObj | |||||
| this.Position = pos; | this.Position = pos; | ||||
| } | } | ||||
| } | } | ||||
| /// <summary> | |||||
| /// 增益道具 | |||||
| /// </summary> | |||||
| public abstract class BuffProp : Prop | |||||
| { | |||||
| public BuffProp(XY initPos) : | |||||
| base(initPos) | |||||
| { | |||||
| } | |||||
| } | |||||
| ///// <summary> | ///// <summary> | ||||
| ///// 坑人地雷 | ///// 坑人地雷 | ||||
| ///// </summary> | ///// </summary> | ||||
| @@ -54,7 +44,7 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 增加速度 | /// 增加速度 | ||||
| /// </summary> | /// </summary> | ||||
| public sealed class AddSpeed : BuffProp | |||||
| public sealed class AddSpeed : Prop | |||||
| { | { | ||||
| public AddSpeed(XY initPos) : | public AddSpeed(XY initPos) : | ||||
| base(initPos) | base(initPos) | ||||
| @@ -65,7 +55,7 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 复活甲 | /// 复活甲 | ||||
| /// </summary> | /// </summary> | ||||
| public sealed class AddLIFE : BuffProp | |||||
| public sealed class AddLIFE : Prop | |||||
| { | { | ||||
| public AddLIFE(XY initPos) : | public AddLIFE(XY initPos) : | ||||
| base(initPos) | base(initPos) | ||||
| @@ -76,7 +66,7 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 护盾 | /// 护盾 | ||||
| /// </summary> | /// </summary> | ||||
| public sealed class Shield : BuffProp | |||||
| public sealed class Shield : Prop | |||||
| { | { | ||||
| public Shield(XY initPos) : | public Shield(XY initPos) : | ||||
| base(initPos) | base(initPos) | ||||
| @@ -87,7 +77,7 @@ namespace GameClass.GameObj | |||||
| /// <summary> | /// <summary> | ||||
| /// 矛 | /// 矛 | ||||
| /// </summary> | /// </summary> | ||||
| public sealed class Spear : BuffProp | |||||
| public sealed class Spear : Prop | |||||
| { | { | ||||
| public Spear(XY initPos) : | public Spear(XY initPos) : | ||||
| base(initPos) | base(initPos) | ||||
| @@ -2,7 +2,6 @@ | |||||
| using System.Threading; | using System.Threading; | ||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| using System; | using System; | ||||
| using Timothy.FrameRateTask; | using Timothy.FrameRateTask; | ||||
| @@ -1,7 +1,6 @@ | |||||
| using System; | using System; | ||||
| using System.Threading; | using System.Threading; | ||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using Preparation.GameData; | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Timothy.FrameRateTask; | using Timothy.FrameRateTask; | ||||
| @@ -3,7 +3,6 @@ using System.Threading; | |||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Timothy.FrameRateTask; | using Timothy.FrameRateTask; | ||||
| using Preparation.GameData; | |||||
| namespace GameEngine | namespace GameEngine | ||||
| { | { | ||||
| @@ -1,7 +1,7 @@ | |||||
| using System; | using System; | ||||
| using System.Runtime.InteropServices; | |||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using GameEngine; | using GameEngine; | ||||
| using Preparation.GameData; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| namespace Gaming | namespace Gaming | ||||
| @@ -18,90 +18,104 @@ namespace Gaming | |||||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); | moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); | ||||
| } | } | ||||
| public bool Fix(Character player, Generator? generator = null) | |||||
| public bool TryToFix(Character player)// 自动检查有无发电机可修 | |||||
| { | { | ||||
| if (player.IsResetting) | |||||
| if (player.IsResetting||player.IsGhost()) | |||||
| return false; | return false; | ||||
| Generator? generatorForFix = null; | |||||
| Prop? pickProp = null; | |||||
| if (propType == PropType.Null) // 自动检查有无道具可捡 | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Prop prop in gameMap.GameObjDict[GameObjIdx.Prop]) | |||||
| foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) | |||||
| { | { | ||||
| if (GameData.IsInTheSameCell(prop.Position, player.Position) && prop.CanMove == false) | |||||
| if (GameData.IsInTheSameCell(generator.Position, player.Position)) | |||||
| { | { | ||||
| pickProp = prop; | |||||
| generatorForFix = generator; | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | |||||
| } | } | ||||
| } | |||||
| else | |||||
| if (generatorForFix != null) | |||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Prop prop in gameMap.GameObjDict[GameObjIdx.Prop]) | |||||
| { | |||||
| if (prop.GetPropType() == propType) | |||||
| if (generatorForFix.Repair(player.FixSpeed)) | |||||
| { | |||||
| Doorway exit = (Doorway)gameMap.GameObjDict[GameObjType.Doorway][1]; | |||||
| if (!exit.PowerSupply) | |||||
| { | { | ||||
| if (GameData.IsInTheSameCell(prop.Position, player.Position) && prop.CanMove == false) | |||||
| int numOfFixedGenerator = 0; | |||||
| foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) | |||||
| if (generator.DegreeOfFRepair==GameData.degreeOfFixedGenerator) | |||||
| ++numOfFixedGenerator; | |||||
| if(numOfFixedGenerator>=GameData.numOfGeneratorRequiredForRepair) | |||||
| { | { | ||||
| pickProp = prop; | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| foreach (Doorway doorway in gameMap.GameObjDict[GameObjType.Doorway]) | |||||
| doorway.PowerSupply=true; | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Generator].ExitReadLock(); | |||||
| } | } | ||||
| return true; | |||||
| } | } | ||||
| else | |||||
| return false; | |||||
| } | |||||
| public bool TryToEscape(Character player) | |||||
| { | |||||
| if (player.IsResetting||player.IsGhost()) | |||||
| return false; | |||||
| Doorway? doorwayForEscape = null; | |||||
| if (pickProp != null) | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].EnterReadLock(); | |||||
| try | |||||
| { | { | ||||
| // pickProp.CanMove = false; | |||||
| Prop? dropProp = null; | |||||
| if (player.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地 | |||||
| { | |||||
| dropProp = player.PropInventory; | |||||
| dropProp.SetNewPos(GameData.GetCellCenterPos(player.Position.x / GameData.numOfPosGridPerCell, player.Position.y / GameData.numOfPosGridPerCell)); | |||||
| } | |||||
| player.PropInventory = pickProp; | |||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterWriteLock(); | |||||
| try | |||||
| foreach (Doorway doorway in gameMap.GameObjDict[GameObjType.Doorway]) | |||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Remove(pickProp); | |||||
| if (dropProp != null) | |||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(dropProp); | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitWriteLock(); | |||||
| } | |||||
| gameMap.GameObjLockDict[GameObjIdx.PickedProp].EnterWriteLock(); | |||||
| try | |||||
| { | |||||
| gameMap.GameObjDict[GameObjIdx.PickedProp].Add(new PickedProp(pickProp)); | |||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjIdx.PickedProp].ExitWriteLock(); | |||||
| if (GameData.IsInTheSameCell(doorway.Position, player.Position)) | |||||
| { | |||||
| doorwayForEscape = doorway; | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| } | |||||
| finally | |||||
| { | |||||
| gameMap.GameObjLockDict[GameObjType.Doorway].ExitReadLock(); | |||||
| } | |||||
| if (doorwayForEscape != null&& doorwayForEscape.IsOpen) | |||||
| { | |||||
| player.Escape(); | |||||
| return true; | return true; | ||||
| } | } | ||||
| else | else | ||||
| return false; | return false; | ||||
| } | } | ||||
| /* | /* | ||||
| private void ActivateMine(Character player, Mine mine) | private void ActivateMine(Character player, Mine mine) | ||||
| { | { | ||||
| @@ -125,11 +139,11 @@ namespace Gaming | |||||
| } | } | ||||
| */ | */ | ||||
| // private readonly Map gameMap; | |||||
| private readonly Map gameMap; | |||||
| private readonly MoveEngine moveEngine; | private readonly MoveEngine moveEngine; | ||||
| public ActionManager(Map gameMap) | public ActionManager(Map gameMap) | ||||
| { | { | ||||
| // this.gameMap = gameMap; | |||||
| this.gameMap = gameMap; | |||||
| this.moveEngine = new MoveEngine( | this.moveEngine = new MoveEngine( | ||||
| gameMap: gameMap, | gameMap: gameMap, | ||||
| OnCollision: (obj, collisionObj, moveVec) => | OnCollision: (obj, collisionObj, moveVec) => | ||||
| @@ -2,7 +2,6 @@ | |||||
| using System.Threading; | using System.Threading; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using Preparation.GameData; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using GameEngine; | using GameEngine; | ||||
| @@ -41,14 +40,14 @@ namespace Gaming | |||||
| { | { | ||||
| playerBeingShot.CanMove = false; | playerBeingShot.CanMove = false; | ||||
| playerBeingShot.IsResetting = true; | playerBeingShot.IsResetting = true; | ||||
| // gameMap.GameObjLockDict[GameObjIdx.Player].EnterWriteLock(); | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| // try | // try | ||||
| //{ | //{ | ||||
| // gameMap.GameObjDict[GameObjIdx.Player].Remove(playerBeingShot); | |||||
| // gameMap.GameObjDict[GameObjType.Character].Remove(playerBeingShot); | |||||
| // } | // } | ||||
| // finally | // finally | ||||
| //{ | //{ | ||||
| // gameMap.GameObjLockDict[GameObjIdx.Player].ExitWriteLock(); | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||||
| // } | // } | ||||
| Prop? dropProp = null; | Prop? dropProp = null; | ||||
| @@ -57,15 +56,15 @@ namespace Gaming | |||||
| dropProp = playerBeingShot.PropInventory; | dropProp = playerBeingShot.PropInventory; | ||||
| dropProp.SetNewPos(GameData.GetCellCenterPos(playerBeingShot.Position.x / GameData.numOfPosGridPerCell, playerBeingShot.Position.y / GameData.numOfPosGridPerCell)); | dropProp.SetNewPos(GameData.GetCellCenterPos(playerBeingShot.Position.x / GameData.numOfPosGridPerCell, playerBeingShot.Position.y / GameData.numOfPosGridPerCell)); | ||||
| } | } | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| if (dropProp != null) | if (dropProp != null) | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(dropProp); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add(dropProp); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||||
| } | } | ||||
| playerBeingShot.Reset(); | playerBeingShot.Reset(); | ||||
| @@ -79,12 +78,12 @@ namespace Gaming | |||||
| playerBeingShot.AddShield(GameData.shieldTimeAtBirth); // 复活加个盾 | playerBeingShot.AddShield(GameData.shieldTimeAtBirth); // 复活加个盾 | ||||
| // gameMap.GameObjLockDict[GameObjIdx.Player].EnterWriteLock(); | |||||
| // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| // try | // try | ||||
| //{ | //{ | ||||
| // gameMap.GameObjDict[GameObjIdx.Player].Add(playerBeingShot); | |||||
| // gameMap.GameObjDict[GameObjType.Character].Add(playerBeingShot); | |||||
| // } | // } | ||||
| // finally { gameMap.GameObjLockDict[GameObjIdx.Player].ExitWriteLock(); } | |||||
| // finally { gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); } | |||||
| if (gameMap.Timer.IsGaming) | if (gameMap.Timer.IsGaming) | ||||
| { | { | ||||
| @@ -102,30 +101,30 @@ namespace Gaming | |||||
| Debugger.Output(bullet, "bombed!"); | Debugger.Output(bullet, "bombed!"); | ||||
| #endif | #endif | ||||
| bullet.CanMove = false; | bullet.CanMove = false; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Bullet].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Bullet].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (ObjOfCharacter _bullet in gameMap.GameObjDict[GameObjIdx.Bullet]) | |||||
| foreach (ObjOfCharacter _bullet in gameMap.GameObjDict[GameObjType.Bullet]) | |||||
| { | { | ||||
| if (_bullet.ID == bullet.ID) | if (_bullet.ID == bullet.ID) | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.BombedBullet].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.BombedBullet].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.BombedBullet].Add(new BombedBullet(bullet)); | |||||
| gameMap.GameObjDict[GameObjType.BombedBullet].Add(new BombedBullet(bullet)); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.BombedBullet].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.BombedBullet].ExitWriteLock(); | |||||
| } | } | ||||
| gameMap.GameObjDict[GameObjIdx.Bullet].Remove(_bullet); | |||||
| gameMap.GameObjDict[GameObjType.Bullet].Remove(_bullet); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Bullet].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); | |||||
| } | } | ||||
| /*if (objBeingShot != null) | /*if (objBeingShot != null) | ||||
| @@ -138,10 +137,10 @@ namespace Gaming | |||||
| // 子弹爆炸会发生的事↓↓↓ | // 子弹爆炸会发生的事↓↓↓ | ||||
| var beAttackedList = new List<Character>(); | var beAttackedList = new List<Character>(); | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Character player in gameMap.GameObjDict[GameObjIdx.Player]) | |||||
| foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) | |||||
| { | { | ||||
| if (bullet.CanAttack(player)) | if (bullet.CanAttack(player)) | ||||
| { | { | ||||
| @@ -153,7 +152,7 @@ namespace Gaming | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||||
| } | } | ||||
| foreach (Character beAttackedPlayer in beAttackedList) | foreach (Character beAttackedPlayer in beAttackedList) | ||||
| @@ -184,14 +183,14 @@ namespace Gaming | |||||
| if (bullet != null) | if (bullet != null) | ||||
| { | { | ||||
| bullet.CanMove = true; | bullet.CanMove = true; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Bullet].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Bullet].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.Bullet].Add(bullet); | |||||
| gameMap.GameObjDict[GameObjType.Bullet].Add(bullet); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Bullet].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); | |||||
| } | } | ||||
| moveEngine.MoveObj(bullet, (int)((player.AttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms | moveEngine.MoveObj(bullet, (int)((player.AttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms | ||||
| #if DEBUG | #if DEBUG | ||||
| @@ -3,7 +3,6 @@ using System.Threading; | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using Preparation.GameData; | |||||
| using Timothy.FrameRateTask; | using Timothy.FrameRateTask; | ||||
| using Preparation.Interface; | using Preparation.Interface; | ||||
| @@ -44,16 +43,16 @@ namespace Gaming | |||||
| // Console.WriteLine($"x,y: {pos.x},{pos.y}"); | // Console.WriteLine($"x,y: {pos.x},{pos.y}"); | ||||
| Character newPlayer = new(pos, GameData.characterRadius, gameMap.GetPlaceType(pos), playerInitInfo.characterType, playerInitInfo.commonSkill); | Character newPlayer = new(pos, GameData.characterRadius, gameMap.GetPlaceType(pos), playerInitInfo.characterType, playerInitInfo.commonSkill); | ||||
| gameMap.BirthPointList[playerInitInfo.birthPointIndex].Parent = newPlayer; | gameMap.BirthPointList[playerInitInfo.birthPointIndex].Parent = newPlayer; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.Player].Add(newPlayer); | |||||
| gameMap.GameObjDict[GameObjType.Character].Add(newPlayer); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||||
| } | } | ||||
| // Console.WriteLine($"GameObjDict[GameObjIdx.Player] length:{gameMap.GameObjDict[GameObjIdx.Player].Count}"); | |||||
| // Console.WriteLine($"GameObjDict[GameObjType.Character] length:{gameMap.GameObjDict[GameObjType.Character].Count}"); | |||||
| teamList[(int)playerInitInfo.teamID].AddPlayer(newPlayer); | teamList[(int)playerInitInfo.teamID].AddPlayer(newPlayer); | ||||
| newPlayer.TeamID = playerInitInfo.teamID; | newPlayer.TeamID = playerInitInfo.teamID; | ||||
| newPlayer.PlayerID = playerInitInfo.playerID; | newPlayer.PlayerID = playerInitInfo.playerID; | ||||
| @@ -103,10 +102,10 @@ namespace Gaming | |||||
| { | { | ||||
| if (gameMap.Timer.IsGaming) | if (gameMap.Timer.IsGaming) | ||||
| return false; | return false; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Character player in gameMap.GameObjDict[GameObjIdx.Player]) | |||||
| foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) | |||||
| { | { | ||||
| player.CanMove = true; | player.CanMove = true; | ||||
| @@ -115,7 +114,7 @@ namespace Gaming | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||||
| } | } | ||||
| propManager.StartProducing(); | propManager.StartProducing(); | ||||
| @@ -130,7 +129,7 @@ namespace Gaming | |||||
| { | { | ||||
| foreach (var kvp in gameMap.GameObjDict) // 检查物体位置 | foreach (var kvp in gameMap.GameObjDict) // 检查物体位置 | ||||
| { | { | ||||
| if (kvp.Key == GameObjIdx.Bullet || kvp.Key == GameObjIdx.Player || kvp.Key == GameObjIdx.Prop) | |||||
| if (kvp.Key == GameObjType.Bullet || kvp.Key == GameObjType.Character || kvp.Key == GameObjType.Prop) | |||||
| { | { | ||||
| gameMap.GameObjLockDict[kvp.Key].EnterWriteLock(); | gameMap.GameObjLockDict[kvp.Key].EnterWriteLock(); | ||||
| try | try | ||||
| @@ -167,14 +166,14 @@ namespace Gaming | |||||
| public void EndGame() | public void EndGame() | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| /*try | /*try | ||||
| { | { | ||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| }*/ | }*/ | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||||
| } | } | ||||
| public void MovePlayer(long playerID, int moveTimeInMilliseconds, double angle) | public void MovePlayer(long playerID, int moveTimeInMilliseconds, double angle) | ||||
| { | { | ||||
| @@ -183,11 +182,7 @@ namespace Gaming | |||||
| Character? player = gameMap.FindPlayer(playerID); | Character? player = gameMap.FindPlayer(playerID); | ||||
| if (player != null) | if (player != null) | ||||
| { | { | ||||
| <<<<<<< HEAD | |||||
| actionManager.MovePlayer(player, moveTimeInMilliseconds, angle); | actionManager.MovePlayer(player, moveTimeInMilliseconds, angle); | ||||
| ======= | |||||
| moveManager.MovePlayer(player, moveTimeInMilliseconds, angle); | |||||
| >>>>>>> bad3c7b1c2a9453f59ea260079904624c3df6fb1 | |||||
| #if DEBUG | #if DEBUG | ||||
| Console.WriteLine($"PlayerID:{playerID} move to ({player.Position.x},{player.Position.y})!"); | Console.WriteLine($"PlayerID:{playerID} move to ({player.Position.x},{player.Position.y})!"); | ||||
| #endif | #endif | ||||
| @@ -258,25 +253,25 @@ namespace Gaming | |||||
| { | { | ||||
| if (!gameMap.Timer.IsGaming) | if (!gameMap.Timer.IsGaming) | ||||
| return; | return; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Character player in gameMap.GameObjDict[GameObjIdx.Player]) | |||||
| foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) | |||||
| { | { | ||||
| skillManager.UsePassiveSkill(player); | skillManager.UsePassiveSkill(player); | ||||
| } | } | ||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Player].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||||
| } | } | ||||
| } | } | ||||
| public void ClearLists(GameObjIdx[] objIdxes) | |||||
| public void ClearLists(GameObjType[] objIdxes) | |||||
| { | { | ||||
| foreach (var idx in objIdxes) | foreach (var idx in objIdxes) | ||||
| { | { | ||||
| if (idx != GameObjIdx.None) | |||||
| if (idx != GameObjType.Null) | |||||
| { | { | ||||
| gameMap.GameObjLockDict[idx].EnterWriteLock(); | gameMap.GameObjLockDict[idx].EnterWriteLock(); | ||||
| try | try | ||||
| @@ -294,14 +289,14 @@ namespace Gaming | |||||
| { | { | ||||
| foreach (var keyValuePair in gameMap.GameObjDict) | foreach (var keyValuePair in gameMap.GameObjDict) | ||||
| { | { | ||||
| if (keyValuePair.Key != GameObjIdx.Map) | |||||
| if (((uint)keyValuePair.Key) <= GameData.numOfObjNotMap) | |||||
| { | { | ||||
| gameMap.GameObjLockDict[keyValuePair.Key].EnterWriteLock(); | gameMap.GameObjLockDict[keyValuePair.Key].EnterWriteLock(); | ||||
| try | try | ||||
| { | { | ||||
| if (keyValuePair.Key == GameObjIdx.Player) | |||||
| if (keyValuePair.Key == GameObjType.Character) | |||||
| { | { | ||||
| foreach (Character player in gameMap.GameObjDict[GameObjIdx.Player]) | |||||
| foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) | |||||
| { | { | ||||
| player.CanMove = false; | player.CanMove = false; | ||||
| } | } | ||||
| @@ -325,7 +320,7 @@ namespace Gaming | |||||
| var gameObjList = new List<IGameObj>(); | var gameObjList = new List<IGameObj>(); | ||||
| foreach (var keyValuePair in gameMap.GameObjDict) | foreach (var keyValuePair in gameMap.GameObjDict) | ||||
| { | { | ||||
| if (keyValuePair.Key != GameObjIdx.Map) | |||||
| if (((uint)keyValuePair.Key) <= GameData.numOfObjNotMap) | |||||
| { | { | ||||
| gameMap.GameObjLockDict[keyValuePair.Key].EnterReadLock(); | gameMap.GameObjLockDict[keyValuePair.Key].EnterReadLock(); | ||||
| try | try | ||||
| @@ -1,7 +1,6 @@ | |||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using System.Threading; | using System.Threading; | ||||
| using Preparation.GameData; | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | using System; | ||||
| using Timothy.FrameRateTask; | using Timothy.FrameRateTask; | ||||
| @@ -66,10 +65,10 @@ namespace Gaming | |||||
| Prop? pickProp = null; | Prop? pickProp = null; | ||||
| if (propType == PropType.Null) // 自动检查有无道具可捡 | if (propType == PropType.Null) // 自动检查有无道具可捡 | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Prop prop in gameMap.GameObjDict[GameObjIdx.Prop]) | |||||
| foreach (Prop prop in gameMap.GameObjDict[GameObjType.Prop]) | |||||
| { | { | ||||
| if (GameData.IsInTheSameCell(prop.Position, player.Position) && prop.CanMove == false) | if (GameData.IsInTheSameCell(prop.Position, player.Position) && prop.CanMove == false) | ||||
| { | { | ||||
| @@ -79,15 +78,15 @@ namespace Gaming | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitReadLock(); | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterReadLock(); | |||||
| try | try | ||||
| { | { | ||||
| foreach (Prop prop in gameMap.GameObjDict[GameObjIdx.Prop]) | |||||
| foreach (Prop prop in gameMap.GameObjDict[GameObjType.Prop]) | |||||
| { | { | ||||
| if (prop.GetPropType() == propType) | if (prop.GetPropType() == propType) | ||||
| { | { | ||||
| @@ -100,7 +99,7 @@ namespace Gaming | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitReadLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitReadLock(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -114,25 +113,25 @@ namespace Gaming | |||||
| dropProp.SetNewPos(GameData.GetCellCenterPos(player.Position.x / GameData.numOfPosGridPerCell, player.Position.y / GameData.numOfPosGridPerCell)); | dropProp.SetNewPos(GameData.GetCellCenterPos(player.Position.x / GameData.numOfPosGridPerCell, player.Position.y / GameData.numOfPosGridPerCell)); | ||||
| } | } | ||||
| player.PropInventory = pickProp; | player.PropInventory = pickProp; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Remove(pickProp); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Remove((Preparation.Interface.IGameObj)pickProp); | |||||
| if (dropProp != null) | if (dropProp != null) | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(dropProp); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add((Preparation.Interface.IGameObj)dropProp); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||||
| } | } | ||||
| gameMap.GameObjLockDict[GameObjIdx.PickedProp].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.PickedProp].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.PickedProp].Add(new PickedProp(pickProp)); | |||||
| gameMap.GameObjDict[GameObjType.PickedProp].Add(new PickedProp(pickProp)); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.PickedProp].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.PickedProp].ExitWriteLock(); | |||||
| } | } | ||||
| return true; | return true; | ||||
| @@ -153,14 +152,14 @@ namespace Gaming | |||||
| prop.CanMove = true; | prop.CanMove = true; | ||||
| prop.SetNewPos(player.Position); | prop.SetNewPos(player.Position); | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(prop); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add((Preparation.Interface.IGameObj)prop); | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||||
| } | } | ||||
| timeInMilliseconds = timeInMilliseconds < GameData.PropMaxMoveDistance / prop.MoveSpeed * 1000 ? timeInMilliseconds : GameData.PropMaxMoveDistance / prop.MoveSpeed * 1000; | timeInMilliseconds = timeInMilliseconds < GameData.PropMaxMoveDistance / prop.MoveSpeed * 1000 ? timeInMilliseconds : GameData.PropMaxMoveDistance / prop.MoveSpeed * 1000; | ||||
| moveEngine.MoveObj(prop, timeInMilliseconds, angle); | moveEngine.MoveObj(prop, timeInMilliseconds, angle); | ||||
| @@ -182,22 +181,22 @@ namespace Gaming | |||||
| int rand = r.Next(0, len); | int rand = r.Next(0, len); | ||||
| XY randPos = availableCellForGenerateProp[rand]; | XY randPos = availableCellForGenerateProp[rand]; | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].EnterWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); | |||||
| try | try | ||||
| { | { | ||||
| switch (r.Next(0, 4)) | switch (r.Next(0, 4)) | ||||
| { | { | ||||
| case 0: | case 0: | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(new AddLIFE(randPos)); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add((Preparation.Interface.IGameObj)new AddLIFE(randPos)); | |||||
| break; | break; | ||||
| case 1: | case 1: | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(new AddSpeed(randPos)); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add((Preparation.Interface.IGameObj)new AddSpeed(randPos)); | |||||
| break; | break; | ||||
| case 2: | case 2: | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(new Shield(randPos)); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add((Preparation.Interface.IGameObj)new Shield(randPos)); | |||||
| break; | break; | ||||
| case 3: | case 3: | ||||
| gameMap.GameObjDict[GameObjIdx.Prop].Add(new Spear(randPos)); | |||||
| gameMap.GameObjDict[GameObjType.Prop].Add((Preparation.Interface.IGameObj)new Spear(randPos)); | |||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| @@ -205,7 +204,7 @@ namespace Gaming | |||||
| } | } | ||||
| finally | finally | ||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjIdx.Prop].ExitWriteLock(); | |||||
| gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); | |||||
| } | } | ||||
| }, | }, | ||||
| GameData.PropProduceTime, | GameData.PropProduceTime, | ||||
| @@ -233,21 +232,15 @@ namespace Gaming | |||||
| availableCellForGenerateProp = new List<XY>(); | availableCellForGenerateProp = new List<XY>(); | ||||
| for (int i = 0; i < gameMap.ProtoGameMap.GetLength(0); i++) | for (int i = 0; i < gameMap.ProtoGameMap.GetLength(0); i++) | ||||
| { | { | ||||
| <<<<<<< HEAD | |||||
| for (int j = 0; j < gameMap.ProtoGameMap.GetLength(1); j++) | for (int j = 0; j < gameMap.ProtoGameMap.GetLength(1); j++) | ||||
| { | { | ||||
| if (gameMap.ProtoGameMap[i, j] == (int)MapInfoObjType.Null) | if (gameMap.ProtoGameMap[i, j] == (int)MapInfoObjType.Null) | ||||
| ======= | |||||
| for (int j = 0; j < gameMap.ProtoGameMap.GetLength(1); j++) | |||||
| >>>>>>> bad3c7b1c2a9453f59ea260079904624c3df6fb1 | |||||
| { | { | ||||
| if (gameMap.ProtoGameMap[i, j] == (int)MapInfo.MapInfoObjType.Null) | |||||
| { | |||||
| availableCellForGenerateProp.Add(GameData.GetCellCenterPos(i, j)); | |||||
| } | |||||
| availableCellForGenerateProp.Add(GameData.GetCellCenterPos(i, j)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| @@ -9,8 +9,8 @@ namespace Preparation.Interface | |||||
| ITimer Timer { get; } | ITimer Timer { get; } | ||||
| // the two dicts must have same keys | // the two dicts must have same keys | ||||
| Dictionary<GameObjIdx, IList<IGameObj>> GameObjDict { get; } | |||||
| Dictionary<GameObjIdx, ReaderWriterLockSlim> GameObjLockDict { get; } | |||||
| Dictionary<GameObjType, IList<IGameObj>> GameObjDict { get; } | |||||
| Dictionary<GameObjType, ReaderWriterLockSlim> GameObjLockDict { get; } | |||||
| public bool IsOutOfBound(IGameObj obj); | public bool IsOutOfBound(IGameObj obj); | ||||
| public IOutOfBound GetOutOfBound(XY pos); // 返回新建的一个OutOfBound对象 | public IOutOfBound GetOutOfBound(XY pos); // 返回新建的一个OutOfBound对象 | ||||
| @@ -1,4 +1,4 @@ | |||||
| <Project Sdk="Microsoft.NET.Sdk"> | |||||
| <Project Sdk="Microsoft.NET.Sdk"> | |||||
| <PropertyGroup> | <PropertyGroup> | ||||
| <OutputType>Library</OutputType> | <OutputType>Library</OutputType> | ||||
| @@ -4,6 +4,7 @@ namespace Preparation.Utility | |||||
| /// <summary> | /// <summary> | ||||
| /// 存放所有用到的枚举类型 | /// 存放所有用到的枚举类型 | ||||
| /// </summary> | /// </summary> | ||||
| // public const int numOfObjNotMap = 5;在GameData中 | |||||
| public enum GameObjType | public enum GameObjType | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| @@ -17,7 +18,7 @@ namespace Preparation.Utility | |||||
| Grass = 7, | Grass = 7, | ||||
| Generator = 8, // 发电机 | Generator = 8, // 发电机 | ||||
| BirthPoint = 9, | BirthPoint = 9, | ||||
| Exit = 10, | |||||
| Doorway = 10, | |||||
| EmergencyExit = 11, | EmergencyExit = 11, | ||||
| OutOfBoundBlock = 12, // 范围外 | OutOfBoundBlock = 12, // 范围外 | ||||
| } | } | ||||
| @@ -80,30 +81,21 @@ namespace Preparation.Utility | |||||
| Shield = 3, | Shield = 3, | ||||
| Spear = 4 | Spear = 4 | ||||
| } | } | ||||
| public enum GameObjIdx | |||||
| public enum MapInfoObjType | |||||
| { | { | ||||
| None = 0, | |||||
| Player = 1, | |||||
| Bullet = 2, | |||||
| Prop = 3, | |||||
| Map = 4, | |||||
| BombedBullet = 5, | |||||
| PickedProp = 6 | |||||
| Null = 0, | |||||
| BirthPoint1 = 1,//必须从1开始 | |||||
| BirthPoint2 = 2, | |||||
| BirthPoint3 = 3, | |||||
| BirthPoint4 = 4, | |||||
| BirthPoint5 = 5, | |||||
| Wall = 6, | |||||
| Grass1 = 7, | |||||
| Grass2 = 8, | |||||
| Grass3 = 9, | |||||
| Generator = 10, // 发电机 | |||||
| Doorway = 11, | |||||
| EmergencyExit = 12 | |||||
| } | } | ||||
| } | |||||
| public enum MapInfoObjType | |||||
| { | |||||
| Null = 0, | |||||
| Wall = 1, | |||||
| Grass1 = 2, | |||||
| Grass2 = 3, | |||||
| Grass3 = 4, | |||||
| Generator = 5, // 发电机 | |||||
| Exit = 6, | |||||
| EmergencyExit = 7, | |||||
| BirthPoint1 = 8, | |||||
| BirthPoint2 = 9, | |||||
| BirthPoint3 = 10, | |||||
| BirthPoint4 = 11, | |||||
| BirthPoint5 = 12, | |||||
| } | } | ||||
| @@ -1,6 +1,4 @@ | |||||
| using Preparation.Utility; | |||||
| namespace Preparation.GameData | |||||
| namespace Preparation.Utility | |||||
| { | { | ||||
| public static class GameData | public static class GameData | ||||
| { | { | ||||
| @@ -16,9 +14,15 @@ namespace Preparation.GameData | |||||
| public const int MinSpeed = 1; // 最小速度 | public const int MinSpeed = 1; // 最小速度 | ||||
| public const int MaxSpeed = int.MaxValue; // 最大速度 | public const int MaxSpeed = int.MaxValue; // 最大速度 | ||||
| public const int numOfBirthPoint = 5; | |||||
| // public const int numOfGenerator = 7; | |||||
| public const int numOfGeneratorRequiredForRepair = 5; | |||||
| public const int numOfObjNotMap = 5; | |||||
| public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 | public static XY GetCellCenterPos(int x, int y) // 求格子的中心坐标 | ||||
| { | { | ||||
| XY ret = new((x * numOfPosGridPerCell) + (numOfPosGridPerCell / 2), (y * numOfPosGridPerCell) + (numOfPosGridPerCell / 2)); | |||||
| XY ret = new(x * numOfPosGridPerCell + numOfPosGridPerCell / 2, y * numOfPosGridPerCell + numOfPosGridPerCell / 2); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| public static int PosGridToCellX(XY pos) // 求坐标所在的格子的x坐标 | public static int PosGridToCellX(XY pos) // 求坐标所在的格子的x坐标 | ||||
| @@ -33,13 +37,8 @@ namespace Preparation.GameData | |||||
| { | { | ||||
| return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2); | return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2); | ||||
| } | } | ||||
| public static int numOfBirthPoint = 5; | |||||
| #endregion | #endregion | ||||
| #region 角色相关 | #region 角色相关 | ||||
| /// <summary> | |||||
| /// 玩家相关 | |||||
| /// </summary> | |||||
| public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 | public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 | ||||
| public const int basicAp = 3000; // 初始攻击力 | public const int basicAp = 3000; // 初始攻击力 | ||||
| public const int basicHp = 6000; // 初始血量 | public const int basicHp = 6000; // 初始血量 | ||||
| @@ -59,9 +58,8 @@ namespace Preparation.GameData | |||||
| public const int reviveTime = 30000; // 复活时间 | public const int reviveTime = 30000; // 复活时间 | ||||
| public const int shieldTimeAtBirth = 3000; // 复活时的护盾时间 | public const int shieldTimeAtBirth = 3000; // 复活时的护盾时间 | ||||
| public const int gemToScore = 4; // 一个宝石的标准加分 | public const int gemToScore = 4; // 一个宝石的标准加分 | ||||
| /// <summary> | |||||
| /// 道具相关 | |||||
| /// </summary> | |||||
| #endregion | |||||
| #region 道具相关 | |||||
| public const int MinPropTypeNum = 1; | public const int MinPropTypeNum = 1; | ||||
| public const int MaxPropTypeNum = 10; | public const int MaxPropTypeNum = 10; | ||||
| public const int PropRadius = numOfPosGridPerCell / 2; | public const int PropRadius = numOfPosGridPerCell / 2; | ||||
| @@ -71,6 +69,8 @@ namespace Preparation.GameData | |||||
| public const long GemProduceTime = 10000; | public const long GemProduceTime = 10000; | ||||
| public const long PropProduceTime = 10000; | public const long PropProduceTime = 10000; | ||||
| public const int PropDuration = 10000; | public const int PropDuration = 10000; | ||||
| public const int degreeOfFixedGenerator = 100; | |||||
| #endregion | #endregion | ||||
| #region 游戏帧相关 | #region 游戏帧相关 | ||||
| public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | ||||