Browse Source

perf: use more safe, efficient way to update BulletNum

tags/v0.1.0
shangfengh 3 years ago
parent
commit
eed264a2f5
5 changed files with 82 additions and 114 deletions
  1. +44
    -72
      logic/GameClass/GameObj/Character/Character.cs
  2. +3
    -2
      logic/GameClass/GameObj/Moveable.cs
  3. +1
    -2
      logic/Gaming/AttackManager.cs
  4. +33
    -37
      logic/Gaming/CharacterManager .cs
  5. +1
    -1
      logic/Preparation/Interface/ICharacter.cs

+ 44
- 72
logic/GameClass/GameObj/Character/Character.cs View File

@@ -10,10 +10,7 @@ namespace GameClass.GameObj
{
#region 装弹、攻击相关的基本属性及方法

protected readonly object AttackLock = new();
private readonly ReaderWriterLockSlim attackReaderWriterLock = new();
public ReaderWriterLockSlim AttackReaderWriterLock => attackReaderWriterLock;
//规定AttackReaderWriterLock>AttackLock
private readonly object attackLock = new();

/// <summary>
/// 装弹冷却
@@ -23,114 +20,89 @@ namespace GameClass.GameObj
{
get
{
attackReaderWriterLock.EnterReadLock();
try
lock (attackLock)
{
return cd;
}
finally { attackReaderWriterLock.ExitReadLock(); }
}
}
public int OrgCD { get; protected set; }

protected int maxBulletNum;
public int MaxBulletNum
{
get
{
attackReaderWriterLock.EnterReadLock();
try
{
return maxBulletNum;
}
finally { attackReaderWriterLock.ExitReadLock(); }
}
}
protected int bulletNum;
public int BulletNum => bulletNum; // 目前持有的子弹数

public readonly BulletType OriBulletOfPlayer;
private BulletType bulletOfPlayer;
public BulletType BulletOfPlayer
{
get
{
attackReaderWriterLock.EnterReadLock();
try
lock (attackLock)
{
return bulletOfPlayer;
}
finally { attackReaderWriterLock.ExitReadLock(); }
}
set
{
attackReaderWriterLock.EnterWriteLock();
try
lock (attackLock)
{
lock (AttackLock)
{
bulletOfPlayer = value;
cd = OrgCD = (BulletFactory.BulletCD(value));
Debugger.Output(this, string.Format("'s CD has been set to: {0}.", cd));
maxBulletNum = bulletNum = (BulletFactory.BulletNum(value));
}
bulletOfPlayer = value;
cd = OrgCD = (BulletFactory.BulletCD(value));
Debugger.Output(this, string.Format("'s CD has been set to: {0}.", cd));
maxBulletNum = bulletNum = (BulletFactory.BulletNum(value));
}
finally { attackReaderWriterLock.ExitWriteLock(); }
}
}

/// <summary>
/// 进行一次攻击
/// </summary>
/// <returns>攻击操作发出的子弹</returns>
public Bullet? Attack(double angle)
protected int maxBulletNum;
public int MaxBulletNum
{
if (TrySubBulletNum())
get
{
XY res = Position + new XY // 子弹紧贴人物生成。
(
(int)(Math.Abs((Radius + BulletFactory.BulletRadius(BulletOfPlayer)) * Math.Cos(angle))) * ((Math.Cos(angle) > 0) ? 1 : -1),
(int)(Math.Abs((Radius + BulletFactory.BulletRadius(BulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1)
);
Bullet? bullet = BulletFactory.GetBullet(this, res);
if (bullet == null) return null;
facingDirection = new(angle, bullet.BulletAttackRange);
return bullet;
lock (attackLock)
{
return maxBulletNum;
}
}
else
return null;
}
private int bulletNum;
private int updateTimeOfBulletNum = 0;

/// <summary>
/// 尝试将子弹数量减1
/// </summary>
/// <returns>减操作是否成功</returns>
private bool TrySubBulletNum()
public int UpdateBulletNum(int time)
{
lock (gameObjLock)
lock (attackLock)
{
if (bulletNum > 0)
if (bulletNum < maxBulletNum)
{
--bulletNum;
return true;
int add = Math.Min(maxBulletNum - bulletNum, (time - updateTimeOfBulletNum) / cd);
updateTimeOfBulletNum += add * cd;
return (bulletNum += add);
}
return false;
return maxBulletNum;
}
}

/// <summary>
/// 尝试将子弹数量加1
/// 进行一次攻击
/// </summary>
/// <returns>加操作是否成功</returns>
public bool TryAddBulletNum()
/// <returns>攻击操作发出的子弹</returns>
public Bullet? Attack(double angle, int time)
{
lock (gameObjLock)
lock (attackLock)
{
if (bulletNum < maxBulletNum)
if (UpdateBulletNum(time) > 0)
{
++bulletNum;
return true;
if(bulletNum==maxBulletNum)updateTimeOfBulletNum = time;
--bulletNum;
XY res = Position + new XY // 子弹紧贴人物生成。
(
(int)(Math.Abs((Radius + BulletFactory.BulletRadius(BulletOfPlayer)) * Math.Cos(angle))) * ((Math.Cos(angle) > 0) ? 1 : -1),
(int)(Math.Abs((Radius + BulletFactory.BulletRadius(BulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1)
);
Bullet? bullet = BulletFactory.GetBullet(this, res);
if (bullet == null) return null;
facingDirection = new(angle, bullet.BulletAttackRange);
return bullet;
}
return false;
else
return null;
}
}

@@ -405,7 +377,7 @@ namespace GameClass.GameObj
position = GameData.PosWhoDie;
}
}
finally
finally
{
MoveReaderWriterLock.ExitWriteLock();
}


+ 3
- 2
logic/GameClass/GameObj/Moveable.cs View File

@@ -141,8 +141,9 @@ namespace GameClass.GameObj
moveReaderWriterLock.EnterWriteLock();
try
{
lock (moveObjLock) {
moveSpeed=value;
lock (moveObjLock)
{
moveSpeed = value;
}
}
finally


+ 1
- 2
logic/Gaming/AttackManager.cs View File

@@ -123,7 +123,6 @@ namespace Gaming
if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null)
{
bullet.Parent!.BulletOfPlayer = BulletType.JumpyDumpty;
Debugger.Output(bullet.Parent, bullet.Parent.CharacterType.ToString() + " " + bullet.Parent.BulletNum.ToString());
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI / 2.0);
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0);
}
@@ -173,7 +172,7 @@ namespace Gaming

Debugger.Output(player, player.Position.ToString() + " " + player.Radius.ToString() + " " + BulletFactory.BulletRadius(player.BulletOfPlayer).ToString());

Bullet? bullet = player.Attack(angle);
Bullet? bullet = player.Attack(angle, gameMap.Timer.nowTime());

if (bullet != null)
{


+ 33
- 37
logic/Gaming/CharacterManager .cs View File

@@ -66,43 +66,39 @@ namespace Gaming

newPlayer.TeamID = teamID;
newPlayer.PlayerID = playerID;
#region 人物装弹
new Thread
(
() =>
{
while (!gameMap.Timer.IsGaming)
Thread.Sleep(Math.Max(newPlayer.CD, GameData.checkInterval));
long lastTime = Environment.TickCount64;
new FrameRateTaskExecutor<int>(
loopCondition: () => gameMap.Timer.IsGaming && !newPlayer.IsResetting,
loopToDo: () =>
{
long nowTime = Environment.TickCount64;
if (newPlayer.BulletNum == newPlayer.MaxBulletNum)
lastTime = nowTime;
else if (nowTime - lastTime >= newPlayer.CD)
{
_ = newPlayer.TryAddBulletNum();
lastTime = nowTime;
}
},
timeInterval: GameData.checkInterval,
finallyReturn: () => 0
)
{
AllowTimeExceed = true/*,
MaxTolerantTimeExceedCount = 5,
TimeExceedAction = exceedTooMuch =>
{
if (exceedTooMuch) Console.WriteLine("The computer runs too slow that it cannot check the color below the player in time!");
}*/
}
.Start();
}
)
{ IsBackground = true }.Start();
#endregion
/* #region 人物装弹
new Thread
(
() =>
{
while (!gameMap.Timer.IsGaming)
Thread.Sleep(Math.Max(newPlayer.CD, GameData.checkInterval));
long lastTime = Environment.TickCount64;
new FrameRateTaskExecutor<int>(
loopCondition: () => gameMap.Timer.IsGaming && !newPlayer.IsResetting,
loopToDo: () =>
{
long nowTime = Environment.TickCount64;
if (newPlayer.BulletNum == newPlayer.MaxBulletNum)
lastTime = nowTime;
else if (nowTime - lastTime >= newPlayer.CD)
{
_ = newPlayer.TryAddBulletNum();
lastTime = nowTime;
}
},
timeInterval: GameData.checkInterval,
finallyReturn: () => 0
)
{
AllowTimeExceed = true,
}
.Start();
}
)
{ IsBackground = true }.Start();
#endregion
*/
#region BGM,牵制得分更新
new Thread
(


+ 1
- 1
logic/Preparation/Interface/ICharacter.cs View File

@@ -13,7 +13,7 @@ namespace Preparation.Interface
public PlayerStateType PlayerState { get; }
public BulletType BulletOfPlayer { get; set; }
public CharacterType CharacterType { get; }
public int BulletNum { get; }
public int UpdateBulletNum(int time);
public long ThreadNum { get; }

public bool IsGhost();


Loading…
Cancel
Save