Browse Source

Merge pull request #419 from eesast/dev

fix: 🐛 fix the bug about attacking When clipping
tags/0.1.0
Du Liu GitHub 2 years ago
parent
commit
4b304f00c5
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 128 additions and 92 deletions
  1. +1
    -0
      CAPI/cpp/API/src/logic.cpp
  2. +1
    -0
      CAPI/python/PyAPI/logic.py
  3. +2
    -1
      docs/CAPI接口(python).md
  4. +6
    -3
      docs/QandA.md
  5. +1
    -0
      logic/GameClass/GameObj/Bullet/Bullet.cs
  6. +1
    -1
      logic/GameClass/GameObj/Character/Character.cs
  7. +107
    -81
      logic/GameEngine/MoveEngine.cs
  8. +1
    -0
      logic/Gaming/ActionManager.cs
  9. +6
    -3
      logic/Gaming/AttackManager.cs
  10. +0
    -2
      logic/Gaming/CharacterManager .cs
  11. +2
    -1
      logic/Preparation/Utility/GameData.cs

+ 1
- 0
CAPI/cpp/API/src/logic.cpp View File

@@ -618,6 +618,7 @@ void Logic::LoadBuffer(const protobuf::MessageToClient& message)
{ {
std::lock_guard<std::mutex> lock(mtxState); std::lock_guard<std::mutex> lock(mtxState);
std::swap(currentState, bufferState); std::swap(currentState, bufferState);
counterState = counterBuffer;
logger->info("Update State!"); logger->info("Update State!");
} }
freshed = true; freshed = true;


+ 1
- 0
CAPI/python/PyAPI/logic.py View File

@@ -476,6 +476,7 @@ class Logic(ILogic):
if Setting.asynchronous(): if Setting.asynchronous():
with self.__mtxState: with self.__mtxState:
self.__currentState, self.__bufferState = self.__bufferState, self.__currentState self.__currentState, self.__bufferState = self.__bufferState, self.__currentState
self.__counterState = self.__counterBuffer
self.__logger.info("Update state!") self.__logger.info("Update state!")
self.__freshed = True self.__freshed = True
else: else:


+ 2
- 1
docs/CAPI接口(python).md View File

@@ -8,7 +8,8 @@


#### 移动 #### 移动


