Browse Source

feat: add alertness radius, concealment and BgmDictionary

tags/0.1.0
shangfengh 2 years ago
parent
commit
88a691e48e
8 changed files with 179 additions and 60 deletions
  1. +3
    -5
      logic/GameClass/GameObj/Character/Character.Skill.cs
  2. +39
    -0
      logic/GameClass/GameObj/Character/Character.cs
  3. +3
    -2
      logic/Gaming/ActionManager.cs
  4. +3
    -4
      logic/Gaming/AttackManager.cs
  5. +97
    -35
      logic/Gaming/Game.cs
  6. +16
    -1
      logic/Preparation/Interface/IOccupation.cs
  7. +7
    -0
      logic/Preparation/Utility/GameData.cs
  8. +11
    -13
      logic/规则Logic.md

logic/GameClass/GameObj/Character/Character.SkillManager.cs → logic/GameClass/GameObj/Character/Character.Skill.cs View File

@@ -53,11 +53,7 @@ namespace GameClass.GameObj

public bool IsGhost()
{
return this.CharacterType switch
{
CharacterType.Assassin => true,
_ => false,
};
return GameData.IsGhost(CharacterType);
}

protected Character(XY initPos, int initRadius, CharacterType characterType) :
@@ -88,6 +84,8 @@ namespace GameClass.GameObj
this.bulletNum = maxBulletNum;
this.bulletOfPlayer = Occupation.InitBullet;
this.OriBulletOfPlayer = Occupation.InitBullet;
this.concealment = Occupation.Concealment;
this.alertnessRadius = Occupation.AlertnessRadius;
this.characterType = characterType;

foreach (var activeSkill in this.Occupation.ListOfIActiveSkill)

+ 39
- 0
logic/GameClass/GameObj/Character/Character.cs View File

@@ -175,6 +175,45 @@ namespace GameClass.GameObj
}
}

private Dictionary<BgmType, double> bgmDictionary = new();
public Dictionary<BgmType, double> BgmDictionary
{
get => bgmDictionary;
set
{
lock (gameObjLock)
{
bgmDictionary = value;
}
}
}

private int alertnessRadius;
public int AlertnessRadius
{
get => alertnessRadius;
set
{
lock (gameObjLock)
{
alertnessRadius = value;
}
}
}

private double concealment;
public double Concealment
{
get => concealment;
set
{
lock (gameObjLock)
{
concealment = value;
}
}
}

/// <summary>
/// 进行一次远程攻击
/// </summary>


+ 3
- 2
logic/Gaming/ActionManager.cs View File

@@ -1,4 +1,5 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Threading;
using GameClass.GameObj;
@@ -38,7 +39,7 @@ namespace Gaming

public bool Fix(Student player)// 自动检查有无发电机可修
{
if (player.PlayerState != PlayerStateType.Null || player.IsGhost())
if (player.IsGhost() || (player.PlayerState != PlayerStateType.Null && player.PlayerState != PlayerStateType.IsMoving))
return false;
Generator? generatorForFix = null;

@@ -72,7 +73,7 @@ namespace Gaming
loopCondition: () => player.PlayerState == PlayerStateType.IsFixing && gameMap.Timer.IsGaming && generatorForFix.DegreeOfFRepair < GameData.degreeOfFixedGenerator && GameData.ApproachToInteract(player.Position, generatorForFix.Position),
loopToDo: () =>
{
return !generatorForFix.Repair(player.FixSpeed * GameData.frameDuration);
generatorForFix.Repair(player.FixSpeed * GameData.frameDuration);
},
timeInterval: GameData.frameDuration,
finallyReturn: () => 0


+ 3
- 4
logic/Gaming/AttackManager.cs View File

@@ -38,7 +38,7 @@ namespace Gaming
);
}

