Browse Source

feat: Add the progress TimeBasedProgressAtVariableSpeed

dev
shangfengh 2 years ago
parent
commit
70604b56f8
7 changed files with 254 additions and 200 deletions
  1. +1
    -1
      logic/GameClass/GameObj/Character/Character.cs
  2. +3
    -55
      logic/GameClass/GameObj/Map/Doorway.cs
  3. +4
    -3
      logic/Gaming/ActionManager.cs
  4. +1
    -4
      logic/Preparation/Interface/IDoorway.cs
  5. +53
    -56
      logic/Preparation/Utility/SafeValue/InTheRange.cs
  6. +191
    -79
      logic/Preparation/Utility/SafeValue/TimeBased.cs
  7. +1
    -2
      logic/Server/CopyInfo.cs

+ 1
- 1
logic/GameClass/GameObj/Character/Character.cs View File

@@ -327,7 +327,7 @@ namespace GameClass.GameObj
case PlayerStateType.OpeningTheDoorway: case PlayerStateType.OpeningTheDoorway:
if (value == PlayerStateType.Rescued) return -1; if (value == PlayerStateType.Rescued) return -1;
Doorway doorway = (Doorway)lastObj!; Doorway doorway = (Doorway)lastObj!;
doorway.StopOpenning();
doorway.ProgressOfDoorway.TryStop();
return ChangePlayerState(runningState, value, gameObj); return ChangePlayerState(runningState, value, gameObj);
case PlayerStateType.OpeningTheDoor: case PlayerStateType.OpeningTheDoor:
if (value == PlayerStateType.Rescued) return -1; if (value == PlayerStateType.Rescued) return -1;


+ 3
- 55
logic/GameClass/GameObj/Map/Doorway.cs View File

@@ -17,70 +17,18 @@ namespace GameClass.GameObj
public override ShapeType Shape => ShapeType.Square; public override ShapeType Shape => ShapeType.Square;
public override bool IgnoreCollideExecutor(IGameObj targetObj) public override bool IgnoreCollideExecutor(IGameObj targetObj)
{ {
if (!IsOpen()) return false;
if (!ProgressOfDoorway.IsFinished()) return false;
if (targetObj.Type != GameObjType.Character) if (targetObj.Type != GameObjType.Character)
return true; // 非玩家不碰撞 return true; // 非玩家不碰撞
return false; return false;
} }


public AtomicBool PowerSupply { get; } = new(false); public AtomicBool PowerSupply { get; } = new(false);

private long openStartTime = 0;
public long OpenStartTime
{
get
{
lock (gameObjLock)
return openStartTime;
}
}
public TimeBasedProgressAtVariableSpeed ProgressOfDoorway { get; } = new(GameData.degreeOfOpenedDoorway, 1);
public bool TryToOpen() public bool TryToOpen()
{ {
if (!PowerSupply) return false; if (!PowerSupply) return false;
lock (gameObjLock)
{
if (openStartTime > 0) return false;
openStartTime = Environment.TickCount64;
return true;
}
return ProgressOfDoorway.Start();
} }

public bool StopOpenning()
{
lock (gameObjLock)
{
if (Environment.TickCount64 - openStartTime + openDegree >= GameData.degreeOfOpenedDoorway)
{
openDegree = GameData.degreeOfOpenedDoorway;
return true;
}
else
{
openDegree = (int)(Environment.TickCount64 - openStartTime) + openDegree;
openStartTime = 0;
return false;
}
}
}

public void FinishOpenning()
{
lock (gameObjLock)
{
openDegree = GameData.degreeOfOpenedDoorway;
}
}

private int openDegree = 0;
public int OpenDegree
{
get
{
lock (gameObjLock)
return openDegree;
}
}

public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway);
} }
} }

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

@@ -2,6 +2,7 @@
using System.Threading; using System.Threading;
using GameClass.GameObj; using GameClass.GameObj;
using GameEngine; using GameEngine;
using Preparation.Interface;
using Preparation.Utility; using Preparation.Utility;
using Timothy.FrameRateTask; using Timothy.FrameRateTask;


@@ -148,11 +149,11 @@ namespace Gaming
player.ThreadNum.Release(); player.ThreadNum.Release();
return; return;
} }
Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree);
Thread.Sleep(GameData.degreeOfOpenedDoorway - (int)doorwayToOpen.ProgressOfDoorway.GetProgressNow());