- `def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为 x 轴,水平向右方向为 y 轴**因为移动过程中你会受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。
- `def Move(self, timeInMilliseconds: int, angle: float) -> Future[bool]`:移动,`timeInMilliseconds` 为移动时间,单位毫秒;`angleInRadian` 表示移动方向,单位弧度,使用极坐标,**竖直向下方向为 x 轴,水平向右方向为 y 轴**因为移动过程中你会受到多种干扰使得移动结果不符合你的预期;因此建议小步移动,边移动边考虑之后的行为。
- 5ms以内的移动指令会被禁止,你不应当使用过小的移动指令
- `def MoveRight(self, timeInMilliseconds: int) -> Future[bool]`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理 - `def MoveRight(self, timeInMilliseconds: int) -> Future[bool]`即向右移动,`MoveLeft`、`MoveDown`、`MoveUp`同理


#### 使用技能 #### 使用技能


+ 6
- 3
docs/QandA.md View File

@@ -62,12 +62,15 @@ A:
- 可能措施1. - 可能措施1.
首先保证Python版本在3.9及以上 首先保证Python版本在3.9及以上
- 可能措施2. 更换为国内镜像源 - 可能措施2. 更换为国内镜像源
在终端输入
`pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple`
在终端输入 `pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple`
- 可能措施3. 更新pip - 可能措施3. 更新pip
`python -m pip install --upgrade pip` (pip 版本最好为23.1) `python -m pip install --upgrade pip` (pip 版本最好为23.1)


## 比赛相关 ## 比赛相关
Q:职业数值会修改吗? Q:职业数值会修改吗?


A:初赛结束会调数值及机制,增加新角色
A:初赛结束会调数值及机制,增加新角色

Q:初赛后会修改什么呢?

A:技能冷却时间等属性设为不可见;出生点随机性或可选性;增强教师等职业,削弱职业;规范Debug信息

+ 1
- 0
logic/GameClass/GameObj/Bullet/Bullet.cs View File

@@ -36,6 +36,7 @@ namespace GameClass.GameObj


public override bool IgnoreCollideExecutor(IGameObj targetObj) public override bool IgnoreCollideExecutor(IGameObj targetObj)
{ {
if (targetObj == Parent && CanMove) return true;
if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) if (targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet)
return true; return true;
return false; return false;


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

@@ -594,7 +594,7 @@ namespace GameClass.GameObj
{ {
return true; return true;
} }
if (targetObj.Type == GameObjType.Character && XY.DistanceFloor3(targetObj.Position, this.Position) < this.Radius + targetObj.Radius)
if (targetObj.Type == GameObjType.Character && XY.DistanceCeil3(targetObj.Position, this.Position) < this.Radius + targetObj.Radius - GameData.adjustLength)
return true; return true;
return false; return false;
} }


+ 107
- 81
logic/GameEngine/MoveEngine.cs View File

@@ -91,106 +91,132 @@ namespace GameEngine
double deltaLen = moveVecLength - Math.Sqrt(obj.MovingSetPos(res, GetPlaceType(obj.Position + res))); // 转向,并用deltaLen存储行走的误差 double deltaLen = moveVecLength - Math.Sqrt(obj.MovingSetPos(res, GetPlaceType(obj.Position + res))); // 转向,并用deltaLen存储行走的误差
IGameObj? collisionObj = null; IGameObj? collisionObj = null;
bool isDestroyed = false; bool isDestroyed = false;
new FrameRateTaskExecutor<int>(
() => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting && obj.IsMoving,
() =>

bool flag; // 循环标志
do
{
flag = false;
collisionObj = collisionChecker.CheckCollision(obj, obj.Position);
if (collisionObj == null)
break;

switch (OnCollision(obj, collisionObj, res))
{ {
moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond;
res = new XY(direction, moveVecLength);
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
break;
case AfterCollision.MoveMax:
break;
}
} while (flag);


// 越界情况处理:如果越界,则与越界方块碰撞
bool flag; // 循环标志
do
if (!isDestroyed)
{
new FrameRateTaskExecutor<int>(
() => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting && obj.IsMoving,
() =>
{ {
flag = false;
collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res);
if (collisionObj == null)
break;
moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond;
res = new XY(direction, moveVecLength);


switch (OnCollision(obj, collisionObj, res))
// 越界情况处理:如果越界,则与越界方块碰撞
bool flag; // 循环标志
do
{ {
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
return false;
case AfterCollision.MoveMax:
MoveMax(obj, res);
moveVecLength = 0;
res = new XY(direction, moveVecLength);
flag = false;
collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res);
if (collisionObj == null)
break; break;
}
} while (flag);


deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res, GetPlaceType(obj.Position + res)));
switch (OnCollision(obj, collisionObj, res))
{
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
return false;
case AfterCollision.MoveMax:
MoveMax(obj, res);
moveVecLength = 0;
res = new XY(direction, moveVecLength);
break;
}
} while (flag);


return true;
},
GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond,
() =>
{
int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond);
bool flag;
do
deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res, GetPlaceType(obj.Position + res)));

return true;
},
GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond,
() =>
{ {
flag = false;
if (!isDestroyed)
int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond);
bool flag;
do
{ {
moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell;
res = new XY(direction, moveVecLength);
if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null)
{
obj.MovingSetPos(res, GetPlaceType(obj.Position + res));
}
else
flag = false;
if (!isDestroyed)
{ {
switch (OnCollision(obj, collisionObj, res))
moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell;
res = new XY(direction, moveVecLength);
if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null)
{
obj.MovingSetPos(res, GetPlaceType(obj.Position + res));
}
else
{ {
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
break;
case AfterCollision.MoveMax:
MoveMax(obj, res);
moveVecLength = 0;
res = new XY(direction, moveVecLength);
break;
switch (OnCollision(obj, collisionObj, res))
{
case AfterCollision.ContinueCheck:
flag = true;
break;
case AfterCollision.Destroyed:
Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game.");
isDestroyed = true;
break;
case AfterCollision.MoveMax:
MoveMax(obj, res);
moveVecLength = 0;
res = new XY(direction, moveVecLength);
break;
}
} }
} }
} while (flag);
if (leftTime > 0 && obj.IsMoving)
{
Thread.Sleep(leftTime); // 多移动的在这里补回来
} }
} while (flag);
if (leftTime > 0 && obj.IsMoving)
{
Thread.Sleep(leftTime); // 多移动的在这里补回来
}
lock (obj.MoveLock)
obj.IsMoving = false; // 结束移动
EndMove(obj);
return 0;
},
maxTotalDuration: moveTime
)
{
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
lock (obj.MoveLock)
obj.IsMoving = false; // 结束移动
EndMove(obj);
return 0;
},
maxTotalDuration: moveTime
)
{ {
if (b)
Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!");
AllowTimeExceed = true,
MaxTolerantTimeExceedCount = ulong.MaxValue,
TimeExceedAction = b =>
{
if (b)
Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!");


#if DEBUG #if DEBUG
else
{
Console.WriteLine("Debug info: Object moving time exceed for once.");
}
else
{
Console.WriteLine("Debug info: Object moving time exceed for once.");
}
#endif #endif
}
}.Start();
}
}.Start();
}
} }
).Start(); ).Start();
} }


+ 1
- 0
logic/Gaming/ActionManager.cs View File

@@ -35,6 +35,7 @@ namespace Gaming
} }
public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection) public bool MovePlayer(Character playerToMove, int moveTimeInMilliseconds, double moveDirection)
{ {
if (moveTimeInMilliseconds < 5) return false;
if (!playerToMove.Commandable() || !TryToStop()) return false; if (!playerToMove.Commandable() || !TryToStop()) return false;
characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving); characterManager.SetPlayerState(playerToMove, PlayerStateType.Moving);
moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection); moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection);


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

@@ -34,6 +34,7 @@ namespace Gaming
Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64);
if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty) if (obj.CanMove && ((Bullet)obj).TypeOfBullet != BulletType.JumpyDumpty)
BulletBomb((Bullet)obj, null); BulletBomb((Bullet)obj, null);
obj.CanMove = false;
} }
); );
this.characterManager = characterManager; this.characterManager = characterManager;
@@ -171,17 +172,19 @@ namespace Gaming
return false; return false;
Debugger.Output(player, player.CharacterType.ToString() + "Attack in " + player.BulletOfPlayer.ToString()); Debugger.Output(player, player.CharacterType.ToString() + "Attack in " + player.BulletOfPlayer.ToString());


Debugger.Output(player, player.Position.ToString() + " " + player.Radius.ToString() + " " + BulletFactory.BulletRadius(player.BulletOfPlayer).ToString());
XY res = player.Position + new XY // 子弹紧贴人物生成。 XY res = player.Position + new XY // 子弹紧贴人物生成。
( (
(int)((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Cos(angle)),
(int)((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Sin(angle))
(int)(Math.Abs((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Cos(angle))) * ((Math.Cos(angle) > 0) ? 1 : -1),
(int)(Math.Abs((player.Radius + BulletFactory.BulletRadius(player.BulletOfPlayer)) * Math.Sin(angle))) * ((Math.Sin(angle) > 0) ? 1 : -1)
); );


Bullet? bullet = player.Attack(res, gameMap.GetPlaceType(res)); Bullet? bullet = player.Attack(res, gameMap.GetPlaceType(res));


if (bullet != null) if (bullet != null)
{ {
Debugger.Output(player, "Attack in " + bullet.ToString());
player.FacingDirection = new(angle, bullet.BulletAttackRange);
Debugger.Output(bullet, "Attack in " + bullet.Position.ToString());
bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0; bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0;
bullet.CanMove = true; bullet.CanMove = true;
gameMap.Add(bullet); gameMap.Add(bullet);


+ 0
- 2
logic/Gaming/CharacterManager .cs View File

@@ -398,10 +398,8 @@ namespace Gaming
((SummonGolem)(((Golem)player).Parent.FindIActiveSkill(ActiveSkillType.SummonGolem))).GolemSummoned = null; ((SummonGolem)(((Golem)player).Parent.FindIActiveSkill(ActiveSkillType.SummonGolem))).GolemSummoned = null;
player.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false; player.FindIActiveSkill(ActiveSkillType.UseRobot).IsBeingUsed = false;
} }
gameMap.Remove(player);
return; return;
} }
gameMap.Remove(player);
++gameMap.NumOfDeceasedStudent; ++gameMap.NumOfDeceasedStudent;
} }




+ 2
- 1
logic/Preparation/Utility/GameData.cs View File

@@ -9,7 +9,8 @@ namespace Preparation.Utility
#region 基本常数 #region 基本常数
public const int numOfStepPerSecond = 20; // 每秒行走的步数 public const int numOfStepPerSecond = 20; // 每秒行走的步数


public const int tolerancesLength = 10;
public const int tolerancesLength = 3;
public const int adjustLength = 3;


public const int frameDuration = 50; // 每帧时长 public const int frameDuration = 50; // 每帧时长
public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长 public const int checkInterval = 50; // 检查位置标志、补充子弹的帧时长


Loading…
Cancel
Save