| @@ -4,44 +4,48 @@ using System; | |||||
| namespace GameClass.GameObj | namespace GameClass.GameObj | ||||
| { | { | ||||
| public abstract class Bullet : ObjOfCharacter | |||||
| internal sealed class CommonAttackOfGhost : Bullet | |||||
| { | { | ||||
| /// <summary> | |||||
| /// //攻击力 | |||||
| /// </summary> | |||||
| public abstract int AP { get; } | |||||
| public abstract int Speed { get; } | |||||
| private readonly bool hasSpear; | |||||
| /// <summary> | |||||
| /// 是否有矛 | |||||
| /// </summary> | |||||
| public bool HasSpear => hasSpear; | |||||
| /// <summary> | |||||
| /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target | |||||
| /// </summary> | |||||
| /// <param name="target">被尝试攻击者</param> | |||||
| /// <returns>是否可以攻击到</returns> | |||||
| 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; | 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 | internal sealed class AtomBomb : Bullet | ||||
| @@ -50,10 +54,13 @@ namespace GameClass.GameObj | |||||
| base(player, radius) | 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 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) | public override bool CanAttack(GameObj target) | ||||
| { | { | ||||
| // 圆形攻击范围 | // 圆形攻击范围 | ||||
| @@ -61,6 +68,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| public override BulletType TypeOfBullet => BulletType.AtomBomb; | public override BulletType TypeOfBullet => BulletType.AtomBomb; | ||||
| } | } | ||||
| internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速 | internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速 | ||||
| @@ -69,10 +77,13 @@ namespace GameClass.GameObj | |||||
| base(player, radius) | 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 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) | public override bool CanAttack(GameObj target) | ||||
| { | { | ||||
| // 圆形攻击范围 | // 圆形攻击范围 | ||||
| @@ -88,10 +99,13 @@ namespace GameClass.GameObj | |||||
| base(player, radius) | 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 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) | public override bool CanAttack(GameObj target) | ||||
| { | { | ||||
| @@ -108,10 +122,13 @@ namespace GameClass.GameObj | |||||
| base(player, radius) | 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 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) | public override bool CanAttack(GameObj target) | ||||
| { | { | ||||
| @@ -165,73 +182,5 @@ namespace GameClass.GameObj | |||||
| public override BulletType TypeOfBullet => BulletType.LineBullet; | 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -0,0 +1,7 @@ | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| using System; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| } | |||||
| @@ -0,0 +1,89 @@ | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| using System; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public abstract class Bullet : ObjOfCharacter | |||||
| { | |||||
| /// <summary> | |||||
| /// //攻击力 | |||||
| /// </summary> | |||||
| 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; | |||||
| /// <summary> | |||||
| /// 是否有矛 | |||||
| /// </summary> | |||||
| public bool HasSpear => hasSpear; | |||||
| /// <summary> | |||||
| /// 与THUAI4不同的一个攻击判定方案,通过这个函数判断爆炸时能否伤害到target | |||||
| /// </summary> | |||||
| /// <param name="target">被尝试攻击者</param> | |||||
| /// <returns>是否可以攻击到</returns> | |||||
| 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -19,15 +19,18 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| return commonSkill(this); | return commonSkill(this); | ||||
| } | } | ||||
| private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能 | |||||
| public int TimeUntilCommonSkillAvailable | |||||
| private Dictionary<ActiveSkillType, int> 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; | readonly CharacterPassiveSkill passiveSkill; | ||||
| @@ -41,14 +44,14 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| return this.characterType switch | 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, | _ => false, | ||||
| }; | }; | ||||
| } | } | ||||
| @@ -61,19 +64,19 @@ namespace GameClass.GameObj | |||||
| this.propInventory = null; | this.propInventory = null; | ||||
| this.buffManeger = new BuffManeger(); | this.buffManeger = new BuffManeger(); | ||||
| IPassiveSkill pSkill; | IPassiveSkill pSkill; | ||||
| ICommonSkill cSkill; | |||||
| IActiveSkill cSkill; | |||||
| switch (characterType) | switch (characterType) | ||||
| { | { | ||||
| case CharacterType.Assassin: | |||||
| pSkill = new(); | |||||
| case this.CharacterType.Assassin: | |||||
| pSkill = null; | |||||
| break; | break; | ||||
| case CharacterType.RecoverAfterBattle: | |||||
| case this.CharacterType.RecoverAfterBattle: | |||||
| pSkill = new RecoverAfterBattle(); | pSkill = new RecoverAfterBattle(); | ||||
| break; | break; | ||||
| case CharacterType.SpeedUpWhenLeavingGrass: | |||||
| case this.CharacterType.SpeedUpWhenLeavingGrass: | |||||
| pSkill = new SpeedUpWhenLeavingGrass(); | pSkill = new SpeedUpWhenLeavingGrass(); | ||||
| break; | break; | ||||
| case CharacterType.Vampire: | |||||
| case this.CharacterType.Vampire: | |||||
| pSkill = new Vampire(); | pSkill = new Vampire(); | ||||
| break; | break; | ||||
| default: | default: | ||||
| @@ -83,7 +86,7 @@ namespace GameClass.GameObj | |||||
| switch (commonSkillType) | switch (commonSkillType) | ||||
| { | { | ||||
| case ActiveSkillType.BecomeAssassin: | case ActiveSkillType.BecomeAssassin: | ||||
| cSkill = new BecomeAssassin(); | |||||
| cSkill = new BecomeInvisible(); | |||||
| break; | break; | ||||
| case ActiveSkillType.BecomeVampire: | case ActiveSkillType.BecomeVampire: | ||||
| cSkill = new BecomeVampire(); | cSkill = new BecomeVampire(); | ||||
| @@ -102,7 +105,6 @@ namespace GameClass.GameObj | |||||
| this.hp = cSkill.MaxHp; | this.hp = cSkill.MaxHp; | ||||
| this.OrgMoveSpeed = cSkill.MoveSpeed; | this.OrgMoveSpeed = cSkill.MoveSpeed; | ||||
| this.moveSpeed = cSkill.MoveSpeed; | this.moveSpeed = cSkill.MoveSpeed; | ||||
| this.cd = cSkill.CD; | |||||
| this.maxBulletNum = cSkill.MaxBulletNum; | this.maxBulletNum = cSkill.MaxBulletNum; | ||||
| this.bulletNum = maxBulletNum; | this.bulletNum = maxBulletNum; | ||||
| this.bulletOfPlayer = pSkill.InitBullet; | this.bulletOfPlayer = pSkill.InitBullet; | ||||
| @@ -2,6 +2,7 @@ | |||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Numerics; | |||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
| using System.Threading; | using System.Threading; | ||||
| @@ -13,26 +14,7 @@ namespace GameClass.GameObj | |||||
| #region 角色的基本属性及方法,包括与道具的交互方法 | #region 角色的基本属性及方法,包括与道具的交互方法 | ||||
| /// <summary> | |||||
| /// 装弹冷却 | |||||
| /// </summary> | |||||
| 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; | |||||
| /// <summary> | /// <summary> | ||||
| /// 修理电机速度 | /// 修理电机速度 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -90,7 +72,7 @@ namespace GameClass.GameObj | |||||
| get => score; | get => score; | ||||
| } | } | ||||
| public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer); | |||||
| // public double AttackRange => BulletFactory.BulletAttackRange(this.BulletOfPlayer); | |||||
| private double vampire = 0; // 回血率:0-1之间 | private double vampire = 0; // 回血率:0-1之间 | ||||
| public double Vampire | public double Vampire | ||||
| @@ -272,16 +254,13 @@ namespace GameClass.GameObj | |||||
| /// </summary> | /// </summary> | ||||
| /// <param name="sub">减血量</param> | /// <param name="sub">减血量</param> | ||||
| /// <returns>减操作是否成功</returns> | /// <returns>减操作是否成功</returns> | ||||
| public bool TrySubHp(int sub) | |||||
| public int TrySubHp(int sub) | |||||
| { | { | ||||
| if (hp > 0) | |||||
| { | |||||
| int previousHp = hp; | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| hp = 0 >= hp - sub ? 0 : hp - sub; | |||||
| hp = hp >= sub ? 0 : hp - sub; | |||||
| Debugger.Output(this, " hp has subed to: " + hp.ToString()); | Debugger.Output(this, " hp has subed to: " + hp.ToString()); | ||||
| return true; | |||||
| } | |||||
| return false; | |||||
| return previousHp - hp; | |||||
| } | } | ||||
| /* /// <summary> | /* /// <summary> | ||||
| /// 增加死亡次数 | /// 增加死亡次数 | ||||
| @@ -327,7 +306,7 @@ namespace GameClass.GameObj | |||||
| /// <param name="hasSpear"></param> | /// <param name="hasSpear"></param> | ||||
| /// <param name="attacker">伤害来源</param> | /// <param name="attacker">伤害来源</param> | ||||
| /// <returns>人物在受到攻击后死了吗</returns> | /// <returns>人物在受到攻击后死了吗</returns> | ||||
| public bool BeAttack(Bullet bullet) | |||||
| public bool BeAttacked(Bullet bullet) | |||||
| { | { | ||||
| lock (beAttackedLock) | lock (beAttackedLock) | ||||
| @@ -346,7 +325,7 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| TrySubHp(bullet.AP); | |||||
| bullet.Parent.HP = (int)(bullet.Parent.HP + (bullet.Parent.Vampire * TrySubHp(bullet.AP))); | |||||
| } | } | ||||
| #if DEBUG | #if DEBUG | ||||
| Console.WriteLine($"PlayerID:{ID} is being shot! Now his hp is {hp}."); | Console.WriteLine($"PlayerID:{ID} is being shot! Now his hp is {hp}."); | ||||
| @@ -171,6 +171,7 @@ namespace GameClass.GameObj | |||||
| /// </summary> | /// </summary> | ||||
| /// <returns> 依具体类及该方法参数而定,默认为false </returns> | /// <returns> 依具体类及该方法参数而定,默认为false </returns> | ||||
| protected virtual bool IgnoreCollideExecutor(IGameObj targetObj) => false; | protected virtual bool IgnoreCollideExecutor(IGameObj targetObj) => false; | ||||
| bool IMoveable.IgnoreCollide(IGameObj targetObj) => IgnoreCollideExecutor(targetObj); | bool IMoveable.IgnoreCollide(IGameObj targetObj) => IgnoreCollideExecutor(targetObj); | ||||
| public GameObj(XY initPos, int initRadius, PlaceType initPlace, GameObjType initType) | public GameObj(XY initPos, int initRadius, PlaceType initPlace, GameObjType initType) | ||||
| { | { | ||||
| @@ -1,7 +1,4 @@ | |||||
| using Preparation.Utility; | |||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | |||||
| namespace GameClass.GameObj | |||||
| { | { | ||||
| public static class MapInfo | public static class MapInfo | ||||
| { | { | ||||
| @@ -33,6 +33,8 @@ namespace GameClass.GameObj | |||||
| } | } | ||||
| } | } | ||||
| ///// <summary> | ///// <summary> | ||||
| ///// 坑人地雷 | ///// 坑人地雷 | ||||
| ///// </summary> | ///// </summary> | ||||
| @@ -7,7 +7,7 @@ using Timothy.FrameRateTask; | |||||
| namespace GameClass.Skill | namespace GameClass.Skill | ||||
| { | { | ||||
| public class BecomeVampire : ICommonSkill // 化身吸血鬼 | |||||
| public class BecomeVampire : IActiveSkill // 化身吸血鬼 | |||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed; | private const int moveSpeed = GameData.basicMoveSpeed; | ||||
| public int MoveSpeed => moveSpeed; | public int MoveSpeed => moveSpeed; | ||||
| @@ -15,22 +15,16 @@ namespace GameClass.Skill | |||||
| private const int maxHp = (int)(GameData.basicHp / 6 * 9.5); | private const int maxHp = (int)(GameData.basicHp / 6 * 9.5); | ||||
| public int MaxHp => maxHp; | 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 SkillCD => GameData.commonSkillCD / 3 * 4; | ||||
| public int DurationTime => GameData.commonSkillTime; | public int DurationTime => GameData.commonSkillTime; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| public object CommonSkillLock => commonSkillLock; | |||||
| public object ActiveSkillLock => commonSkillLock; | |||||
| public bool SkillEffect(Character player) | public bool SkillEffect(Character player) | ||||
| { | { | ||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||||
| { | { | ||||
| player.Vampire += 0.5; | player.Vampire += 0.5; | ||||
| Debugger.Output(player, "becomes vampire!"); | 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 SkillCD => GameData.commonSkillCD; | ||||
| public int DurationTime => GameData.commonSkillTime / 10 * 6; | public int DurationTime => GameData.commonSkillTime / 10 * 6; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| public object CommonSkillLock => commonSkillLock; | |||||
| public object ActiveSkillLock => commonSkillLock; | |||||
| public bool SkillEffect(Character player) | public bool SkillEffect(Character player) | ||||
| { | { | ||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||||
| { | { | ||||
| player.IsInvisible = true; | player.IsInvisible = true; | ||||
| Debugger.Output(player, "uses atombomb!"); | Debugger.Output(player, "uses atombomb!"); | ||||
| @@ -72,7 +54,7 @@ namespace GameClass.Skill | |||||
| { player.IsInvisible = false; }); | { player.IsInvisible = false; }); | ||||
| } | } | ||||
| } | } | ||||
| public class NuclearWeapon : ICommonSkill // 核武器 | |||||
| public class NuclearWeapon : IActiveSkill // 核武器 | |||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4; | private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4; | ||||
| public int MoveSpeed => moveSpeed; | public int MoveSpeed => moveSpeed; | ||||
| @@ -80,19 +62,16 @@ namespace GameClass.Skill | |||||
| private const int maxHp = GameData.basicHp; | private const int maxHp = GameData.basicHp; | ||||
| public int MaxHp => maxHp; | public int MaxHp => maxHp; | ||||
| private const int cd = GameData.basicCD; | |||||
| public int CD => cd; | |||||
| private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; | private const int maxBulletNum = GameData.basicBulletNum * 2 / 3; | ||||
| public int MaxBulletNum => maxBulletNum; | public int MaxBulletNum => maxBulletNum; | ||||
| // 以上参数以后再改 | // 以上参数以后再改 | ||||
| public int SkillCD => GameData.commonSkillCD / 3 * 7; | public int SkillCD => GameData.commonSkillCD / 3 * 7; | ||||
| public int DurationTime => GameData.commonSkillTime / 10; | public int DurationTime => GameData.commonSkillTime / 10; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| public object CommonSkillLock => commonSkillLock; | |||||
| public object ActiveSkillLock => commonSkillLock; | |||||
| public bool SkillEffect(Character player) | public bool SkillEffect(Character player) | ||||
| { | { | ||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||||
| { | { | ||||
| player.BulletOfPlayer = BulletType.AtomBomb; | player.BulletOfPlayer = BulletType.AtomBomb; | ||||
| Debugger.Output(player, "uses atombomb!"); | Debugger.Output(player, "uses atombomb!"); | ||||
| @@ -101,7 +80,7 @@ namespace GameClass.Skill | |||||
| { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | ||||
| } | } | ||||
| } | } | ||||
| public class SuperFast : ICommonSkill // 3倍速 | |||||
| public class SuperFast : IActiveSkill // 3倍速 | |||||
| { | { | ||||
| private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3; | private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3; | ||||
| public int MoveSpeed => moveSpeed; | public int MoveSpeed => moveSpeed; | ||||
| @@ -109,19 +88,16 @@ namespace GameClass.Skill | |||||
| private const int maxHp = GameData.basicHp / 6 * 4; | private const int maxHp = GameData.basicHp / 6 * 4; | ||||
| public int MaxHp => maxHp; | public int MaxHp => maxHp; | ||||
| private const int cd = GameData.basicCD; | |||||
| public int CD => cd; | |||||
| private const int maxBulletNum = GameData.basicBulletNum * 4 / 3; | private const int maxBulletNum = GameData.basicBulletNum * 4 / 3; | ||||
| public int MaxBulletNum => maxBulletNum; | public int MaxBulletNum => maxBulletNum; | ||||
| // 以上参数以后再改 | // 以上参数以后再改 | ||||
| public int SkillCD => GameData.commonSkillCD; | public int SkillCD => GameData.commonSkillCD; | ||||
| public int DurationTime => GameData.commonSkillTime / 10 * 4; | public int DurationTime => GameData.commonSkillTime / 10 * 4; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| public object CommonSkillLock => commonSkillLock; | |||||
| public object ActiveSkillLock => commonSkillLock; | |||||
| public bool SkillEffect(Character player) | public bool SkillEffect(Character player) | ||||
| { | { | ||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| return ActiveSkillFactory.SkillEffect(this, player, () => | |||||
| { | { | ||||
| player.AddMoveSpeed(this.DurationTime, 3.0); | player.AddMoveSpeed(this.DurationTime, 3.0); | ||||
| Debugger.Output(player, "moves very fast!"); | 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; | private const int moveSpeed = GameData.basicMoveSpeed; | ||||
| public int MoveSpeed => moveSpeed; | public int MoveSpeed => moveSpeed; | ||||
| @@ -138,31 +114,28 @@ namespace GameClass.Skill | |||||
| private const int maxHp = GameData.basicHp; | private const int maxHp = GameData.basicHp; | ||||
| public int MaxHp => maxHp; | public int MaxHp => maxHp; | ||||
| private const int cd = GameData.basicCD; | |||||
| public int CD => cd; | |||||
| private const int maxBulletNum = GameData.basicBulletNum; | private const int maxBulletNum = GameData.basicBulletNum; | ||||
| public int MaxBulletNum => maxBulletNum; | public int MaxBulletNum => maxBulletNum; | ||||
| // 以上参数以后再改 | // 以上参数以后再改 | ||||
| public int SkillCD => GameData.commonSkillCD; | public int SkillCD => GameData.commonSkillCD; | ||||
| public int DurationTime => GameData.commonSkillTime; | public int DurationTime => GameData.commonSkillTime; | ||||
| private readonly object commonSkillLock = new object(); | private readonly object commonSkillLock = new object(); | ||||
| public object CommonSkillLock => commonSkillLock; | |||||
| public object ActiveSkillLock => commonSkillLock; | |||||
| public bool SkillEffect(Character player) | public bool SkillEffect(Character player) | ||||
| { | { | ||||
| return false; | 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) | if (player.TimeUntilCommonSkillAvailable == 0) | ||||
| { | { | ||||
| player.TimeUntilCommonSkillAvailable = commonSkill.SkillCD; | |||||
| player.TimeUntilCommonSkillAvailable = activeSkill.SkillCD; | |||||
| new Thread | new Thread | ||||
| (() => | (() => | ||||
| { | { | ||||
| @@ -175,7 +148,7 @@ namespace GameClass.Skill | |||||
| }, | }, | ||||
| timeInterval: GameData.frameDuration, | timeInterval: GameData.frameDuration, | ||||
| () => 0, | () => 0, | ||||
| maxTotalDuration: (long)(commonSkill.DurationTime) | |||||
| maxTotalDuration: (long)(activeSkill.DurationTime) | |||||
| ) | ) | ||||
| { | { | ||||
| AllowTimeExceed = true, | AllowTimeExceed = true, | ||||
| @@ -194,7 +167,7 @@ namespace GameClass.Skill | |||||
| }, | }, | ||||
| timeInterval: GameData.frameDuration, | timeInterval: GameData.frameDuration, | ||||
| () => 0, | () => 0, | ||||
| maxTotalDuration: (long)(commonSkill.SkillCD - commonSkill.DurationTime) | |||||
| maxTotalDuration: (long)(activeSkill.SkillCD - activeSkill.DurationTime) | |||||
| ) | ) | ||||
| { | { | ||||
| AllowTimeExceed = true, | AllowTimeExceed = true, | ||||
| @@ -1,23 +1,29 @@ | |||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using System.Threading; | |||||
| using System.Collections.Generic; | |||||
| namespace GameClass.Skill | namespace GameClass.Skill | ||||
| { | { | ||||
| public interface IPassiveSkill | |||||
| public interface ISkill | |||||
| { | |||||
| } | |||||
| public interface IPassiveSkill: ISkill | |||||
| { | { | ||||
| public BulletType InitBullet { get; } | |||||
| public void SkillEffect(Character player); | 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 MoveSpeed { get; } | ||||
| public int MaxHp { 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<IActiveSkill> ListOfIActiveSkill { get; } | |||||
| public List<IPassiveSkill> ListOfIPassiveSkill { get; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -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<IActiveSkill> ListOfIActiveSkill { get; } | |||||
| public abstract List<IPassiveSkill> 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<IActiveSkill> ListOfIActiveSkill => new(new IActiveSkill[]{new BecomeInvisible(),}); | |||||
| public override List<IPassiveSkill> ListOfIPassiveSkill => new(new IPassiveSkill[] {}); | |||||
| } | |||||
| } | |||||
| @@ -30,7 +30,7 @@ namespace Gaming | |||||
| { | { | ||||
| foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) | foreach (Generator generator in gameMap.GameObjDict[GameObjType.Generator]) | ||||
| { | { | ||||
| if (GameData.IsInTheSameCell(generator.Position, player.Position)) | |||||
| if (GameData.ApproachToInteract(generator.Position, player.Position)) | |||||
| { | { | ||||
| generatorForFix = generator; | generatorForFix = generator; | ||||
| break; | break; | ||||
| @@ -4,6 +4,7 @@ using System.Collections.Generic; | |||||
| using GameClass.GameObj; | using GameClass.GameObj; | ||||
| using Preparation.Utility; | using Preparation.Utility; | ||||
| using GameEngine; | using GameEngine; | ||||
| using Preparation.Interface; | |||||
| namespace Gaming | 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(); | // gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | ||||
| // try | // 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) | private void BulletBomb(Bullet bullet, GameObj? objBeingShot) | ||||
| { | { | ||||
| #if DEBUG | #if DEBUG | ||||
| @@ -127,6 +141,55 @@ namespace Gaming | |||||
| gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); | 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) | /*if (objBeingShot != null) | ||||
| { | { | ||||
| else if (objBeingShot is Bullet) //子弹不能相互引爆,若要更改这一设定,取消注释即可。 | else if (objBeingShot is Bullet) //子弹不能相互引爆,若要更改这一设定,取消注释即可。 | ||||
| @@ -136,31 +199,79 @@ namespace Gaming | |||||
| }*/ | }*/ | ||||
| // 子弹爆炸会发生的事↓↓↓ | // 子弹爆炸会发生的事↓↓↓ | ||||
| var beAttackedList = new List<Character>(); | |||||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||||
| try | |||||
| var beAttackedList = new List<IGameObj>(); | |||||
| 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(); | beAttackedList.Clear(); | ||||
| } | } | ||||
| public bool Attack(Character? player, double angle) // 射出去的子弹泼出去的水(狗头) | public bool Attack(Character? player, double angle) // 射出去的子弹泼出去的水(狗头) | ||||
| { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange | { // 子弹如果没有和其他物体碰撞,将会一直向前直到超出人物的attackRange | ||||
| if (player == null) | if (player == null) | ||||
| @@ -192,7 +303,7 @@ namespace Gaming | |||||
| { | { | ||||
| gameMap.GameObjLockDict[GameObjType.Bullet].ExitWriteLock(); | 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 | #if DEBUG | ||||
| Console.WriteLine($"playerID:{player.ID} successfully attacked!"); | Console.WriteLine($"playerID:{player.ID} successfully attacked!"); | ||||
| #endif | #endif | ||||
| @@ -31,7 +31,7 @@ namespace Gaming | |||||
| public List<Team> TeamList => teamList; | public List<Team> TeamList => teamList; | ||||
| private readonly Map gameMap; | private readonly Map gameMap; | ||||
| public Map GameMap => gameMap; | public Map GameMap => gameMap; | ||||
| private readonly int numOfTeam; | |||||
| // private readonly int numOfTeam; | |||||
| public long AddPlayer(PlayerInitInfo playerInitInfo) | public long AddPlayer(PlayerInitInfo playerInitInfo) | ||||
| { | { | ||||
| if (!Team.teamExists(playerInitInfo.teamID)) | if (!Team.teamExists(playerInitInfo.teamID)) | ||||
| @@ -57,7 +57,7 @@ namespace Gaming | |||||
| newPlayer.TeamID = playerInitInfo.teamID; | newPlayer.TeamID = playerInitInfo.teamID; | ||||
| newPlayer.PlayerID = playerInitInfo.playerID; | newPlayer.PlayerID = playerInitInfo.playerID; | ||||
| new Thread //人物装弹 | |||||
| /*new Thread //人物装弹 | |||||
| ( | ( | ||||
| () => | () => | ||||
| { | { | ||||
| @@ -85,16 +85,16 @@ namespace Gaming | |||||
| ) | ) | ||||
| { | { | ||||
| AllowTimeExceed = true | AllowTimeExceed = true | ||||
| /*MaxTolerantTimeExceedCount = 5, | |||||
| MaxTolerantTimeExceedCount = 5, | |||||
| TimeExceedAction = exceedTooMuch => | TimeExceedAction = exceedTooMuch => | ||||
| { | { | ||||
| if (exceedTooMuch) Console.WriteLine("The computer runs too slow that it cannot check the color below the player in time!"); | if (exceedTooMuch) Console.WriteLine("The computer runs too slow that it cannot check the color below the player in time!"); | ||||
| }*/ | |||||
| } | |||||
| } | } | ||||
| .Start(); | .Start(); | ||||
| } | } | ||||
| ) | ) | ||||
| { IsBackground = true }.Start(); | |||||
| { IsBackground = true }.Start();*/ | |||||
| return newPlayer.ID; | return newPlayer.ID; | ||||
| } | } | ||||
| @@ -132,7 +132,7 @@ namespace Gaming | |||||
| if (kvp.Key == GameObjType.Bullet || kvp.Key == GameObjType.Character || kvp.Key == GameObjType.Prop) | if (kvp.Key == GameObjType.Bullet || kvp.Key == GameObjType.Character || kvp.Key == GameObjType.Prop) | ||||
| { | { | ||||
| gameMap.GameObjLockDict[kvp.Key].EnterWriteLock(); | gameMap.GameObjLockDict[kvp.Key].EnterWriteLock(); | ||||
| try | |||||
| try | |||||
| { | { | ||||
| foreach (var item in gameMap.GameObjDict[kvp.Key]) | foreach (var item in gameMap.GameObjDict[kvp.Key]) | ||||
| { | { | ||||
| @@ -342,7 +342,7 @@ namespace Gaming | |||||
| gameMap = new Map(mapResource); | gameMap = new Map(mapResource); | ||||
| // 加入队伍 | // 加入队伍 | ||||
| this.numOfTeam = numOfTeam; | |||||
| // this.numOfTeam = numOfTeam; | |||||
| teamList = new List<Team>(); | teamList = new List<Team>(); | ||||
| for (int i = 0; i < numOfTeam; ++i) | for (int i = 0; i < numOfTeam; ++i) | ||||
| { | { | ||||
| @@ -42,7 +42,9 @@ namespace Preparation.Utility | |||||
| OrdinaryBullet = 1, // 普通子弹 | OrdinaryBullet = 1, // 普通子弹 | ||||
| AtomBomb = 2, // 原子弹 | AtomBomb = 2, // 原子弹 | ||||
| FastBullet = 3, // 快速子弹 | FastBullet = 3, // 快速子弹 | ||||
| LineBullet = 4 // 直线子弹 | |||||
| LineBullet = 4, // 直线子弹 | |||||
| FlyingKnife = 5, //飞刀 | |||||
| CommonAttackOfGhost = 6 | |||||
| } | } | ||||
| public enum PropType // 道具类型 | public enum PropType // 道具类型 | ||||
| { | { | ||||
| @@ -66,7 +68,7 @@ namespace Preparation.Utility | |||||
| public enum ActiveSkillType // 主动技能 | public enum ActiveSkillType // 主动技能 | ||||
| { | { | ||||
| Null = 0, | Null = 0, | ||||
| BecomeAssassin = 1, | |||||
| BecomeInvisible = 1, | |||||
| BecomeVampire = 2, | BecomeVampire = 2, | ||||
| NuclearWeapon = 3, | NuclearWeapon = 3, | ||||
| SuperFast = 4, | SuperFast = 4, | ||||
| @@ -1,4 +1,5 @@ | |||||
| namespace Preparation.Utility | |||||
| using System; | |||||
| namespace Preparation.Utility | |||||
| { | { | ||||
| public static class GameData | public static class GameData | ||||
| { | { | ||||
| @@ -37,19 +38,25 @@ | |||||
| { | { | ||||
| return PosGridToCellX(pos1) == PosGridToCellX(pos2) && PosGridToCellY(pos1) == PosGridToCellY(pos2); | 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 | #endregion | ||||
| #region 角色相关 | #region 角色相关 | ||||
| public const int characterRadius = numOfPosGridPerCell / 2; // 人物半径 | 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 basicBulletNum = 3; // 基本初始子弹量 | ||||
| public const int MinAP = 0; // 最小攻击力 | public const int MinAP = 0; // 最小攻击力 | ||||
| public const int MaxAP = int.MaxValue; // 最大攻击力 | 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 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 characterMaxSpeed = 12000; // 最大速度 | ||||
| public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分 | public const int addScoreWhenKillOneLevelPlayer = 30; // 击杀一级角色获得的加分 | ||||
| public const int commonSkillCD = 30000; // 普通技能标准冷却时间 | public const int commonSkillCD = 30000; // 普通技能标准冷却时间 | ||||
| @@ -70,7 +77,7 @@ | |||||
| public const long PropProduceTime = 10000; | public const long PropProduceTime = 10000; | ||||
| public const int PropDuration = 10000; | public const int PropDuration = 10000; | ||||
| public const int degreeOfFixedGenerator = 100; | |||||
| public const int degreeOfFixedGenerator = 2000; | |||||
| #endregion | #endregion | ||||
| #region 游戏帧相关 | #region 游戏帧相关 | ||||
| public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | ||||