Browse Source

fix: 🐛 fix the initposition about JumpyDumpty

tags/v0.1.0
shangfengh 2 years ago
parent
commit
a541c68907
10 changed files with 101 additions and 75 deletions
  1. +5
    -1
      docs/版本更新说明.md
  2. +0
    -2
      logic/GameClass/GameObj/Character/Character.Skill.cs
  3. +17
    -20
      logic/GameClass/GameObj/Character/Character.cs
  4. +16
    -11
      logic/GameClass/GameObj/Moveable.cs
  5. +8
    -8
      logic/GameEngine/MoveEngine.cs
  6. +15
    -15
      logic/Gaming/ActionManager.cs
  7. +30
    -7
      logic/Gaming/AttackManager.cs
  8. +8
    -9
      logic/Gaming/CharacterManager .cs
  9. +1
    -1
      logic/Preparation/Interface/ICharacter.cs
  10. +1
    -1
      logic/Preparation/Interface/IMoveable.cs

+ 5
- 1
docs/版本更新说明.md View File

@@ -17,5 +17,9 @@
- feat:增加了可选地图功能
- **脚本RunServer(ForDebug).cmd/sh现在支持可选地图功能,但想选择地图,选手需要自行参照使用文档修改命令行或在云盘下载脚本**

# 5月9日更新
- docs:更新了 游戏机制与平衡性调整更新草案.pdf
- change:更改了地图的文件路径

# 最新更新
- docs:更新了 游戏机制与平衡性调整更新草案.pdf
-

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

@@ -1,8 +1,6 @@
using Preparation.Utility;
using Preparation.Interface;
using System.Collections.Generic;
using System;
using System.Numerics;