public void BeAddictedToGame(Student player)
private void BeAddictedToGame(Student player)
{
new Thread
(() =>
@@ -68,11 +68,10 @@ namespace Gaming
{ IsBackground = true }.Start();
}

public void Die(Character player)
private void Die(Character player)
{

player.CanMove = false;
player.IsResetting = true;
player.Die(PlayerStateType.IsDeceased);
// gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock();
// try
//{


+ 97
- 35
logic/Gaming/Game.cs View File

@@ -5,6 +5,7 @@ using Preparation.Utility;
using Timothy.FrameRateTask;
using Preparation.Interface;
using GameClass.GameObj;
using System.Numerics;

namespace Gaming
{
@@ -41,21 +42,14 @@ namespace Gaming
// Console.WriteLine($"x,y: {pos.x},{pos.y}");

Character newPlayer = (GameData.IsGhost(playerInitInfo.characterType)) ? new Ghost(pos, GameData.characterRadius, playerInitInfo.characterType) : new Student(pos, GameData.characterRadius, playerInitInfo.characterType);
gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock();
try
{
gameMap.GameObjDict[GameObjType.Character].Add(newPlayer);
}
finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock();
}
gameMap.Add(newPlayer);

// Console.WriteLine($"GameObjDict[GameObjType.Character] length:{gameMap.GameObjDict[GameObjType.Character].Count}");
teamList[(int)playerInitInfo.teamID].AddPlayer(newPlayer);
newPlayer.TeamID = playerInitInfo.teamID;
newPlayer.PlayerID = playerInitInfo.playerID;
new Thread //人物装弹
#region 人物装弹
new Thread
(
() =>
{
@@ -63,19 +57,16 @@ namespace Gaming
Thread.Sleep(newPlayer.CD);
long lastTime = Environment.TickCount64;
new FrameRateTaskExecutor<int>(
loopCondition: () => gameMap.Timer.IsGaming,
loopCondition: () => gameMap.Timer.IsGaming && !newPlayer.IsResetting,
loopToDo: () =>
{
if (!newPlayer.IsResetting)
long nowTime = Environment.TickCount64;
if (newPlayer.BulletNum == newPlayer.MaxBulletNum)
lastTime = nowTime;
if (nowTime - lastTime >= newPlayer.CD)
{
long nowTime = Environment.TickCount64;
if (newPlayer.BulletNum == newPlayer.MaxBulletNum)
lastTime = nowTime;
if (nowTime - lastTime >= newPlayer.CD)
{
_ = newPlayer.TryAddBulletNum();
lastTime = nowTime;
}
_ = newPlayer.TryAddBulletNum();
lastTime = nowTime;
}
},
timeInterval: GameData.checkInterval,
@@ -93,6 +84,91 @@ namespace Gaming
}
)
{ IsBackground = true }.Start();
#endregion
#region BGM更新
new Thread
(
() =>
{
while (!gameMap.Timer.IsGaming)
Thread.Sleep((int)GameData.checkInterval);
new FrameRateTaskExecutor<int>(
loopCondition: () => gameMap.Timer.IsGaming && !newPlayer.IsResetting,
loopToDo: () =>
{
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try
{
if (newPlayer.IsGhost())
{
double bgmVolume = 0;
foreach (Character person in gameMap.GameObjDict[GameObjType.Character])
{
if (!person.IsGhost() && XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment))
{
if ((double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position) > bgmVolume)
bgmVolume = newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position);
}
}
if (bgmVolume > 0)
newPlayer.BgmDictionary.Add(BgmType.StudentIsApproaching, bgmVolume);
}
else
{
foreach (Character person in gameMap.GameObjDict[GameObjType.Character])
{
if (person.IsGhost())
{
if (XY.Distance(newPlayer.Position, person.Position) <= (newPlayer.AlertnessRadius / person.Concealment))
newPlayer.BgmDictionary.Add(BgmType.GhostIsComing, (double)newPlayer.AlertnessRadius / XY.Distance(newPlayer.Position, person.Position));
break;
}
}
}
}
finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
}

gameMap.GameObjLockDict[GameObjType.Generator].EnterReadLock();
try
{
double bgmVolume = 0;
foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator])
{
if (XY.Distance(newPlayer.Position, generator.Position) <= newPlayer.AlertnessRadius)
{
if ((double)newPlayer.AlertnessRadius * generator.DegreeOfFRepair / GameData.degreeOfFixedGenerator / XY.Distance(newPlayer.Position, generator.Position) > bgmVolume)
bgmVolume = (double)newPlayer.AlertnessRadius * generator.DegreeOfFRepair / GameData.degreeOfFixedGenerator / XY.Distance(newPlayer.Position, generator.Position);
}
}
if (bgmVolume > 0)
newPlayer.BgmDictionary.Add(BgmType.StudentIsApproaching, bgmVolume);
}


finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
}
},
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

return newPlayer.ID;
}
@@ -100,20 +176,6 @@ namespace Gaming
{
if (gameMap.Timer.IsGaming)
return false;
gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();
try
{
foreach (Character player in gameMap.GameObjDict[GameObjType.Character])
{
player.CanMove = true;

player.AddShield(GameData.shieldTimeAtBirth);
}
}
finally
{
gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock();
}

propManager.StartProducing();



+ 16
- 1
logic/Preparation/Interface/IOccupation.cs View File

@@ -12,6 +12,8 @@ namespace Preparation.Interface
public int MaxBulletNum { get; }
public List<ActiveSkillType> ListOfIActiveSkill { get; }
public List<PassiveSkillType> ListOfIPassiveSkill { get; }
public double Concealment { get; }
public int AlertnessRadius { get; }
}

public interface IGhost : IOccupation
@@ -41,6 +43,12 @@ namespace Preparation.Interface

public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.BecomeInvisible, ActiveSkillType.UseKnife });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

public double concealment = GameData.basicConcealment * 1.5;
public double Concealment => concealment;

