diff --git a/logic/GameClass/GameObj/BombedBullet.cs b/logic/GameClass/GameObj/Bullet/BombedBullet.cs similarity index 100% rename from logic/GameClass/GameObj/BombedBullet.cs rename to logic/GameClass/GameObj/Bullet/BombedBullet.cs diff --git a/logic/GameClass/GameObj/Bullet.cs b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs similarity index 51% rename from logic/GameClass/GameObj/Bullet.cs rename to logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs index d861351..4eb48cb 100644 --- a/logic/GameClass/GameObj/Bullet.cs +++ b/logic/GameClass/GameObj/Bullet/Bullet.Ghost.cs @@ -4,44 +4,48 @@ using System; namespace GameClass.GameObj { - public abstract class Bullet : ObjOfCharacter + internal sealed class CommonAttackOfGhost : Bullet { - /// - /// //攻击力 - /// - public abstract int AP { get; } - public abstract int Speed { get; } - - private readonly bool hasSpear; - /// - /// 是否有矛 - /// - public bool HasSpear => hasSpear; - - /// - /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target - /// - /// 被尝试攻击者 - /// 是否可以攻击到 - public abstract bool CanAttack(GameObj target); - - protected override bool IgnoreCollideExecutor(IGameObj targetObj) + public CommonAttackOfGhost(Character player, int radius = GameData.bulletRadius) : + base(player, radius) + { + } + public override double BulletBombRange => 0; + public override double BulletAttackRange => GameData.basicAttackShortRange; + public override int AP => GameData.basicApOfGhost; + public override int Speed => GameData.basicBulletMoveSpeed; + public override bool IsToBomb => false; + public override int Backswing => GameData.basicBackswing; + public override int RecoveryFromHit => GameData.basicRecoveryFromHit; + public override bool CanAttack(GameObj target) { - if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) - return true; return false; } - public Bullet(Character player, int radius) : - base(player.Position, radius, PlaceType.Null, GameObjType.Bullet) + + public override BulletType TypeOfBullet => BulletType.CommonAttackOfGhost; + + } + internal sealed class FlyingKnife : Bullet + { + public FlyingKnife(Character player, int radius = GameData.bulletRadius) : + base(player, radius) + { + } + public override double BulletBombRange => 0; + public override double BulletAttackRange => GameData.basicAttackShortRange * 13; + public override int AP => GameData.basicApOfGhost / 3 * 7; + public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2; + public override bool IsToBomb => true; + public override int Backswing => GameData.basicBackswing; + public override int RecoveryFromHit => GameData.basicRecoveryFromHit; + public override bool CanAttack(GameObj target) { - this.CanMove = true; - this.moveSpeed = this.Speed; - this.hasSpear = player.HasSpear; - this.Parent = player; + // 圆形攻击范围 + return XY.Distance(this.Position, target.Position) <= BulletBombRange; } - public override bool IsRigid => true; // 默认为true - public override ShapeType Shape => ShapeType.Circle; // 默认为圆形 - public abstract BulletType TypeOfBullet { get; } + + public override BulletType TypeOfBullet => BulletType.FlyingKnife; + } internal sealed class AtomBomb : Bullet @@ -50,10 +54,13 @@ namespace GameClass.GameObj base(player, radius) { } - public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 7; - public const double BulletAttackRange = GameData.basicAttackRange / 9 * 7; - public override int AP => GameData.basicAp / 3 * 7; + public override double BulletBombRange => GameData.basicBulletBombRange / 3 * 7; + public override double BulletAttackRange => GameData.basicAttackShortRange / 9 * 7; + public override int AP => GameData.basicApOfGhost / 3 * 7; public override int Speed => GameData.basicBulletMoveSpeed / 3 * 2; + public override int Backswing => GameData.basicBackswing; + public override int RecoveryFromHit => GameData.basicRecoveryFromHit; + public override bool IsToBomb => true; public override bool CanAttack(GameObj target) { // 圆形攻击范围 @@ -61,6 +68,7 @@ namespace GameClass.GameObj } public override BulletType TypeOfBullet => BulletType.AtomBomb; + } internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速 @@ -69,10 +77,13 @@ namespace GameClass.GameObj base(player, radius) { } - public const double BulletBombRange = GameData.basicBulletBombRange / 6 * 5; - public const double BulletAttackRange = GameData.basicAttackRange / 2; - public override int AP => GameData.basicAp / 6 * 5; + public override double BulletBombRange => GameData.basicBulletBombRange / 6 * 5; + public override double BulletAttackRange => GameData.basicAttackShortRange / 2; + public override int AP => GameData.basicApOfGhost / 6 * 5; public override int Speed => GameData.basicBulletMoveSpeed / 6 * 5; + public override int Backswing => GameData.basicBackswing; + public override int RecoveryFromHit => GameData.basicRecoveryFromHit; + public override bool IsToBomb => true; public override bool CanAttack(GameObj target) { // 圆形攻击范围 @@ -88,10 +99,13 @@ namespace GameClass.GameObj base(player, radius) { } - public const double BulletBombRange = GameData.basicBulletBombRange / 4 * 2; - public const double BulletAttackRange = GameData.basicAttackRange; - public override int AP => (int)(0.5 * GameData.basicAp); + public override double BulletBombRange => GameData.basicBulletBombRange / 4 * 2; + public override double BulletAttackRange => GameData.basicAttackShortRange; + public override int AP => (int)(0.5 * GameData.basicApOfGhost); public override int Speed => 5 * GameData.basicBulletMoveSpeed / 3; + public override int Backswing => GameData.basicBackswing; + public override int RecoveryFromHit => GameData.basicRecoveryFromHit; + public override bool IsToBomb => true; public override bool CanAttack(GameObj target) { @@ -108,10 +122,13 @@ namespace GameClass.GameObj base(player, radius) { } - public const double BulletBombRange = GameData.basicBulletBombRange / 3 * 4; - public const double BulletAttackRange = 0.1 * GameData.basicAttackRange; - public override int AP => GameData.basicAp / 3 * 2; + public override double BulletBombRange => GameData.basicBulletBombRange / 3 * 4; + public override double BulletAttackRange => 0.1 * GameData.basicAttackShortRange; + public override int AP => GameData.basicApOfGhost / 3 * 2; public override int Speed => GameData.basicBulletMoveSpeed / 3; + public override int Backswing => GameData.basicBackswing; + public override int RecoveryFromHit => GameData.basicRecoveryFromHit; + public override bool IsToBomb => true; public override bool CanAttack(GameObj target) { @@ -165,73 +182,5 @@ namespace GameClass.GameObj public override BulletType TypeOfBullet => BulletType.LineBullet; } - public static class BulletFactory - { - public static Bullet? GetBullet(Character character) - { - Bullet? newBullet = null; - switch (character.BulletOfPlayer) - { - case BulletType.AtomBomb: - newBullet = new AtomBomb(character); - break; - case BulletType.LineBullet: - newBullet = new LineBullet(character); - break; - case BulletType.FastBullet: - newBullet = new FastBullet(character); - break; - case BulletType.OrdinaryBullet: - newBullet = new OrdinaryBullet(character); - break; - default: - break; - } - return newBullet; - } - public static int BulletRadius(BulletType bulletType) - { - switch (bulletType) - { - case BulletType.AtomBomb: - case BulletType.LineBullet: - case BulletType.FastBullet: - case BulletType.OrdinaryBullet: - default: - return GameData.bulletRadius; - } - } - public static double BulletAttackRange(BulletType bulletType) - { - switch (bulletType) - { - case BulletType.AtomBomb: - return AtomBomb.BulletAttackRange; - case BulletType.LineBullet: - return LineBullet.BulletAttackRange; - case BulletType.FastBullet: - return FastBullet.BulletAttackRange; - case BulletType.OrdinaryBullet: - return OrdinaryBullet.BulletAttackRange; - default: - return 0; - } - } - public static double BulletBombRange(BulletType bulletType) - { - switch (bulletType) - { - case BulletType.AtomBomb: - return AtomBomb.BulletBombRange; - case BulletType.LineBullet: - return LineBullet.BulletBombRange; - case BulletType.FastBullet: - return FastBullet.BulletBombRange; - case BulletType.OrdinaryBullet: - return OrdinaryBullet.BulletBombRange; - default: - return 0; - } - } - } + } diff --git a/logic/GameClass/GameObj/Bullet/Bullet.Student.cs b/logic/GameClass/GameObj/Bullet/Bullet.Student.cs new file mode 100644 index 0000000..6140d57 --- /dev/null +++ b/logic/GameClass/GameObj/Bullet/Bullet.Student.cs @@ -0,0 +1,7 @@ +using Preparation.Interface; +using Preparation.Utility; +using System; + +namespace GameClass.GameObj +{ +} diff --git a/logic/GameClass/GameObj/Bullet/Bullet.cs b/logic/GameClass/GameObj/Bullet/Bullet.cs new file mode 100644 index 0000000..d0cc2f5 --- /dev/null +++ b/logic/GameClass/GameObj/Bullet/Bullet.cs @@ -0,0 +1,89 @@ +using Preparation.Interface; +using Preparation.Utility; +using System; + +namespace GameClass.GameObj +{ + public abstract class Bullet : ObjOfCharacter + { + /// + /// //攻击力 + /// + public abstract double BulletBombRange{ get; } + public abstract double BulletAttackRange{ get; } + public abstract int AP { get; } + public abstract int Speed { get; } + public abstract bool IsToBomb { get; } + public abstract int Backswing { get; } + public abstract int RecoveryFromHit { get; } + + private readonly bool hasSpear; + /// + /// 是否有矛 + /// + public bool HasSpear => hasSpear; + + /// + /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target + /// + /// 被尝试攻击者 + /// 是否可以攻击到 + public abstract bool CanAttack(GameObj target); + + protected override bool IgnoreCollideExecutor(IGameObj targetObj) + { + if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet) + return true; + return false; + } + public Bullet(Character player, int radius) : + base(player.Position, radius, PlaceType.Null, GameObjType.Bullet) + { + this.CanMove = true; + this.moveSpeed = this.Speed; + this.hasSpear = player.HasSpear; + this.Parent = player; + } + public override bool IsRigid => true; // 默认为true + public override ShapeType Shape => ShapeType.Circle; // 默认为圆形 + public abstract BulletType TypeOfBullet { get; } + } + + public static class BulletFactory + { + public static Bullet? GetBullet(Character character) + { + Bullet? newBullet = null; + switch (character.BulletOfPlayer) + { + case BulletType.AtomBomb: + newBullet = new AtomBomb(character); + break; + case BulletType.LineBullet: + newBullet = new LineBullet(character); + break; + case BulletType.FastBullet: + newBullet = new FastBullet(character); + break; + case BulletType.OrdinaryBullet: + newBullet = new OrdinaryBullet(character); + break; + default: + break; + } + return newBullet; + } + public static int BulletRadius(BulletType bulletType) + { + switch (bulletType) + { + case BulletType.AtomBomb: + case BulletType.LineBullet: + case BulletType.FastBullet: + case BulletType.OrdinaryBullet: + default: + return GameData.bulletRadius; + } + } + } +} diff --git a/logic/GameClass/GameObj/Character/Character.SkillManager.cs b/logic/GameClass/GameObj/Character/Character.SkillManager.cs index 36b522f..a9a604f 100644 --- a/logic/GameClass/GameObj/Character/Character.SkillManager.cs +++ b/logic/GameClass/GameObj/Character/Character.SkillManager.cs @@ -19,15 +19,18 @@ namespace GameClass.GameObj { return commonSkill(this); } - private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能 - public int TimeUntilCommonSkillAvailable + + private Dictionary TimeUntilActiveSkillAvailable { get; set; } + + public bool SetTimeUntilActiveSkillAvailable(ActiveSkillType activeSkillType, int timeUntilActiveSkillAvailable) { - get => timeUntilCommonSkillAvailable; - set + lock (gameObjLock) + if (TimeUntilActiveSkillAvailable.ContainsKey(activeSkillType)) { - lock (gameObjLock) - timeUntilCommonSkillAvailable = value < 0 ? 0 : value; + TimeUntilActiveSkillAvailable[activeSkillType] = (timeUntilActiveSkillAvailable > 0) ? timeUntilActiveSkillAvailable : 0; + return true; } + return false; } readonly CharacterPassiveSkill passiveSkill; @@ -41,14 +44,14 @@ namespace GameClass.GameObj { return this.characterType switch { - CharacterType.Assassin => true, - CharacterType.Vampire => true, + this.CharacterType.Assassin => true, + this.CharacterType.Vampire => true, - CharacterType.Null => false, - CharacterType.RecoverAfterBattle => false, - CharacterType.SpeedUpWhenLeavingGrass => false, - CharacterType.PSkill4 => false, - CharacterType.PSkill5 => false, + this.CharacterType.Null => false, + this.CharacterType.RecoverAfterBattle => false, + this.CharacterType.SpeedUpWhenLeavingGrass => false, + this.CharacterType.PSkill4 => false, + this.CharacterType.PSkill5 => false, _ => false, }; } @@ -61,19 +64,19 @@ namespace GameClass.GameObj this.propInventory = null; this.buffManeger = new BuffManeger(); IPassiveSkill pSkill; - ICommonSkill cSkill; + IActiveSkill cSkill; switch (characterType) { - case CharacterType.Assassin: - pSkill = new(); + case this.CharacterType.Assassin: + pSkill = null; break; - case CharacterType.RecoverAfterBattle: + case this.CharacterType.RecoverAfterBattle: pSkill = new RecoverAfterBattle(); break; - case CharacterType.SpeedUpWhenLeavingGrass: + case this.CharacterType.SpeedUpWhenLeavingGrass: pSkill = new SpeedUpWhenLeavingGrass(); break; - case CharacterType.Vampire: + case this.CharacterType.Vampire: pSkill = new Vampire(); break; default: @@ -83,7 +86,7 @@ namespace GameClass.GameObj switch (commonSkillType) { case ActiveSkillType.BecomeAssassin: - cSkill = new BecomeAssassin(); + cSkill = new BecomeInvisible(); break; case ActiveSkillType.BecomeVampire: cSkill = new BecomeVampire(); @@ -102,7 +105,6 @@ namespace GameClass.GameObj this.hp = cSkill.MaxHp; this.OrgMoveSpeed = cSkill.MoveSpeed; this.moveSpeed = cSkill.MoveSpeed; - this.cd = cSkill.CD; this.maxBulletNum = cSkill.MaxBulletNum; this.bulletNum = maxBulletNum; this.bulletOfPlayer = pSkill.InitBullet; diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index ba2bcb0..2f14ca9 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -2,6 +2,7 @@ using Preparation.Utility; using System; using System.Collections.Generic; +using System.Numerics; using System.Runtime.InteropServices; using System.Threading; @@ -13,26 +14,7 @@ namespace GameClass.GameObj #region 角色的基本属性及方法,包括与道具的交互方法 - /// - /// 装弹冷却 - /// - protected int cd; - public int CD - { - get => cd; - private - set - { - lock (gameObjLock) - { - cd = value; - Debugger.Output(this, string.Format("'s CD has been set to: {0}.", value)); - } - } - } - public int OrgCD { get; protected set; } - - protected int fixSpeed; + protected int fixSpeed = 1; /// /// 修理电机速度 /// @@ -90,7 +72,7 @@ namespace GameClass.GameObj get => score; } - public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer); + // public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer); private double vampire = 0; // 回血率:0-1之间 public double Vampire @@ -272,16 +254,13 @@ namespace GameClass.GameObj /// /// 减血量 /// 减操作是否成功 - public bool TrySubHp(int sub) + public int TrySubHp(int sub) { - if (hp > 0) - { + int previousHp = hp; lock (gameObjLock) - hp = 0 >= hp - sub ? 0 : hp - sub; + hp = hp >= sub ? 0 : hp - sub; Debugger.Output(this, " hp has subed to: " + hp.ToString()); - return true; - } - return false; + return previousHp - hp; } /* /// /// 增加死亡次数 @@ -327,7 +306,7 @@ namespace GameClass.GameObj /// /// 伤害来源 /// 人物在受到攻击后死了吗 - public bool BeAttack(Bullet bullet) + public bool BeAttacked(Bullet bullet) { lock (beAttackedLock) @@ -346,7 +325,7 @@ namespace GameClass.GameObj } else { - TrySubHp(bullet.AP); + bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * TrySubHp(bullet.AP))); } #if DEBUG Console.WriteLine($"PlayerID:{ID} is being shot! Now his hp is {hp}."); diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs index eecbabb..fc51880 100644 --- a/logic/GameClass/GameObj/GameObj.cs +++ b/logic/GameClass/GameObj/GameObj.cs @@ -171,6 +171,7 @@ namespace GameClass.GameObj /// /// 依具体类及该方法参数而定,默认为false protected virtual bool IgnoreCollideExecutor(IGameObj targetObj) => false; + bool IMoveable.IgnoreCollide(IGameObj targetObj) => IgnoreCollideExecutor(targetObj); public GameObj(XY initPos, int initRadius, PlaceType initPlace, GameObjType initType) { diff --git a/logic/GameClass/GameObj/Map/MapInfo.cs b/logic/GameClass/GameObj/Map/MapInfo.cs index 436456e..53b9453 100644 --- a/logic/GameClass/GameObj/Map/MapInfo.cs +++ b/logic/GameClass/GameObj/Map/MapInfo.cs @@ -1,7 +1,4 @@ -using Preparation.Utility; -using Preparation.GameData; - -namespace GameClass.GameObj +namespace GameClass.GameObj { public static class MapInfo { diff --git a/logic/GameClass/GameObj/Prop.cs b/logic/GameClass/GameObj/Prop.cs index 2e2e373..8e6dfbc 100644 --- a/logic/GameClass/GameObj/Prop.cs +++ b/logic/GameClass/GameObj/Prop.cs @@ -33,6 +33,8 @@ namespace GameClass.GameObj } } + + ///// ///// 坑人地雷 ///// diff --git a/logic/GameClass/Skill/CommonSkill.cs b/logic/GameClass/Skill/ActiveSkill.cs similarity index 77% rename from logic/GameClass/Skill/CommonSkill.cs rename to logic/GameClass/Skill/ActiveSkill.cs index 5a8588b..afecdaa 100644 --- a/logic/GameClass/Skill/CommonSkill.cs +++ b/logic/GameClass/Skill/ActiveSkill.cs @@ -7,7 +7,7 @@ using Timothy.FrameRateTask; namespace GameClass.Skill { - public class BecomeVampire : ICommonSkill // 化身吸血鬼 + public class BecomeVampire : IActiveSkill // 化身吸血鬼 { private const int moveSpeed = GameData.basicMoveSpeed; public int MoveSpeed => moveSpeed; @@ -15,22 +15,16 @@ namespace GameClass.Skill private const int maxHp = (int)(GameData.basicHp / 6 * 9.5); public int MaxHp => maxHp; - private const int cd = GameData.basicCD; - public int CD => cd; - - private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; - public int MaxBulletNum => maxBulletNum; - // 以上参数以后再改 public int SkillCD => GameData.commonSkillCD / 3 * 4; public int DurationTime => GameData.commonSkillTime; private readonly object commonSkillLock = new object(); - public object CommonSkillLock => commonSkillLock; + public object ActiveSkillLock => commonSkillLock; public bool SkillEffect(Character player) { - return CommonSkillFactory.SkillEffect(this, player, () => + return ActiveSkillFactory.SkillEffect(this, player, () => { player.Vampire += 0.5; Debugger.Output(player, "becomes vampire!"); @@ -42,28 +36,16 @@ namespace GameClass.Skill }); } } - public class BecomeAssassin : ICommonSkill // 化身刺客,隐身 + public class BecomeInvisible : IActiveSkill { - private const int moveSpeed = GameData.basicMoveSpeed / 3 * 5; - public int MoveSpeed => moveSpeed; - - private const int maxHp = (int)(GameData.basicHp / 6 * 7.5); - public int MaxHp => maxHp; - - private const int cd = GameData.basicCD; - public int CD => cd; - - private const int maxBulletNum = GameData.basicBulletNum; - public int MaxBulletNum => maxBulletNum; - // 以上参数以后再改 public int SkillCD => GameData.commonSkillCD; public int DurationTime => GameData.commonSkillTime / 10 * 6; private readonly object commonSkillLock = new object(); - public object CommonSkillLock => commonSkillLock; + public object ActiveSkillLock => commonSkillLock; public bool SkillEffect(Character player) { - return CommonSkillFactory.SkillEffect(this, player, () => + return ActiveSkillFactory.SkillEffect(this, player, () => { player.IsInvisible = true; Debugger.Output(player, "uses atombomb!"); @@ -72,7 +54,7 @@ namespace GameClass.Skill { player.IsInvisible = false; }); } } - public class NuclearWeapon : ICommonSkill // 核武器 + public class NuclearWeapon : IActiveSkill // 核武器 { private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4; public int MoveSpeed => moveSpeed; @@ -80,19 +62,16 @@ namespace GameClass.Skill private const int maxHp = GameData.basicHp; public int MaxHp => maxHp; - private const int cd = GameData.basicCD; - public int CD => cd; - private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; public int MaxBulletNum => maxBulletNum; // 以上参数以后再改 public int SkillCD => GameData.commonSkillCD / 3 * 7; public int DurationTime => GameData.commonSkillTime / 10; private readonly object commonSkillLock = new object(); - public object CommonSkillLock => commonSkillLock; + public object ActiveSkillLock => commonSkillLock; public bool SkillEffect(Character player) { - return CommonSkillFactory.SkillEffect(this, player, () => + return ActiveSkillFactory.SkillEffect(this, player, () => { player.BulletOfPlayer = BulletType.AtomBomb; Debugger.Output(player, "uses atombomb!"); @@ -101,7 +80,7 @@ namespace GameClass.Skill { player.BulletOfPlayer = player.OriBulletOfPlayer; }); } } - public class SuperFast : ICommonSkill // 3倍速 + public class SuperFast : IActiveSkill // 3倍速 { private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3; public int MoveSpeed => moveSpeed; @@ -109,19 +88,16 @@ namespace GameClass.Skill private const int maxHp = GameData.basicHp / 6 * 4; public int MaxHp => maxHp; - private const int cd = GameData.basicCD; - public int CD => cd; - private const int maxBulletNum = GameData.basicBulletNum * 4 / 3; public int MaxBulletNum => maxBulletNum; // 以上参数以后再改 public int SkillCD => GameData.commonSkillCD; public int DurationTime => GameData.commonSkillTime / 10 * 4; private readonly object commonSkillLock = new object(); - public object CommonSkillLock => commonSkillLock; + public object ActiveSkillLock => commonSkillLock; public bool SkillEffect(Character player) { - return CommonSkillFactory.SkillEffect(this, player, () => + return ActiveSkillFactory.SkillEffect(this, player, () => { player.AddMoveSpeed(this.DurationTime, 3.0); Debugger.Output(player, "moves very fast!"); @@ -130,7 +106,7 @@ namespace GameClass.Skill { }); } } - public class NoCommonSkill : ICommonSkill // 这种情况不该发生,定义着以防意外 + public class NoCommonSkill : IActiveSkill // 这种情况不该发生,定义着以防意外 { private const int moveSpeed = GameData.basicMoveSpeed; public int MoveSpeed => moveSpeed; @@ -138,31 +114,28 @@ namespace GameClass.Skill private const int maxHp = GameData.basicHp; public int MaxHp => maxHp; - private const int cd = GameData.basicCD; - public int CD => cd; - private const int maxBulletNum = GameData.basicBulletNum; public int MaxBulletNum => maxBulletNum; // 以上参数以后再改 public int SkillCD => GameData.commonSkillCD; public int DurationTime => GameData.commonSkillTime; private readonly object commonSkillLock = new object(); - public object CommonSkillLock => commonSkillLock; + public object ActiveSkillLock => commonSkillLock; public bool SkillEffect(Character player) { return false; } } - public static class CommonSkillFactory + public static class ActiveSkillFactory { - public static bool SkillEffect(ICommonSkill commonSkill, Character player, Action startSkill, Action endSkill) + public static bool SkillEffect(IActiveSkill activeSkill, Character player, Action startSkill, Action endSkill) { - lock (commonSkill.CommonSkillLock) + lock (activeSkill.ActiveSkillLock) { if (player.TimeUntilCommonSkillAvailable == 0) { - player.TimeUntilCommonSkillAvailable = commonSkill.SkillCD; + player.TimeUntilCommonSkillAvailable = activeSkill.SkillCD; new Thread (() => { @@ -175,7 +148,7 @@ namespace GameClass.Skill }, timeInterval: GameData.frameDuration, () => 0, - maxTotalDuration: (long)(commonSkill.DurationTime) + maxTotalDuration: (long)(activeSkill.DurationTime) ) { AllowTimeExceed = true, @@ -194,7 +167,7 @@ namespace GameClass.Skill }, timeInterval: GameData.frameDuration, () => 0, - maxTotalDuration: (long)(commonSkill.SkillCD - commonSkill.DurationTime) + maxTotalDuration: (long)(activeSkill.SkillCD - activeSkill.DurationTime) ) { AllowTimeExceed = true, diff --git a/logic/GameClass/Skill/ISkill.cs b/logic/GameClass/Skill/ISkill.cs index a80db89..1735236 100644 --- a/logic/GameClass/Skill/ISkill.cs +++ b/logic/GameClass/Skill/ISkill.cs @@ -1,23 +1,29 @@ using GameClass.GameObj; using Preparation.Utility; -using System.Threading; +using System.Collections.Generic; namespace GameClass.Skill { - public interface IPassiveSkill + public interface ISkill + { + } + public interface IPassiveSkill: ISkill { - public BulletType InitBullet { get; } public void SkillEffect(Character player); } - public interface ICommonSkill + public interface IActiveSkill : ISkill + { + public int SkillCD { get; } + public int DurationTime { get; } //技能持续时间 + public object ActiveSkillLock { get; } + public bool SkillEffect(Character player); + } + public interface ICharacterType { public int MoveSpeed { get; } public int MaxHp { get; } - public int CD { get; } - public int MaxBulletNum { get; } - public bool SkillEffect(Character player); - public int DurationTime { get; } // 技能持续时间 - public int SkillCD { get; } - public object CommonSkillLock { get; } + public BulletType InitBullet { get; } + public List ListOfIActiveSkill { get; } + public List ListOfIPassiveSkill { get; } } } diff --git a/logic/GameClass/Skill/Occupation.cs b/logic/GameClass/Skill/Occupation.cs new file mode 100644 index 0000000..4cb4f65 --- /dev/null +++ b/logic/GameClass/Skill/Occupation.cs @@ -0,0 +1,32 @@ +using GameClass.GameObj; +using System.Threading; +using Preparation.Interface; +using Preparation.Utility; +using System; +using System.Collections.Generic; + +namespace GameClass.Skill +{ + public abstract class Occupation + { + public abstract int MoveSpeed { get; } + public abstract int MaxHp { get; } + public abstract BulletType InitBullet { get; } + public abstract List ListOfIActiveSkill { get; } + public abstract List ListOfIPassiveSkill { get; } + } + public class Assassin : Occupation + { + private const int moveSpeed = GameData.basicMoveSpeed/380*473; + public override int MoveSpeed => moveSpeed; + + private const int maxHp = GameData.basicHp; + public override int MaxHp => maxHp; + + public override BulletType InitBullet => BulletType.CommonAttackOfGhost; + + public override List ListOfIActiveSkill => new(new IActiveSkill[]{new BecomeInvisible(),}); + public override List ListOfIPassiveSkill => new(new IPassiveSkill[] {}); + } + +} diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 2cb0d5e..6ac60db 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -30,7 +30,7 @@ namespace Gaming { foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) { - if (GameData.IsInTheSameCell(generator.Position, player.Position)) + if (GameData.ApproachToInteract(generator.Position, player.Position)) { generatorForFix = generator; break; diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index c1da35d..21ba15a 100644 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using GameClass.GameObj; using Preparation.Utility; using GameEngine; +using Preparation.Interface; namespace Gaming { @@ -34,67 +35,80 @@ namespace Gaming } ); } - private void BombOnePlayer(Bullet bullet, Character playerBeingShot) + private bool CanBeBombed(Bullet bullet, GameObjType gameObjType) { - if (playerBeingShot.BeAttack(bullet)) + if (gameObjType==GameObjType.Character)return true; + return false; + } + private void BombObj(Bullet bullet, GameObj objBeingShot) + { + switch (objBeingShot.Type) { - playerBeingShot.CanMove = false; - playerBeingShot.IsResetting = true; - // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); - // try - //{ - // gameMap.GameObjDict[GameObjType.Character].Remove(playerBeingShot); - // } - // finally - //{ - // gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); - // } - - Prop? dropProp = null; - if (playerBeingShot.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地 - { - dropProp = playerBeingShot.PropInventory; - dropProp.SetNewPos(GameData.GetCellCenterPos(playerBeingShot.Position.x / GameData.numOfPosGridPerCell, playerBeingShot.Position.y / GameData.numOfPosGridPerCell)); - } - gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); - try - { - if (dropProp != null) - gameMap.GameObjDict[GameObjType.Prop].Add(dropProp); - } - finally - { - gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); - } - - playerBeingShot.Reset(); - ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 - - new Thread - (() => + case GameObjType.Character: + Character playerBeingShot= (Character)objBeingShot; + if (playerBeingShot.BeAttacked(bullet)) { - - Thread.Sleep(GameData.reviveTime); - - playerBeingShot.AddShield(GameData.shieldTimeAtBirth); // 复活加个盾 - + playerBeingShot.CanMove = false; + playerBeingShot.IsResetting = true; // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); // try //{ - // gameMap.GameObjDict[GameObjType.Character].Add(playerBeingShot); + // gameMap.GameObjDict[GameObjType.Character].Remove(playerBeingShot); + // } + // finally + //{ + // gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); // } - // finally { gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); } - if (gameMap.Timer.IsGaming) + Prop? dropProp = null; + if (playerBeingShot.PropInventory != null) // 若角色原来有道具,则原始道具掉落在原地 + { + dropProp = playerBeingShot.PropInventory; + dropProp.SetNewPos(GameData.GetCellCenterPos(playerBeingShot.Position.x / GameData.numOfPosGridPerCell, playerBeingShot.Position.y / GameData.numOfPosGridPerCell)); + } + gameMap.GameObjLockDict[GameObjType.Prop].EnterWriteLock(); + try { - playerBeingShot.CanMove = true; + if (dropProp != null) + gameMap.GameObjDict[GameObjType.Prop].Add(dropProp); } - playerBeingShot.IsResetting = false; + finally + { + gameMap.GameObjLockDict[GameObjType.Prop].ExitWriteLock(); + } + + playerBeingShot.Reset(); + ((Character?)bullet.Parent)?.AddScore(GameData.addScoreWhenKillOneLevelPlayer); // 给击杀者加分 + + /* new Thread + (() => + { + + Thread.Sleep(GameData.reviveTime); + + playerBeingShot.AddShield(GameData.shieldTimeAtBirth); // 复活加个盾 + + // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); + // try + //{ + // gameMap.GameObjDict[GameObjType.Character].Add(playerBeingShot); + // } + // finally { gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); } + + if (gameMap.Timer.IsGaming) + { + playerBeingShot.CanMove = true; + } + playerBeingShot.IsResetting = false; + } + ) + { IsBackground = true }.Start(); + */ } - ) - { IsBackground = true }.Start(); + break; } } + private void BulletBomb(Bullet bullet, GameObj? objBeingShot) { #if DEBUG @@ -127,6 +141,55 @@ namespace Gaming gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); } + if (!bullet.IsToBomb) + { + if (objBeingShot==null) + { + if (bullet.Backswing>0) + { + bullet.Parent.CanMove=false; + bullet.Parent.IsMoving=false; + + new Thread + (() => + { + Thread.Sleep(bullet.Backswing); + + if (gameMap.Timer.IsGaming) + { + bullet.Parent.CanMove = true; + } + } + ) + { IsBackground = true }.Start(); + } + return; + } + + + BombObj(bullet, objBeingShot); + if (bullet.RecoveryFromHit>0) + { + bullet.Parent.CanMove=false; + bullet.Parent.IsMoving=false; + + new Thread + (() => + { + + Thread.Sleep(bullet.RecoveryFromHit); + + if (gameMap.Timer.IsGaming) + { + bullet.Parent.CanMove = true; + } + } + ) + { IsBackground = true }.Start(); + } + return; + } + /*if (objBeingShot != null) { else if (objBeingShot is Bullet) //子弹不能相互引爆,若要更改这一设定,取消注释即可。 @@ -136,31 +199,79 @@ namespace Gaming }*/ // 子弹爆炸会发生的事↓↓↓ - var beAttackedList = new List(); - gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); - try + var beAttackedList = new List(); + + foreach (var kvp in gameMap.GameObjDict) { - foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) + if (CanBeBombed(bullet, kvp.Key)) { - if (bullet.CanAttack(player)) + gameMap.GameObjLockDict[kvp.Key].EnterWriteLock(); + try { - beAttackedList.Add(player); - if (player.ID != bullet.Parent.ID) - bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * bullet.AP)); + foreach (var item in gameMap.GameObjDict[kvp.Key]) + if (bullet.CanAttack((GameObj)item)) + { + beAttackedList.Add(item); + } + + } + finally + { + gameMap.GameObjLockDict[kvp.Key].ExitWriteLock(); } } } - finally + + foreach (GameObj beAttackedObj in beAttackedList) { - gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); + BombObj(bullet, beAttackedObj); } - - foreach (Character beAttackedPlayer in beAttackedList) + if (objBeingShot==null) { - BombOnePlayer(bullet, beAttackedPlayer); + if (bullet.Backswing>0) + { + bullet.Parent.CanMove=false; + bullet.Parent.IsMoving=false; + + new Thread + (() => + { + Thread.Sleep(bullet.Backswing); + + if (gameMap.Timer.IsGaming) + { + bullet.Parent.CanMove = true; + } + } + ) + { IsBackground = true }.Start(); + } } + else + { + if (bullet.RecoveryFromHit>0) + { + bullet.Parent.CanMove=false; + bullet.Parent.IsMoving=false; + + new Thread + (() => + { + + Thread.Sleep(bullet.RecoveryFromHit); + + if (gameMap.Timer.IsGaming) + { + bullet.Parent.CanMove = true; + } + } + ) + { IsBackground = true }.Start(); + } + } beAttackedList.Clear(); } + public bool Attack(Character? player, double angle) // 射出去的子弹泼出去的水(狗头) { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange if (player == null) @@ -192,7 +303,7 @@ namespace Gaming { gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); } - moveEngine.MoveObj(bullet, (int)((player.AttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms + moveEngine.MoveObj(bullet, (int)((bullet.BulletAttackRange - player.Radius - BulletFactory.BulletRadius(player.BulletOfPlayer)) * 1000 / bullet.MoveSpeed), angle); // 这里时间参数除出来的单位要是ms #if DEBUG Console.WriteLine($"playerID:{player.ID} successfully attacked!"); #endif diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 3f55577..56db5c4 100644 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -31,7 +31,7 @@ namespace Gaming public List TeamList => teamList; private readonly Map gameMap; public Map GameMap => gameMap; - private readonly int numOfTeam; + // private readonly int numOfTeam; public long AddPlayer(PlayerInitInfo playerInitInfo) { if (!Team.teamExists(playerInitInfo.teamID)) @@ -57,7 +57,7 @@ namespace Gaming newPlayer.TeamID = playerInitInfo.teamID; newPlayer.PlayerID = playerInitInfo.playerID; - new Thread //人物装弹 + /*new Thread //人物装弹 ( () => { @@ -85,16 +85,16 @@ namespace Gaming ) { AllowTimeExceed = true - /*MaxTolerantTimeExceedCount = 5, + 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(); + { IsBackground = true }.Start();*/ return newPlayer.ID; } @@ -132,7 +132,7 @@ namespace Gaming if (kvp.Key == GameObjType.Bullet || kvp.Key == GameObjType.Character || kvp.Key == GameObjType.Prop) { gameMap.GameObjLockDict[kvp.Key].EnterWriteLock(); - try + try { foreach (var item in gameMap.GameObjDict[kvp.Key]) { @@ -342,7 +342,7 @@ namespace Gaming gameMap = new Map(mapResource); // 加入队伍 - this.numOfTeam = numOfTeam; + // this.numOfTeam = numOfTeam; teamList = new List(); for (int i = 0; i < numOfTeam; ++i) { diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs index 3f0d946..2bc4f1b 100644 --- a/logic/Preparation/Utility/EnumType.cs +++ b/logic/Preparation/Utility/EnumType.cs @@ -42,7 +42,9 @@ namespace Preparation.Utility OrdinaryBullet = 1, // 普通子弹 AtomBomb = 2, // 原子弹 FastBullet = 3, // 快速子弹 - LineBullet = 4 // 直线子弹 + LineBullet = 4, // 直线子弹 + FlyingKnife = 5, //飞刀 + CommonAttackOfGhost = 6 } public enum PropType // 道具类型 { @@ -66,7 +68,7 @@ namespace Preparation.Utility public enum ActiveSkillType // 主动技能 { Null = 0, - BecomeAssassin = 1, + BecomeInvisible = 1, BecomeVampire = 2, NuclearWeapon = 3, SuperFast = 4, diff --git a/logic/Preparation/Utility/GameData.cs b/logic/Preparation/Utility/GameData.cs index a01bce8..a296986 100644 --- a/logic/Preparation/Utility/GameData.cs +++ b/logic/Preparation/Utility/GameData.cs @@ -1,4 +1,5 @@ -namespace Preparation.Utility +using System; +namespace Preparation.Utility { public static class GameData { @@ -37,19 +38,25 @@ { return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2); } + public static bool ApproachToInteract(XY pos1, XY pos2) + { + return Math.Abs(PosGridToCellX(pos1) - PosGridToCellX(pos2))<=1 && Math.Abs(PosGridToCellY(pos1) - PosGridToCellY(pos2))<=1; + } #endregion #region 角色相关 public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 - public const int basicAp = 3000; // 初始攻击力 - public const int basicHp = 6000; // 初始血量 - public const int basicCD = 3000; // 初始子弹冷却 + public const int basicApOfGhost = 500; // 初始攻击力 + public const int basicHp = 1003; // 初始血量 + public const int basicBackswing = 500;//基本后摇时间 + public const int basicRecoveryFromHit = 4300;//基本命中攻击恢复时长 public const int basicBulletNum = 3; // 基本初始子弹量 public const int MinAP = 0; // 最小攻击力 public const int MaxAP = int.MaxValue; // 最大攻击力 - public const double basicAttackRange = 9000; // 基本攻击范围 + public const double basicRemoteAttackRange = 9000; // 基本远程攻击范围 + public const double basicAttackShortRange = 2700; // 基本近程攻击范围 public const double basicBulletBombRange = 3000; // 基本子弹爆炸范围 - public const int basicMoveSpeed = 3000; // 基本移动速度,单位:s-1 - public const int basicBulletMoveSpeed = 3000; // 基本子弹移动速度,单位:s-1 + public const int basicMoveSpeed = 3800; // 基本移动速度,单位:s-1 + public const int basicBulletMoveSpeed = 5400; // 基本子弹移动速度,单位:s-1 public const int characterMaxSpeed = 12000; // 最大速度 public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分 public const int commonSkillCD = 30000; // 普通技能标准冷却时间 @@ -70,7 +77,7 @@ public const long PropProduceTime = 10000; public const int PropDuration = 10000; - public const int degreeOfFixedGenerator = 100; + public const int degreeOfFixedGenerator = 2000; #endregion #region 游戏帧相关 public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长