namespace GameClass.GameObj
{


+ 17
- 20
logic/GameClass/GameObj/Character/Character.cs View File

@@ -2,15 +2,14 @@
using Preparation.Utility;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;

namespace GameClass.GameObj
{
public partial class Character : Moveable, ICharacter // 负责人LHR摆烂终了
{
#region 装弹、攻击相关的基本属性及方法
private readonly object attackLock = new();
public object AttackLock => attackLock;

/// <summary>
/// 装弹冷却
/// </summary>
@@ -19,7 +18,7 @@ namespace GameClass.GameObj
{
get
{
lock (attackLock)
lock (actionLock)
{
return cd;
}
@@ -33,14 +32,14 @@ namespace GameClass.GameObj
{
get
{
lock (attackLock)
lock (actionLock)
{
return bulletOfPlayer;
}
}
set
{
lock (attackLock)
lock (actionLock)
{
bulletOfPlayer = value;
cd = OrgCD = (BulletFactory.BulletCD(value));
@@ -55,7 +54,7 @@ namespace GameClass.GameObj
{
get
{
lock (attackLock)
lock (actionLock)
{
return maxBulletNum;
}
@@ -66,7 +65,7 @@ namespace GameClass.GameObj

public int UpdateBulletNum(int time)
{
lock (attackLock)
lock (actionLock)
{
if (bulletNum < maxBulletNum)
{
@@ -84,7 +83,7 @@ namespace GameClass.GameObj
/// <returns>攻击操作发出的子弹</returns>
public Bullet? Attack(double angle, int time)
{
lock (attackLock)
lock (actionLock)
{
if (bulletOfPlayer == BulletType.Null)
return null;
@@ -92,10 +91,11 @@ namespace GameClass.GameObj
{
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)
(int)(Math.Abs((Radius + BulletFactory.BulletRadius(bulletOfPlayer)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)),
(int)(Math.Abs((Radius + BulletFactory.BulletRadius(bulletOfPlayer)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle))
);
Bullet? bullet = BulletFactory.GetBullet(this, res);
if (bullet == null) return null;
@@ -326,14 +326,11 @@ namespace GameClass.GameObj
private GameObj? whatInteractingWith = null;
public GameObj? WhatInteractingWith => whatInteractingWith;

private long threadNum = 0;
public long ThreadNum => threadNum;

public void ChangePlayerState(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (moveObjLock)
lock (actionLock)
{
++threadNum;
stateNum= Interlocked.Increment(ref stateNum);
whatInteractingWith = gameObj;
if (value != PlayerStateType.Moving)
IsMoving = false;
@@ -344,7 +341,7 @@ namespace GameClass.GameObj

public void ChangePlayerStateInOneThread(PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (moveObjLock)
lock (actionLock)
{
whatInteractingWith = gameObj;
if (value != PlayerStateType.Moving)
@@ -356,9 +353,9 @@ namespace GameClass.GameObj

public void SetPlayerStateNaturally()
{
lock (moveObjLock)
lock (actionLock)
{
++threadNum;
stateNum= Interlocked.Increment(ref stateNum);
whatInteractingWith = null;
IsMoving = false;
playerState = PlayerStateType.Null;
@@ -370,7 +367,7 @@ namespace GameClass.GameObj
MoveReaderWriterLock.EnterWriteLock();
try
{
lock (moveObjLock)
lock (actionLock)
{
playerState = playerStateType;
canMove = false;


+ 16
- 11
logic/GameClass/GameObj/Moveable.cs View File

@@ -6,17 +6,22 @@ namespace GameClass.GameObj
{
public abstract class Moveable : GameObj, IMoveable
{
protected readonly object moveObjLock = new();
public object MoveLock => moveObjLock;
protected readonly object actionLock = new();
public object ActionLock => actionLock;
private readonly ReaderWriterLockSlim moveReaderWriterLock = new();
public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock;
//规定moveReaderWriterLock>moveObjLock
protected long stateNum = 0;
public long StateNum
{
get=>Interlocked.Read(ref stateNum);
}
//规定moveReaderWriterLock>actionLock

public override XY Position
{
get
{
lock (moveObjLock)
lock (actionLock)
return position;
}
}
@@ -25,7 +30,7 @@ namespace GameClass.GameObj
{
get
{
lock (moveObjLock)
lock (actionLock)
return facingDirection;
}
}
@@ -35,12 +40,12 @@ namespace GameClass.GameObj
{
get
{
lock (moveObjLock)
lock (actionLock)
return isMoving;
}
set
{
lock (moveObjLock)
lock (actionLock)
{
isMoving = value;
}
@@ -51,7 +56,7 @@ namespace GameClass.GameObj
public long MovingSetPos(XY moveVec)
{
if (moveVec.x != 0 || moveVec.y != 0)
lock (moveObjLock)
lock (actionLock)
{
facingDirection = moveVec;
this.position += moveVec;
@@ -61,7 +66,7 @@ namespace GameClass.GameObj

public void ReSetPos(XY position)
{
lock (moveObjLock)
lock (actionLock)
{
this.position = position;
}
@@ -88,7 +93,7 @@ namespace GameClass.GameObj
moveReaderWriterLock.EnterWriteLock();
try
{
lock (moveObjLock)
lock (actionLock)
{
canMove = value;
}
@@ -141,7 +146,7 @@ namespace GameClass.GameObj
moveReaderWriterLock.EnterWriteLock();
try
{
lock (moveObjLock)
lock (actionLock)
{
moveSpeed = value;
}


+ 8
- 8
logic/GameEngine/MoveEngine.cs View File

@@ -80,12 +80,12 @@ namespace GameEngine
if (!obj.IsAvailable || !gameTimer.IsGaming)
return;

long threadNum = (obj.Type == GameObjType.Character) ? ((ICharacter)obj).ThreadNum : 0;//对人特殊处理
long threadNum = (obj.Type == GameObjType.Character) ? ((ICharacter)obj).StateNum : 0;//对人特殊处理
new Thread
(
() =>
{
lock (obj.MoveLock)
lock (obj.ActionLock)
obj.IsMoving = true;

double moveVecLength = 0.0;
@@ -126,7 +126,7 @@ namespace GameEngine
res = new XY(direction, moveVecLength);

//对人特殊处理
if (threadNum > 0 && ((ICharacter)obj).ThreadNum != threadNum) return false;
if (threadNum > 0 && ((ICharacter)obj).StateNum != threadNum) return false;

// 越界情况处理:如果越界,则与越界方块碰撞
bool flag; // 循环标志
@@ -147,7 +147,7 @@ namespace GameEngine
isDestroyed = true;
return false;
case AfterCollision.MoveMax:
if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum)
if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum)
MoveMax(obj, res);
moveVecLength = 0;
res = new XY(direction, moveVecLength);
@@ -155,7 +155,7 @@ namespace GameEngine
}
} while (flag);

if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum)
if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum)
deltaLen += moveVecLength - Math.Sqrt(obj.MovingSetPos(res));

return true;
@@ -174,7 +174,7 @@ namespace GameEngine
res = new XY(direction, moveVecLength);
if ((collisionObj = collisionChecker.CheckCollisionWhenMoving(obj, res)) == null)
{
if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum)
if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum)
obj.MovingSetPos(res);
}
else
@@ -189,7 +189,7 @@ namespace GameEngine
isDestroyed = true;
break;
case AfterCollision.MoveMax:
if (threadNum == 0 || ((ICharacter)obj).ThreadNum == threadNum)
if (threadNum == 0 || ((ICharacter)obj).StateNum == threadNum)
MoveMax(obj, res);
moveVecLength = 0;
res = new XY(direction, moveVecLength);
@@ -202,7 +202,7 @@ namespace GameEngine
{
Thread.Sleep(leftTime); // 多移动的在这里补回来
}
lock (obj.MoveLock)
lock (obj.ActionLock)
obj.IsMoving = false; // 结束移动
EndMove(obj);
return 0;


+ 15
- 15
logic/Gaming/ActionManager.cs View File

@@ -72,14 +72,14 @@ namespace Gaming

++generatorForFix.NumOfFixing;
characterManager.SetPlayerState(player, PlayerStateType.Fixing);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;
new Thread
(
() =>
{
Thread.Sleep(GameData.frameDuration);
new FrameRateTaskExecutor<int>(
loopCondition: () => gameMap.Timer.IsGaming && threadNum == player.ThreadNum,
loopCondition: () => gameMap.Timer.IsGaming && threadNum == player.StateNum,
loopToDo: () =>
{
if (generatorForFix.Repair(player.FixSpeed * GameData.frameDuration, player))
@@ -173,10 +173,10 @@ namespace Gaming
{
characterManager.SetPlayerState(playerTreated, PlayerStateType.Treated);
characterManager.SetPlayerState(player, PlayerStateType.Treating);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;

new FrameRateTaskExecutor<int>(
loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopCondition: () => playerTreated.PlayerState == PlayerStateType.Treated && threadNum == player.StateNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
if (playerTreated.AddDegreeOfTreatment(GameData.frameDuration * player.TreatSpeed, player))
@@ -187,7 +187,7 @@ namespace Gaming
)
.Start();

if (threadNum == player.ThreadNum) characterManager.SetPlayerState(player);
if (threadNum == player.StateNum) characterManager.SetPlayerState(player);
else if (playerTreated.PlayerState == PlayerStateType.Treated) characterManager.SetPlayerState(playerTreated);
}
)
@@ -205,14 +205,14 @@ namespace Gaming
return false;
characterManager.SetPlayerState(player, PlayerStateType.Rescuing);
characterManager.SetPlayerState(playerRescued, PlayerStateType.Rescued);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;

new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopCondition: () => playerRescued.PlayerState == PlayerStateType.Rescued && threadNum == player.StateNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
playerRescued.TimeOfRescue += GameData.frameDuration;
@@ -234,7 +234,7 @@ namespace Gaming
else
characterManager.SetPlayerState(playerRescued, PlayerStateType.Addicted);
}
if (threadNum == player.ThreadNum) characterManager.SetPlayerState(player);
if (threadNum == player.StateNum) characterManager.SetPlayerState(player);
playerRescued.TimeOfRescue = 0;
}
)
@@ -303,14 +303,14 @@ namespace Gaming
// gameMap.Add(addWall);

characterManager.SetPlayerState(player, PlayerStateType.ClimbingThroughWindows);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;
windowForClimb.WhoIsClimbing = player;
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming,
loopToDo: () => { },
timeInterval: GameData.frameDuration,
finallyReturn: () => 0,
@@ -329,7 +329,7 @@ namespace Gaming
moveEngine.MoveObj(player, (int)(windowToPlayer.Length() * 3.0 * 1000 / player.MoveSpeed), (-1 * windowToPlayer).Angle());

new FrameRateTaskExecutor<int>(
loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
},
@@ -343,7 +343,7 @@ namespace Gaming
player.MoveSpeed = player.ReCalculateBuff(BuffType.AddSpeed, player.OrgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed);
windowForClimb.WhoIsClimbing = null;
// gameMap.Remove(addWall);
if (threadNum == player.ThreadNum)
if (threadNum == player.StateNum)
{
characterManager.SetPlayerState(player);
}
@@ -386,13 +386,13 @@ namespace Gaming
if (!flag) return false;

characterManager.SetPlayerState(player, PlayerStateType.LockingOrOpeningTheDoor);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;
new Thread
(
() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => flag && threadNum == player.ThreadNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
loopCondition: () => flag && threadNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
loopToDo: () =>
{
flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null);
@@ -407,7 +407,7 @@ namespace Gaming
{
doorToLock.IsOpen = (!doorToLock.IsOpen);
}
if (threadNum == player.ThreadNum)
if (threadNum == player.StateNum)
characterManager.SetPlayerState(player);
doorToLock.OpenOrLockDegree = 0;
}


+ 30
- 7
logic/Gaming/AttackManager.cs View File

@@ -39,6 +39,17 @@ namespace Gaming
this.characterManager = characterManager;
}

public void ProduceBulletNaturally(BulletType bulletType, Character player, double angle,XY pos)
{
// 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange
if (bulletType == BulletType.Null)return;
Bullet? bullet = BulletFactory.GetBullet(player, pos);
if (bullet == null) return;
Debugger.Output(bullet, "Attack in " + pos.ToString());
gameMap.Add(bullet);
moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(bulletType)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms
}

private void BombObj(Bullet bullet, GameObj objBeingShot)
{
#if DEBUG
@@ -122,9 +133,21 @@ namespace Gaming

if (bullet.TypeOfBullet == BulletType.BombBomb && objBeingShot != null)
{
bullet.Parent!.BulletOfPlayer = BulletType.JumpyDumpty;
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI / 2.0);
Attack((Character)bullet.Parent, bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0);
double angle = bullet.FacingDirection.Angle() + Math.PI / 2.0;
XY pos = bullet.Position + new XY // 子弹紧贴人物生成。
(
(int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)),
(int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle))
);
ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent, angle, pos);

angle = bullet.FacingDirection.Angle() + Math.PI * 3.0 / 2.0;
pos = bullet.Position + new XY // 子弹紧贴人物生成。
(
(int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Cos(angle))) * Math.Sign(Math.Cos(angle)),
(int)(Math.Abs((bullet.Radius + BulletFactory.BulletRadius(BulletType.JumpyDumpty)) * Math.Sin(angle))) * Math.Sign(Math.Sin(angle))
);
ProduceBulletNaturally(BulletType.JumpyDumpty, (Character)bullet.Parent, angle, pos);
}

var beAttackedList = new List<IGameObj>();
@@ -173,17 +196,17 @@ namespace Gaming
Debugger.Output(bullet, "Attack in " + bullet.Position.ToString());
bullet.AP += player.TryAddAp() ? GameData.ApPropAdd : 0;
gameMap.Add(bullet);
moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms
moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(bullet.TypeOfBullet)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms
if (bullet.CastTime > 0)
{
characterManager.SetPlayerState(player, PlayerStateType.TryingToAttack);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;

new Thread
(() =>
{
new FrameRateTaskExecutor<int>(
loopCondition: () => threadNum == player.ThreadNum && gameMap.Timer.IsGaming,
loopCondition: () => threadNum == player.StateNum && gameMap.Timer.IsGaming,
loopToDo: () =>
{
},
@@ -195,7 +218,7 @@ namespace Gaming

if (gameMap.Timer.IsGaming)
{
if (threadNum == player.ThreadNum)
if (threadNum == player.StateNum)
{
characterManager.SetPlayerState(player);
}


+ 8
- 9
logic/Gaming/CharacterManager .cs View File

@@ -1,5 +1,4 @@
using System;
using System.Threading;
using System.Threading;
using GameClass.GameObj;
using Preparation.Utility;
using Preparation.Interface;
@@ -20,7 +19,7 @@ namespace Gaming

public void SetPlayerState(Character player, PlayerStateType value = PlayerStateType.Null, GameObj? gameObj = null)
{
lock (player.MoveLock)
lock (player.ActionLock)
{
switch (player.PlayerState)
{
@@ -246,7 +245,7 @@ namespace Gaming
}
}
SetPlayerState(player, PlayerStateType.Addicted);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;
new Thread
(() =>
{
@@ -254,7 +253,7 @@ namespace Gaming
Debugger.Output(player, " is addicted ");
#endif
new FrameRateTaskExecutor<int>(
() => threadNum == player.ThreadNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming,
() => threadNum == player.StateNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming,
() =>
{
player.GamingAddiction += (player.PlayerState == PlayerStateType.Addicted) ? GameData.frameDuration : 0;
@@ -283,9 +282,9 @@ namespace Gaming
(() =>
{
SetPlayerState(player, PlayerStateType.Stunned);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;
Thread.Sleep(time);
if (threadNum == player.ThreadNum)
if (threadNum == player.StateNum)
SetPlayerState(player);
}
)
@@ -373,14 +372,14 @@ namespace Gaming
if (time <= 0) return false;
if (player.PlayerState == PlayerStateType.Swinging || (!player.Commandable() && player.PlayerState != PlayerStateType.TryingToAttack)) return false;
SetPlayerState(player, PlayerStateType.Swinging);
long threadNum = player.ThreadNum;
long threadNum = player.StateNum;

new Thread
(() =>
{
Thread.Sleep(time);

if (threadNum == player.ThreadNum)
if (threadNum == player.StateNum)
{
SetPlayerState(player);
}


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

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

public bool IsGhost();
}


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

@@ -5,7 +5,7 @@ namespace Preparation.Interface
{
public interface IMoveable : IGameObj
{
object MoveLock { get; }
object ActionLock { get; }
public int MoveSpeed { get; }
public bool IsMoving { get; set; }
public bool IsResetting { get; } // reviving


Loading…
Cancel
Save