if (player.ResetPlayerState(stateNum)) if (player.ResetPlayerState(stateNum))
{ {
doorwayToOpen.FinishOpenning();
doorwayToOpen.ProgressOfDoorway.Finish();
player.ThreadNum.Release(); player.ThreadNum.Release();
} }
} }
@@ -168,7 +169,7 @@ namespace Gaming
return false; return false;


Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway);
if (doorwayForEscape != null && doorwayForEscape.IsOpen())
if (doorwayForEscape != null && doorwayForEscape.ProgressOfDoorway.IsProgressing())
{ {
if (!player.TryToRemoveFromGame(PlayerStateType.Escaped)) return false; if (!player.TryToRemoveFromGame(PlayerStateType.Escaped)) return false;
player.AddScore(GameData.StudentScoreEscape); player.AddScore(GameData.StudentScoreEscape);


+ 1
- 4
logic/Preparation/Interface/IDoorway.cs View File

@@ -4,9 +4,6 @@ namespace Preparation.Interface
{ {
public interface IDoorway : IGameObj public interface IDoorway : IGameObj
{ {
public long OpenStartTime { get; }
public int OpenDegree { get; }
public bool StopOpenning();
public bool TryToOpen();
public TimeBasedProgressAtVariableSpeed ProgressOfDoorway { get; }
} }
} }

+ 53
- 56
logic/Preparation/Utility/SafeValue/InTheRange.cs View File

@@ -24,8 +24,8 @@ namespace Preparation.Utility
/// </summary> /// </summary>
public class IntInTheVariableRange : InTheVariableRange public class IntInTheVariableRange : InTheVariableRange
{ {
private int v;
private int maxV;
protected int v;
protected int maxV;
#region 构造与读取 #region 构造与读取
public IntInTheVariableRange(int value, int maxValue) : base() public IntInTheVariableRange(int value, int maxValue) : base()
{ {
@@ -157,6 +157,13 @@ namespace Preparation.Utility
return true; return true;
} }
} }
public void SetVToMaxV()
{
lock (vLock)
{
v = maxV;
}
}
public bool Set0IfNotMaxor0() public bool Set0IfNotMaxor0()
{ {
lock (vLock) lock (vLock)
@@ -397,6 +404,32 @@ namespace Preparation.Utility
return v - previousV; return v - previousV;
} }
} }

/// <summary>
/// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue
/// 如果无法加到maxValue则清零
/// </summary>
/// <returns>返回是否清零</returns>
public bool Set0IfNotAddToMaxV(StartTime startTime, double speed = 1.0)
{
lock (vLock)
{
if (v == maxV) return false;
int addV = (int)(startTime.StopIfPassing(maxV - v) * speed);
if (addV < 0)
{
v = 0;
return true;
}
if (maxV - v < addV)
{
v = maxV;
return false;
}
v = 0;
return false;
}
}
#endregion #endregion
} }


@@ -405,8 +438,8 @@ namespace Preparation.Utility
/// </summary> /// </summary>
public class LongInTheVariableRange : InTheVariableRange public class LongInTheVariableRange : InTheVariableRange
{ {
private long v;
private long maxV;
protected long v;
protected long maxV;
#region 构造与读取 #region 构造与读取
public LongInTheVariableRange(long value, long maxValue) : base() public LongInTheVariableRange(long value, long maxValue) : base()
{ {
@@ -455,23 +488,6 @@ namespace Preparation.Utility
} }
#endregion #endregion


#region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据)
public (long, long) GetValue(StartTime startTime)
{
lock (vLock)
{
return (v, startTime.Get());
}
}
public (long, long, long) GetValueAndMaxV(StartTime startTime)
{
lock (vLock)
{
return (v, maxV, startTime.Get());
}
}
#endregion

#region 普通设置MaxV与Value的值的方法 #region 普通设置MaxV与Value的值的方法
/// <summary> /// <summary>
/// 若maxValue<=0则maxValue设为0并返回False /// 若maxValue<=0则maxValue设为0并返回False
@@ -645,6 +661,13 @@ namespace Preparation.Utility
return true; return true;
} }
} }
public void SetVToMaxV()
{
lock (vLock)
{
v = maxV;
}
}


public bool Set0IfNotMax() public bool Set0IfNotMax()
{ {
@@ -709,22 +732,6 @@ namespace Preparation.Utility
} }
} }


/// <summary>
/// 增加量为时间差*速度,并将startTime变为long.MaxValue
/// </summary>
/// <returns>返回实际改变量</returns>
public long AddV(StartTime startTime, double speed = 1.0)
{
lock (vLock)
{
long previousV = v;
long addV = (Environment.TickCount64 - startTime.Stop());
if (addV < 0) v += (long)(addV * speed);
else return 0;
if (v > maxV) v = maxV;
return v - previousV;
}
}
#endregion #endregion
} }