public int alertnessRadius = (int)(GameData.basicAlertnessRadius * 1.3);
public int AlertnessRadius => alertnessRadius;
}
public class Athlete : IStudent
{
@@ -61,6 +69,13 @@ namespace Preparation.Interface
public List<ActiveSkillType> ListOfIActiveSkill => new(new ActiveSkillType[] { ActiveSkillType.BeginToCharge });
public List<PassiveSkillType> ListOfIPassiveSkill => new(new PassiveSkillType[] { });

public int FixSpeed => GameData.basicFixSpeed / 10 * 6;
public const int fixSpeed = GameData.basicFixSpeed / 10 * 6;
public int FixSpeed => fixSpeed;

public const double concealment = GameData.basicConcealment * 0.9;
public double Concealment => concealment;

public const int alertnessRadius = (int)(GameData.basicAlertnessRadius * 0.9);
public int AlertnessRadius => alertnessRadius;
}
}

+ 7
- 0
logic/Preparation/Utility/GameData.cs View File

@@ -1,5 +1,6 @@
using System;
using System.Reflection.Metadata.Ecma335;
using System.Threading;

namespace Preparation.Utility
{
@@ -75,12 +76,15 @@ namespace Preparation.Utility
public const int basicMoveSpeed = 3800; // 基本移动速度,单位:s-1
public const int basicBulletMoveSpeed = 5400; // 基本子弹移动速度,单位:s-1
public const int characterMaxSpeed = 12000; // 最大速度
public const double basicConcealment = 1.0;
public const int basicAlertnessRadius = 30700;
public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分
public const int commonSkillCD = 30000; // 普通技能标准冷却时间
public const int commonSkillTime = 10000; // 普通技能标准持续时间
public const int bulletRadius = 200; // 默认子弹半径
public const int reviveTime = 30000; // 复活时间
public const int shieldTimeAtBirth = 3000; // 复活时的护盾时间

public static XY PosWhoDie = new XY(1, 1);

public static bool IsGhost(CharacterType characterType)
@@ -101,9 +105,12 @@ namespace Preparation.Utility
public const long GemProduceTime = 10000;
public const long PropProduceTime = 10000;
public const int PropDuration = 10000;
#endregion

#region 物体相关
public const int degreeOfFixedGenerator = 10300000;
#endregion

#region 游戏帧相关
public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长
#endregion


+ 11
- 13
logic/规则Logic.md View File

@@ -1,7 +1,7 @@
# 规则Logic

## 说明
- 版本V1.003
- 版本V2.0
- 该规则直接服务于Sever,并非选手版本
- *斜体表示Logic底层尚未(完全)实现*
- []表示待决定
@@ -23,13 +23,11 @@
- 底层实现中的属性,不代表界面全部都需要展示,也可能需要额外展示信息
- 只展示外部需要的属性,部分属性被省略

### Bgm
- *double bgmVolume*
- *BgmType bgmType*
对于枚举类BgmType
1. *不详的感觉:监管者进入(求生者的警戒半径/监管者的隐蔽度)时,求生者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离)*
2. *期待搞事的感觉:求生者进入(监管者的警戒半径/求生者的隐蔽度)时,监管者收到;监管者距离求生者越近,Bgm音量2.越大。bgmVolume=(警戒半径/二者距离)*
3. *修理电机的声音: 警戒半径内有电机正在被修理时,全员收到;bgmVolume=(警戒半径/二者距离)*电机修理程度/10300000*
### BgmType
- 枚举类BgmType
1. 不详的感觉:监管者进入(求生者的警戒半径/监管者的隐蔽度)时,求生者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/二者距离)
2. 期待搞事的感觉:求生者进入(监管者的警戒半径/求生者的隐蔽度)时,监管者收到;监管者距离求生者越近,Bgm音量越大。bgmVolume=(警戒半径/可被发觉的最近的求生者距离)
3. 修理电机的声音: 警戒半径内有电机正在被修理时收到;bgmVolume=(警戒半径*电机修理程度/二者距离)/10300000
~~~csharp
public enum BgmType
{
@@ -95,20 +93,20 @@
IsClimbingThroughWindows = 15,
}
~~~
- *Bgm(数组)*
- *Bgm(字典)*
- 得分
- ~~回血率/原始回血率~~
- 当前子弹类型
- 原始子弹类型
- 持有道具*(最多三个)(数组)*
- 持有道具 *(最多三个)(列表)*
- 是否隐身
- 队伍ID
- 玩家ID
- 当前Buff
- 职业类型
- 拥有的被动技能(数组)
- 拥有的主动技能(数组)
- 各个主动技能CD(数组)
- 拥有的被动技能(列表)
- 拥有的主动技能(列表)
- 各个主动技能CD(字典)
- *警戒半径*
- *double 隐蔽度*
- *翻墙速度*


Loading…
Cancel
Save