@@ -733,8 +740,8 @@ namespace Preparation.Utility
/// </summary> /// </summary>
public class DoubleInTheVariableRange : InTheVariableRange public class DoubleInTheVariableRange : InTheVariableRange
{ {
private double v;
private double maxV;
protected double v;
protected double maxV;
#region 构造与读取 #region 构造与读取
public DoubleInTheVariableRange(double value, double maxValue) : base() public DoubleInTheVariableRange(double value, double maxValue) : base()
{ {
@@ -783,23 +790,6 @@ namespace Preparation.Utility
} }
#endregion #endregion


#region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据)
public (double, long) GetValue(StartTime startTime)
{
lock (vLock)
{
return (v, startTime.Get());
}
}
public (double, double, long) GetValueAndMaxValue(StartTime startTime)
{
lock (vLock)
{
return (v, maxV, startTime.Get());
}
}
#endregion

#region 普通设置MaxV与Value的值的方法 #region 普通设置MaxV与Value的值的方法
/// <summary> /// <summary>
/// 若maxValue<=0则maxValue设为0并返回False /// 若maxValue<=0则maxValue设为0并返回False
@@ -949,6 +939,13 @@ namespace Preparation.Utility
return true; return true;
} }
} }
public void SetVToMaxV()
{
lock (vLock)
{
v = maxV;
}
}


public bool Set0IfNotMax() public bool Set0IfNotMax()
{ {


+ 191
- 79
logic/Preparation/Utility/SafeValue/TimeBased.cs View File

@@ -35,6 +35,197 @@ namespace Preparation.Utility
} }
} }


public class LongInTheVariableRangeWithStartTime : LongInTheVariableRange
{
public StartTime startTime = new();
public LongInTheVariableRangeWithStartTime(long value, long maxValue) : base(value, maxValue) { }
/// <summary>
/// 默认使Value=maxValue
/// </summary>
public LongInTheVariableRangeWithStartTime(long maxValue) : base(maxValue) { }
public LongInTheVariableRangeWithStartTime() : base() { }

#region 读取
public (long, long) GetValueWithStartTime()
{
lock (vLock)
{
return (v, startTime.Get());
}
}
public (long, long, long) GetValueAndMaxVWithStartTime()
{
lock (vLock)
{
return (v, maxV, startTime.Get());
}
}
#endregion

/// <summary>
/// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue
/// 如果无法加到maxValue则不加
/// </summary>
/// <returns>返回试图加到的值与最大值</returns>
public (long, long, long) AddStartTimeToMaxV(double speed = 1.0)
{
lock (vLock)
{
long addV = (long)(startTime.StopIfPassing(maxV - v) * speed);
if (addV < 0) return (v, maxV, startTime.Get());
if (maxV - v < addV) return (v = maxV, maxV, startTime.Get());
return (v + addV, maxV, startTime.Get());
}
}

/// <summary>
/// 增加量为时间差*速度,并将startTime变为long.MaxValue
/// </summary>
/// <returns>返回实际改变量</returns>
public long AddStartTime(double speed = 1.0)
{
lock (vLock)
{
long previousV = v;
long addV = (Environment.TickCount64 - startTime.Stop());
if (addV < 0) v += (long)(addV * speed);
else return 0;
if (v > maxV) v = maxV;
return v - previousV;
}
}

/// <summary>
/// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上
/// 如果无法加到maxValue则清零
/// 无论如何startTime变为long.MaxValue
/// </summary>
/// <returns>返回是否清零</returns>
public bool Set0IfNotAddStartTimeToMaxV(double speed = 1.0)
{
lock (vLock)
{
if (v == maxV) return false;
long addV = (long)(startTime.Stop() * speed);
if (addV < 0)
{
v = 0;
return true;
}
if (maxV - v < addV)
{
v = maxV;
return false;
}
v = 0;
return false;
}
}

public void SetAndStop(long value = 0)
{
lock (vLock)
{
this.v = value;
startTime.Stop();
}
}
}

public class TimeBasedProgressAtVariableSpeed
{
private LongInTheVariableRangeWithStartTime progress;
public AtomicDouble speed;

#region 构造
public TimeBasedProgressAtVariableSpeed(long needProgress, double speed = 1.0)
{
progress = new LongInTheVariableRangeWithStartTime(0, needProgress);
if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0.");
this.speed = new(speed);
}
public TimeBasedProgressAtVariableSpeed()
{
progress = new LongInTheVariableRangeWithStartTime(0, 0);
this.speed = new(1.0);
}
#endregion

#region 读取
public override string ToString()
{
long progressStored, lastStartTime;
(progressStored, lastStartTime) = progress.GetValueWithStartTime();
return "ProgressStored: " + progressStored.ToString()
+ " ; LastStartTime: " + lastStartTime.ToString() + "ms"
+ " ; Speed: " + speed.ToString();
}
public long GetProgressNow() => progress.AddStartTimeToMaxV((double)speed).Item1;
public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.AddStartTimeToMaxV((double)speed);
public long GetProgressStored() => progress.GetValue();
public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV();
public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxVWithStartTime();

public bool IsFinished()
{
long progressNow, needTime;
(progressNow, needTime, _) = progress.AddStartTimeToMaxV((double)speed);
return progressNow == needTime;
}
public bool IsProgressing()
{
long progressNow, needTime, startT;
(progressNow, needTime, startT) = progress.AddStartTimeToMaxV((double)speed);
return (startT != long.MaxValue && progressNow != needTime);
}
#endregion

public bool Start(long needTime)
{
if (needTime <= 2)
{
Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0.");
return false;
}
if (progress.startTime.Start() != long.MaxValue) return false;
progress.SetMaxV(needTime);
return true;
}
public bool Start()
{
return progress.startTime.Start() == long.MaxValue;
}
/// <summary>
/// 使进度条强制终止清零
/// </summary>
public void Set0()
{
progress.SetAndStop();
}
/// <summary>
/// 如果进度条加上时间差不能为满,使进度条强制终止清零
/// </summary>
public void TryStop()
{
progress.Set0IfNotAddStartTimeToMaxV(speed);
}
/// <summary>
/// 使进度条暂停
/// </summary>
public bool Pause()
{
return progress.AddStartTime((double)speed) != 0;
}
/// <summary>
/// 使进度条进度为满
/// </summary>
public void Finish()
{
progress.SetVToMaxV();
progress.startTime.Stop();
}
}

/// <summary> /// <summary>
/// 根据时间推算Start后完成多少进度的进度条(long)。 /// 根据时间推算Start后完成多少进度的进度条(long)。
/// 只允许Start(清零状态的进度条才可以Start)时修改needTime(请确保大于0); /// 只允许Start(清零状态的进度条才可以Start)时修改needTime(请确保大于0);
@@ -158,85 +349,6 @@ namespace Preparation.Utility
//增加其他新的写操作可能导致不安全 //增加其他新的写操作可能导致不安全
} }


public class TimeBasedProgressAtVariableSpeed
{
public LongInTheVariableRange progress;
public StartTime startTime = new();
public AtomicDouble speed;

#region 构造
public TimeBasedProgressAtVariableSpeed(long needProgress, double speed)
{
if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0.");
this.progress = new(0, needProgress);
this.speed = new(speed);
}
public TimeBasedProgressAtVariableSpeed()
{
this.progress = new(0, 0);
this.speed = new(1.0);
}
#endregion

#region 读取
public override string ToString()
{
return "ProgressStored: " + progress.ToString()
+ " ; LastStartTime: " + startTime.ToString() + "ms"
+ " ; Speed: " + speed.ToString();
}
public long GetProgressNow() => progress.TryAddToMaxV(startTime, (double)speed).Item1;
public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.TryAddToMaxV(startTime, (double)speed);
public long GetProgressStored() => progress.GetValue();
public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV();
public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxV(startTime);

public bool IsFinished()
{
long progressNow, needTime;
(progressNow, needTime, _) = progress.TryAddToMaxV(startTime);
return progressNow == needTime;
}
public bool IsProgressing()
{
long progressNow, needTime, startT;
(progressNow, needTime, startT) = progress.TryAddToMaxV(startTime);
return (startT != long.MaxValue && progressNow != needTime);
}
#endregion

public bool Start(long needTime)
{
if (needTime <= 2)
{
Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0.");
return false;
}
if (startTime.Start() != long.MaxValue) return false;
progress.SetMaxV(needTime);
return true;
}
public bool Start()
{
return startTime.Start() == long.MaxValue;
}
/// <summary>
/// 使进度条强制终止清零
/// </summary>
public void Set0()
{
startTime.Stop();
progress.SetPositiveV(0);
}
/// <summary>
/// 使进度条暂停
/// </summary>
public bool Pause()
{
return progress.AddV(startTime, (double)speed) != 0;
}
}

/// <summary> /// <summary>
/// 冷却时间为可变的CDms的bool,不支持查看当前进度,初始为True /// 冷却时间为可变的CDms的bool,不支持查看当前进度,初始为True
/// </summary> /// </summary>


+ 1
- 2
logic/Server/CopyInfo.cs View File

@@ -232,8 +232,7 @@ namespace Server
Y = doorway.Position.y Y = doorway.Position.y
} }
}; };
int progress = ((doorway.OpenStartTime > 0) ? ((int)(time - doorway.OpenStartTime)) : 0) + doorway.OpenDegree;
msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress;
msg.GateMessage.Progress = (int)doorway.ProgressOfDoorway.GetProgressNow();
return msg; return msg;
} }
private static MessageOfObj HiddenGate(EmergencyExit Exit) private static MessageOfObj HiddenGate(EmergencyExit Exit)


Loading…
Cancel
Save