| @@ -400,5 +400,3 @@ FodyWeavers.xsd | |||||
| #THUAI playback file | #THUAI playback file | ||||
| *.thuaipb | *.thuaipb | ||||
| Client/ | |||||
| CSharpInterface/ | |||||
| @@ -0,0 +1,20 @@ | |||||
| using Preparation.Utility; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| // 为方便界面组做子弹爆炸特效,现引入“爆炸中的子弹”,在每帧发送给界面组 | |||||
| public sealed class BombedBullet : GameObj | |||||
| { | |||||
| public override ShapeType Shape => ShapeType.Circle; | |||||
| public override bool IsRigid => false; | |||||
| public long MappingID { get; } | |||||
| public Bullet bulletHasBombed; | |||||
| public BombedBullet(Bullet bullet) : | |||||
| base(bullet.Position, bullet.Radius, bullet.Place, GameObjType.BombedBullet) | |||||
| { | |||||
| this.bulletHasBombed = bullet; | |||||
| this.MappingID = bullet.ID; | |||||
| this.FacingDirection = bullet.FacingDirection; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,238 @@ | |||||
| using Preparation.GameData; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| using System; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public abstract class Bullet : ObjOfCharacter | |||||
| { | |||||
| /// <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) | |||||
| { | |||||
| 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; } | |||||
| } | |||||
| internal sealed class AtomBomb : Bullet | |||||
| { | |||||
| public AtomBomb(Character player, int radius = GameData.bulletRadius) : | |||||
| 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 int Speed => GameData.basicBulletMoveSpeed / 3 * 2; | |||||
| public override bool CanAttack(GameObj target) | |||||
| { | |||||
| // 圆形攻击范围 | |||||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||||
| } | |||||
| public override BulletType TypeOfBullet => BulletType.AtomBomb; | |||||
| } | |||||
| internal sealed class OrdinaryBullet : Bullet // 1倍攻击范围,1倍攻击力,一倍速 | |||||
| { | |||||
| public OrdinaryBullet(Character player, int radius = GameData.bulletRadius) : | |||||
| 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 int Speed => GameData.basicBulletMoveSpeed / 6 * 5; | |||||
| public override bool CanAttack(GameObj target) | |||||
| { | |||||
| // 圆形攻击范围 | |||||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||||
| } | |||||
| public override BulletType TypeOfBullet => BulletType.OrdinaryBullet; | |||||
| } | |||||
| internal sealed class FastBullet : Bullet // 1倍攻击范围,0.2倍攻击力,2倍速 | |||||
| { | |||||
| public FastBullet(Character player, int radius = GameData.bulletRadius) : | |||||
| 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 int Speed => 5 * GameData.basicBulletMoveSpeed / 3; | |||||
| public override bool CanAttack(GameObj target) | |||||
| { | |||||
| // 圆形攻击范围 | |||||
| return XY.Distance(this.Position, target.Position) <= BulletBombRange; | |||||
| } | |||||
| public override BulletType TypeOfBullet => BulletType.FastBullet; | |||||
| } | |||||
| internal sealed class LineBullet : Bullet // 直线爆炸,宽度1格,长度为2倍爆炸范围 | |||||
| { | |||||
| public LineBullet(Character player, int radius = GameData.bulletRadius) : | |||||
| 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 int Speed => GameData.basicBulletMoveSpeed / 3; | |||||
| public override bool CanAttack(GameObj target) | |||||
| { | |||||
| double FacingAngle = Math.Atan2(this.FacingDirection.y, this.FacingDirection.x); | |||||
| if (Math.Abs(FacingAngle - Math.PI / 2) < 1e-2) | |||||
| { | |||||
| if (target.Position.y - this.Position.y > BulletBombRange) | |||||
| return false; | |||||
| if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| else if (Math.Abs(FacingAngle - Math.PI * 3 / 2) < 1e-2) | |||||
| { | |||||
| if (target.Position.y - this.Position.y < -BulletBombRange) | |||||
| return false; | |||||
| if (target.Position.x < this.Position.x + GameData.numOfPosGridPerCell / 2 && target.Position.x > this.Position.x - GameData.numOfPosGridPerCell / 2) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| else if (Math.Abs(FacingAngle) < 1e-2) | |||||
| { | |||||
| if (target.Position.x - this.Position.x > BulletBombRange) | |||||
| return false; | |||||
| if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| else if (Math.Abs(FacingAngle - Math.PI) < 1e-2) | |||||
| { | |||||
| if (target.Position.x - this.Position.x < -BulletBombRange) | |||||
| return false; | |||||
| if (target.Position.y < this.Position.y + GameData.numOfPosGridPerCell / 2 && target.Position.y > this.Position.y - GameData.numOfPosGridPerCell / 2) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| double vertical = Math.Tan(FacingAngle + Math.PI / 2); | |||||
| bool posValue = vertical * Math.Cos(FacingAngle) - Math.Sin(FacingAngle) > 0; | |||||
| double dist; | |||||
| dist = vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y) / Math.Sqrt(1 + vertical * vertical); | |||||
| if (Math.Abs(dist) > BulletBombRange) | |||||
| return false; | |||||
| else if (dist < 0 && posValue) // 位于直线两侧 | |||||
| return false; | |||||
| vertical = Math.Tan(FacingAngle); | |||||
| dist = Math.Abs(vertical * (target.Position.x - this.Position.x) - (target.Position.y - this.Position.y)) / Math.Sqrt(1 + vertical * vertical); | |||||
| if (dist > GameData.numOfPosGridPerCell / 2) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| 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; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,172 +0,0 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Runtime.InteropServices; | |||||
| using System.Threading; | |||||
| using Preparation.Utility; | |||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public partial class Character | |||||
| { | |||||
| private readonly BuffManeger buffManeger; | |||||
| /// <summary> | |||||
| /// 角色携带的buff管理器 | |||||
| /// </summary> | |||||
| private class BuffManeger | |||||
| { | |||||
| [StructLayout(LayoutKind.Explicit, Size = 8)] | |||||
| private struct BuffValue // buff参数联合体类型,可能是int或double | |||||
| { | |||||
| [FieldOffset(0)] | |||||
| public int iValue; | |||||
| [FieldOffset(0)] | |||||
| public double lfValue; | |||||
| public BuffValue(int intValue) | |||||
| { | |||||
| this.lfValue = 0.0; | |||||
| this.iValue = intValue; | |||||
| } | |||||
| public BuffValue(double longFloatValue) | |||||
| { | |||||
| this.iValue = 0; | |||||
| this.lfValue = longFloatValue; | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// buff列表 | |||||
| /// </summary> | |||||
| private readonly LinkedList<BuffValue>[] buffList; | |||||
| private readonly object[] buffListLock; | |||||
| private void AddBuff(BuffValue bf, int buffTime, BuffType buffType, Action ReCalculateFunc) | |||||
| { | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| LinkedListNode<BuffValue> buffNode; | |||||
| lock (buffListLock[(int)buffType]) | |||||
| { | |||||
| buffNode = buffList[(int)buffType].AddLast(bf); | |||||
| } | |||||
| ReCalculateFunc(); | |||||
| Thread.Sleep(buffTime); | |||||
| try | |||||
| { | |||||
| lock (buffListLock[(int)buffType]) | |||||
| { | |||||
| buffList[(int)buffType].Remove(buffNode); | |||||
| } | |||||
| } | |||||
| catch | |||||
| { | |||||
| } | |||||
| ReCalculateFunc(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| } | |||||
| private int ReCalculateFloatBuff(BuffType buffType, int orgVal, int maxVal, int minVal) | |||||
| { | |||||
| double times = 1.0; | |||||
| lock (buffListLock[(int)buffType]) | |||||
| { | |||||
| foreach (var add in buffList[(int)buffType]) | |||||
| { | |||||
| times *= add.lfValue; | |||||
| } | |||||
| } | |||||
| return Math.Max(Math.Min((int)Math.Round(orgVal * times), maxVal), minVal); | |||||
| } | |||||
| public void AddMoveSpeed(double add, int buffTime, Action<int> SetNewMoveSpeed, int orgMoveSpeed) => AddBuff(new BuffValue(add), buffTime, BuffType.AddSpeed, () => SetNewMoveSpeed(ReCalculateFloatBuff(BuffType.AddSpeed, orgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed))); | |||||
| public bool HasFasterSpeed | |||||
| { | |||||
| get { | |||||
| lock (buffListLock[(int)BuffType.AddSpeed]) | |||||
| { | |||||
| return buffList[(int)BuffType.AddSpeed].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public void AddShield(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Shield, () => | |||||
| {}); | |||||
| public bool HasShield | |||||
| { | |||||
| get { | |||||
| lock (buffListLock[(int)BuffType.Shield]) | |||||
| { | |||||
| return buffList[(int)BuffType.Shield].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public void AddLIFE(int totelTime) => AddBuff(new BuffValue(), totelTime, BuffType.AddLIFE, () => | |||||
| {}); | |||||
| public bool HasLIFE | |||||
| { | |||||
| get { | |||||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||||
| { | |||||
| return buffList[(int)BuffType.AddLIFE].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public bool TryActivatingLIFE() | |||||
| { | |||||
| if (HasLIFE) | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||||
| { | |||||
| buffList[(int)BuffType.AddLIFE].Clear(); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public void AddSpear(int spearTime) => AddBuff(new BuffValue(), spearTime, BuffType.Spear, () => | |||||
| {}); | |||||
| public bool HasSpear | |||||
| { | |||||
| get { | |||||
| lock (buffListLock[(int)BuffType.Spear]) | |||||
| { | |||||
| return buffList[(int)BuffType.Spear].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// 清除所有buff | |||||
| /// </summary> | |||||
| public void ClearAll() | |||||
| { | |||||
| for (int i = 0; i < buffList.Length; ++i) | |||||
| { | |||||
| lock (buffListLock[i]) | |||||
| { | |||||
| buffList[i].Clear(); | |||||
| } | |||||
| } | |||||
| } | |||||
| public BuffManeger() | |||||
| { | |||||
| var buffTypeArray = Enum.GetValues(typeof(BuffType)); | |||||
| buffList = new LinkedList<BuffValue>[buffTypeArray.Length]; | |||||
| buffListLock = new object[buffList.Length]; | |||||
| int i = 0; | |||||
| foreach (BuffType type in buffTypeArray) | |||||
| { | |||||
| buffList[i] = new LinkedList<BuffValue>(); | |||||
| buffListLock[i++] = new object(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -1,51 +0,0 @@ | |||||
| using Preparation.Utility; | |||||
| using System.Collections.Generic; | |||||
| using System; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public partial class Character | |||||
| { | |||||
| private delegate bool CharacterActiveSkill(Character player); // 返回值:是否成功释放了技能 | |||||
| private delegate void CharacterPassiveSkill(Character player); | |||||
| private readonly CharacterActiveSkill commonSkill; | |||||
| private readonly ActiveSkillType commonSkillType; | |||||
| public ActiveSkillType CommonSkillType => commonSkillType; | |||||
| private readonly CharacterType passiveSkillType; | |||||
| public CharacterType PassiveSkillType => passiveSkillType; | |||||
| public bool UseCommonSkill() | |||||
| { | |||||
| return commonSkill(this); | |||||
| } | |||||
| private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能 | |||||
| public int TimeUntilCommonSkillAvailable | |||||
| { | |||||
| get => timeUntilCommonSkillAvailable; | |||||
| set { | |||||
| lock (gameObjLock) | |||||
| timeUntilCommonSkillAvailable = value < 0 ? 0 : value; | |||||
| } | |||||
| } | |||||
| readonly CharacterPassiveSkill passiveSkill; | |||||
| public void UsePassiveSkill() | |||||
| { | |||||
| passiveSkill(this); | |||||
| return; | |||||
| } | |||||
| public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType passiveSkillType, ActiveSkillType commonSkillType) : | |||||
| base(initPos, initRadius, initPlace, GameObjType.Character) | |||||
| { | |||||
| this.CanMove = true; | |||||
| this.score = 0; | |||||
| this.propInventory = null; | |||||
| this.buffManeger = new BuffManeger(); | |||||
| // UsePassiveSkill(); //创建player时开始被动技能,这一过程也可以放到gamestart时进行 | |||||
| // 这可以放在AddPlayer中做 | |||||
| Debugger.Output(this, "constructed!"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,176 @@ | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Runtime.InteropServices; | |||||
| using System.Threading; | |||||
| using Preparation.Utility; | |||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public partial class Character | |||||
| { | |||||
| private readonly BuffManeger buffManeger; | |||||
| /// <summary> | |||||
| /// 角色携带的buff管理器 | |||||
| /// </summary> | |||||
| private class BuffManeger | |||||
| { | |||||
| [StructLayout(LayoutKind.Explicit, Size = 8)] | |||||
| private struct BuffValue // buff参数联合体类型,可能是int或double | |||||
| { | |||||
| [FieldOffset(0)] | |||||
| public int iValue; | |||||
| [FieldOffset(0)] | |||||
| public double lfValue; | |||||
| public BuffValue(int intValue) | |||||
| { | |||||
| this.lfValue = 0.0; | |||||
| this.iValue = intValue; | |||||
| } | |||||
| public BuffValue(double longFloatValue) | |||||
| { | |||||
| this.iValue = 0; | |||||
| this.lfValue = longFloatValue; | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// buff列表 | |||||
| /// </summary> | |||||
| private readonly LinkedList<BuffValue>[] buffList; | |||||
| private readonly object[] buffListLock; | |||||
| private void AddBuff(BuffValue bf, int buffTime, BuffType buffType, Action ReCalculateFunc) | |||||
| { | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| LinkedListNode<BuffValue> buffNode; | |||||
| lock (buffListLock[(int)buffType]) | |||||
| { | |||||
| buffNode = buffList[(int)buffType].AddLast(bf); | |||||
| } | |||||
| ReCalculateFunc(); | |||||
| Thread.Sleep(buffTime); | |||||
| try | |||||
| { | |||||
| lock (buffListLock[(int)buffType]) | |||||
| { | |||||
| buffList[(int)buffType].Remove(buffNode); | |||||
| } | |||||
| } | |||||
| catch | |||||
| { | |||||
| } | |||||
| ReCalculateFunc(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| } | |||||
| private int ReCalculateFloatBuff(BuffType buffType, int orgVal, int maxVal, int minVal) | |||||
| { | |||||
| double times = 1.0; | |||||
| lock (buffListLock[(int)buffType]) | |||||
| { | |||||
| foreach (var add in buffList[(int)buffType]) | |||||
| { | |||||
| times *= add.lfValue; | |||||
| } | |||||
| } | |||||
| return Math.Max(Math.Min((int)Math.Round(orgVal * times), maxVal), minVal); | |||||
| } | |||||
| public void AddMoveSpeed(double add, int buffTime, Action<int> SetNewMoveSpeed, int orgMoveSpeed) => AddBuff(new BuffValue(add), buffTime, BuffType.AddSpeed, () => SetNewMoveSpeed(ReCalculateFloatBuff(BuffType.AddSpeed, orgMoveSpeed, GameData.MaxSpeed, GameData.MinSpeed))); | |||||
| public bool HasFasterSpeed | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.AddSpeed]) | |||||
| { | |||||
| return buffList[(int)BuffType.AddSpeed].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public void AddShield(int shieldTime) => AddBuff(new BuffValue(), shieldTime, BuffType.Shield, () => | |||||
| { }); | |||||
| public bool HasShield | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.Shield]) | |||||
| { | |||||
| return buffList[(int)BuffType.Shield].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public void AddLIFE(int totelTime) => AddBuff(new BuffValue(), totelTime, BuffType.AddLIFE, () => | |||||
| { }); | |||||
| public bool HasLIFE | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||||
| { | |||||
| return buffList[(int)BuffType.AddLIFE].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| public bool TryActivatingLIFE() | |||||
| { | |||||
| if (HasLIFE) | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.AddLIFE]) | |||||
| { | |||||
| buffList[(int)BuffType.AddLIFE].Clear(); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public void AddSpear(int spearTime) => AddBuff(new BuffValue(), spearTime, BuffType.Spear, () => | |||||
| { }); | |||||
| public bool HasSpear | |||||
| { | |||||
| get | |||||
| { | |||||
| lock (buffListLock[(int)BuffType.Spear]) | |||||
| { | |||||
| return buffList[(int)BuffType.Spear].Count != 0; | |||||
| } | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// 清除所有buff | |||||
| /// </summary> | |||||
| public void ClearAll() | |||||
| { | |||||
| for (int i = 0; i < buffList.Length; ++i) | |||||
| { | |||||
| lock (buffListLock[i]) | |||||
| { | |||||
| buffList[i].Clear(); | |||||
| } | |||||
| } | |||||
| } | |||||
| public BuffManeger() | |||||
| { | |||||
| var buffTypeArray = Enum.GetValues(typeof(BuffType)); | |||||
| buffList = new LinkedList<BuffValue>[buffTypeArray.Length]; | |||||
| buffListLock = new object[buffList.Length]; | |||||
| int i = 0; | |||||
| foreach (BuffType type in buffTypeArray) | |||||
| { | |||||
| buffList[i] = new LinkedList<BuffValue>(); | |||||
| buffListLock[i++] = new object(); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,101 @@ | |||||
| using GameClass.Skill; | |||||
| using Preparation.Utility; | |||||
| using System.Collections.Generic; | |||||
| using System; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public partial class Character | |||||
| { | |||||
| private delegate bool CharacterActiveSkill(Character player); // 返回值:是否成功释放了技能 | |||||
| private delegate void CharacterPassiveSkill(Character player); | |||||
| private readonly CharacterActiveSkill commonSkill; | |||||
| private readonly ActiveSkillType commonSkillType; | |||||
| public ActiveSkillType CommonSkillType => commonSkillType; | |||||
| private readonly CharacterType characterType; | |||||
| public CharacterType CharacterType => characterType; | |||||
| public bool UseCommonSkill() | |||||
| { | |||||
| return commonSkill(this); | |||||
| } | |||||
| private int timeUntilCommonSkillAvailable = 0; // 还剩多少时间可以使用普通技能 | |||||
| public int TimeUntilCommonSkillAvailable | |||||
| { | |||||
| get => timeUntilCommonSkillAvailable; | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | |||||
| timeUntilCommonSkillAvailable = value < 0 ? 0 : value; | |||||
| } | |||||
| } | |||||
| readonly CharacterPassiveSkill passiveSkill; | |||||
| public void UsePassiveSkill() | |||||
| { | |||||
| passiveSkill(this); | |||||
| return; | |||||
| } | |||||
| public Character(XY initPos, int initRadius, PlaceType initPlace, CharacterType characterType, ActiveSkillType commonSkillType) : | |||||
| base(initPos, initRadius, initPlace, GameObjType.Character) | |||||
| { | |||||
| this.CanMove = true; | |||||
| this.score = 0; | |||||
| this.propInventory = null; | |||||
| this.buffManeger = new BuffManeger(); | |||||
| IPassiveSkill pSkill; | |||||
| ICommonSkill cSkill; | |||||
| switch (passiveSkillType) | |||||
| { | |||||
| case this.CharacterType.RecoverAfterBattle: | |||||
| pSkill = new RecoverAfterBattle(); | |||||
| break; | |||||
| case this.CharacterType.SpeedUpWhenLeavingGrass: | |||||
| pSkill = new SpeedUpWhenLeavingGrass(); | |||||
| break; | |||||
| case this.CharacterType.Vampire: | |||||
| pSkill = new Vampire(); | |||||
| break; | |||||
| default: | |||||
| pSkill = new NoPassiveSkill(); | |||||
| break; | |||||
| } | |||||
| switch (commonSkillType) | |||||
| { | |||||
| case ActiveSkillType.BecomeAssassin: | |||||
| cSkill = new BecomeAssassin(); | |||||
| break; | |||||
| case ActiveSkillType.BecomeVampire: | |||||
| cSkill = new BecomeVampire(); | |||||
| break; | |||||
| case ActiveSkillType.NuclearWeapon: | |||||
| cSkill = new NuclearWeapon(); | |||||
| break; | |||||
| case ActiveSkillType.SuperFast: | |||||
| cSkill = new SuperFast(); | |||||
| break; | |||||
| default: | |||||
| cSkill = new NoCommonSkill(); | |||||
| break; | |||||
| } | |||||
| this.MaxHp = cSkill.MaxHp; | |||||
| 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; | |||||
| this.OriBulletOfPlayer = pSkill.InitBullet; | |||||
| this.passiveSkill = pSkill.SkillEffect; | |||||
| this.commonSkill = cSkill.SkillEffect; | |||||
| this.passiveSkillType = passiveSkillType; | |||||
| this.commonSkillType = commonSkillType; | |||||
| // UsePassiveSkill(); //创建player时开始被动技能,这一过程也可以放到gamestart时进行 | |||||
| // 这可以放在AddPlayer中做 | |||||
| Debugger.Output(this, "constructed!"); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -11,9 +11,8 @@ namespace GameClass.GameObj | |||||
| { | { | ||||
| private readonly object beAttackedLock = new(); | private readonly object beAttackedLock = new(); | ||||
| #region 角色的基本属性及方法,包括与道具的交互方法 | |||||
| /* | |||||
| //THUAI5子弹 | |||||
| #region 角色的基本属性及方法,包括与道具的交互方法 | |||||
| /// <summary> | /// <summary> | ||||
| /// 装弹冷却 | /// 装弹冷却 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -21,8 +20,9 @@ namespace GameClass.GameObj | |||||
| public int CD | public int CD | ||||
| { | { | ||||
| get => cd; | get => cd; | ||||
| private | |||||
| set { | |||||
| private | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| cd = value; | cd = value; | ||||
| @@ -35,13 +35,14 @@ namespace GameClass.GameObj | |||||
| public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | public int MaxBulletNum => maxBulletNum; // 人物最大子弹数 | ||||
| protected int bulletNum; | protected int bulletNum; | ||||
| public int BulletNum => bulletNum; // 目前持有的子弹数 | public int BulletNum => bulletNum; // 目前持有的子弹数 | ||||
| */ | |||||
| public int MaxHp { get; protected set; } // 最大血量 | public int MaxHp { get; protected set; } // 最大血量 | ||||
| protected int hp; | protected int hp; | ||||
| public int HP | public int HP | ||||
| { | { | ||||
| get => hp; | get => hp; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| hp = value <= MaxHp ? value : MaxHp; | hp = value <= MaxHp ? value : MaxHp; | ||||
| } | } | ||||
| @@ -55,13 +56,31 @@ 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 | ||||
| { | { | ||||
| get => vampire; | get => vampire; | ||||
| set { | |||||
| set | |||||
| { | |||||
| if (value > 1) | |||||
| lock (gameObjLock) | |||||
| vampire = 1; | |||||
| else if (value < 0) | |||||
| lock (gameObjLock) | |||||
| vampire = 0; | |||||
| else | |||||
| lock (gameObjLock) | |||||
| vampire = value; | |||||
| } | |||||
| } | |||||
| private double oriVampire = 0; | |||||
| public double OriVampire | |||||
| { | |||||
| get => oriVampire; | |||||
| set | |||||
| { | |||||
| if (value > 1) | if (value > 1) | ||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| vampire = 1; | vampire = 1; | ||||
| @@ -73,26 +92,27 @@ namespace GameClass.GameObj | |||||
| vampire = value; | vampire = value; | ||||
| } | } | ||||
| } | } | ||||
| private double OriVampire { get; } | |||||
| /* | |||||
| public readonly BulletType OriBulletOfPlayer; | public readonly BulletType OriBulletOfPlayer; | ||||
| private BulletType bulletOfPlayer; | private BulletType bulletOfPlayer; | ||||
| public BulletType BulletOfPlayer | public BulletType BulletOfPlayer | ||||
| { | { | ||||
| get => bulletOfPlayer; | get => bulletOfPlayer; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| bulletOfPlayer = value; | bulletOfPlayer = value; | ||||
| } | } | ||||
| } | } | ||||
| */ | |||||
| private Prop? propInventory; | private Prop? propInventory; | ||||
| public Prop? PropInventory // 持有的道具 | public Prop? PropInventory // 持有的道具 | ||||
| { | { | ||||
| get => propInventory; | get => propInventory; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| propInventory = value; | propInventory = value; | ||||
| @@ -122,7 +142,8 @@ namespace GameClass.GameObj | |||||
| public bool IsModifyingProp | public bool IsModifyingProp | ||||
| { | { | ||||
| get => isModifyingProp; | get => isModifyingProp; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| isModifyingProp = value; | isModifyingProp = value; | ||||
| @@ -137,14 +158,15 @@ namespace GameClass.GameObj | |||||
| public bool IsInvisible | public bool IsInvisible | ||||
| { | { | ||||
| get => isInvisible; | get => isInvisible; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| isInvisible = value; | isInvisible = value; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* | |||||
| /// <summary> | /// <summary> | ||||
| /// 进行一次远程攻击 | /// 进行一次远程攻击 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -196,7 +218,7 @@ namespace GameClass.GameObj | |||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| */ | |||||
| /// <summary> | /// <summary> | ||||
| /// 尝试加血 | /// 尝试加血 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -265,7 +287,7 @@ namespace GameClass.GameObj | |||||
| Debugger.Output(this, " 's score has been subed to: " + score.ToString()); | Debugger.Output(this, " 's score has been subed to: " + score.ToString()); | ||||
| } | } | ||||
| } | } | ||||
| /* | |||||
| /// <summary> | /// <summary> | ||||
| /// 遭受攻击 | /// 遭受攻击 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -326,7 +348,7 @@ namespace GameClass.GameObj | |||||
| return hp <= 0; | return hp <= 0; | ||||
| } | } | ||||
| } | } | ||||
| */ | |||||
| /// <summary> | /// <summary> | ||||
| /// 角色所属队伍ID | /// 角色所属队伍ID | ||||
| /// </summary> | /// </summary> | ||||
| @@ -334,7 +356,8 @@ namespace GameClass.GameObj | |||||
| public long TeamID | public long TeamID | ||||
| { | { | ||||
| get => teamID; | get => teamID; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| teamID = value; | teamID = value; | ||||
| @@ -346,7 +369,8 @@ namespace GameClass.GameObj | |||||
| public long PlayerID | public long PlayerID | ||||
| { | { | ||||
| get => playerID; | get => playerID; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| playerID = value; | playerID = value; | ||||
| @@ -360,16 +384,17 @@ namespace GameClass.GameObj | |||||
| public string Message | public string Message | ||||
| { | { | ||||
| get => message; | get => message; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| message = value; | message = value; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endregion | |||||
| #endregion | |||||
| #region 角色拥有的buff相关属性、方法 | |||||
| #region 角色拥有的buff相关属性、方法 | |||||
| public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManeger.AddMoveSpeed(add, buffTime, newVal => | public void AddMoveSpeed(int buffTime, double add = 2.0) => buffManeger.AddMoveSpeed(add, buffTime, newVal => | ||||
| { MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; }, | { MoveSpeed = newVal < GameData.characterMaxSpeed ? newVal : GameData.characterMaxSpeed; }, | ||||
| OrgMoveSpeed); | OrgMoveSpeed); | ||||
| @@ -387,7 +412,8 @@ namespace GameClass.GameObj | |||||
| private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | private Array buffTypeArray = Enum.GetValues(typeof(BuffType)); | ||||
| public Dictionary<BuffType, bool> Buff | public Dictionary<BuffType, bool> Buff | ||||
| { | { | ||||
| get { | |||||
| get | |||||
| { | |||||
| Dictionary<BuffType, bool> buff = new Dictionary<BuffType, bool>(); | Dictionary<BuffType, bool> buff = new Dictionary<BuffType, bool>(); | ||||
| foreach (BuffType type in buffTypeArray) | foreach (BuffType type in buffTypeArray) | ||||
| { | { | ||||
| @@ -420,7 +446,7 @@ namespace GameClass.GameObj | |||||
| hp = MaxHp; | hp = MaxHp; | ||||
| } | } | ||||
| } | } | ||||
| #endregion | |||||
| #endregion | |||||
| public override void Reset() // 要加锁吗? | public override void Reset() // 要加锁吗? | ||||
| { | { | ||||
| _ = AddDeathCount(); | _ = AddDeathCount(); | ||||
| @@ -29,8 +29,9 @@ namespace GameClass.GameObj | |||||
| public XY Position | public XY Position | ||||
| { | { | ||||
| get => position; | get => position; | ||||
| protected | |||||
| set { | |||||
| protected | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| position = value; | position = value; | ||||
| @@ -43,7 +44,8 @@ namespace GameClass.GameObj | |||||
| public XY FacingDirection | public XY FacingDirection | ||||
| { | { | ||||
| get => facingDirection; | get => facingDirection; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| facingDirection = value; | facingDirection = value; | ||||
| } | } | ||||
| @@ -54,7 +56,8 @@ namespace GameClass.GameObj | |||||
| public bool CanMove | public bool CanMove | ||||
| { | { | ||||
| get => canMove; | get => canMove; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| canMove = value; | canMove = value; | ||||
| @@ -66,7 +69,8 @@ namespace GameClass.GameObj | |||||
| public bool IsMoving | public bool IsMoving | ||||
| { | { | ||||
| get => isMoving; | get => isMoving; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| isMoving = value; | isMoving = value; | ||||
| @@ -78,7 +82,8 @@ namespace GameClass.GameObj | |||||
| public bool IsResetting | public bool IsResetting | ||||
| { | { | ||||
| get => isResetting; | get => isResetting; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| isResetting = value; | isResetting = value; | ||||
| @@ -92,7 +97,8 @@ namespace GameClass.GameObj | |||||
| public PlaceType Place | public PlaceType Place | ||||
| { | { | ||||
| get => place; | get => place; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| place = value; | place = value; | ||||
| @@ -106,7 +112,8 @@ namespace GameClass.GameObj | |||||
| public int MoveSpeed | public int MoveSpeed | ||||
| { | { | ||||
| get => moveSpeed; | get => moveSpeed; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| moveSpeed = value; | moveSpeed = value; | ||||
| @@ -120,8 +127,9 @@ namespace GameClass.GameObj | |||||
| public int OrgMoveSpeed | public int OrgMoveSpeed | ||||
| { | { | ||||
| get => orgMoveSpeed; | get => orgMoveSpeed; | ||||
| protected | |||||
| set { | |||||
| protected | |||||
| set | |||||
| { | |||||
| orgMoveSpeed = value; | orgMoveSpeed = value; | ||||
| } | } | ||||
| } | } | ||||
| @@ -12,7 +12,8 @@ namespace GameClass.GameObj | |||||
| public ICharacter? Parent | public ICharacter? Parent | ||||
| { | { | ||||
| get => parent; | get => parent; | ||||
| set { | |||||
| set | |||||
| { | |||||
| lock (gameObjLock) | lock (gameObjLock) | ||||
| { | { | ||||
| parent = value; | parent = value; | ||||
| @@ -0,0 +1,24 @@ | |||||
| using Preparation.Utility; | |||||
| using System; | |||||
| using System.Collections.Generic; | |||||
| using System.Linq; | |||||
| using System.Text; | |||||
| using System.Threading.Tasks; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| // 为方便界面组做道具拾起特效,现引入“被捡起的道具”,在每帧发送给界面组 | |||||
| public class PickedProp : GameObj | |||||
| { | |||||
| public override ShapeType Shape => ShapeType.Circle; | |||||
| public override bool IsRigid => false; | |||||
| public long MappingID { get; } | |||||
| public Prop PropHasPicked; | |||||
| public PickedProp(Prop prop) : | |||||
| base(prop.Position, prop.Radius, prop.Place, GameObjType.PickedProp) | |||||
| { | |||||
| this.PropHasPicked = prop; | |||||
| this.MappingID = prop.ID; | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,125 @@ | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| using Preparation.GameData; | |||||
| namespace GameClass.GameObj | |||||
| { | |||||
| public abstract class Prop : ObjOfCharacter | |||||
| { | |||||
| protected bool laid = false; | |||||
| public bool Laid => laid; // 道具是否放置在地图上 | |||||
| public override bool IsRigid => true; | |||||
| protected override bool IgnoreCollideExecutor(IGameObj targetObj) | |||||
| { | |||||
| if (targetObj.Type == GameObjType.BirthPoint || targetObj.Type == GameObjType.Prop || targetObj.Type == GameObjType.Bullet || targetObj.Type == GameObjType.Character) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| public override ShapeType Shape => ShapeType.Square; | |||||
| public abstract PropType GetPropType(); | |||||
| public Prop(XY initPos, int radius = GameData.PropRadius) : | |||||
| base(initPos, radius, PlaceType.Land, GameObjType.Prop) | |||||
| { | |||||
| this.CanMove = false; | |||||
| this.moveSpeed = GameData.PropMoveSpeed; | |||||
| } | |||||
| public void SetNewPos(XY pos) | |||||
| { | |||||
| this.Position = pos; | |||||
| } | |||||
| } | |||||
| /// <summary> | |||||
| /// 增益道具 | |||||
| /// </summary> | |||||
| public abstract class BuffProp : Prop | |||||
| { | |||||
| public BuffProp(XY initPos) : | |||||
| base(initPos) | |||||
| { | |||||
| } | |||||
| } | |||||
| ///// <summary> | |||||
| ///// 坑人地雷 | |||||
| ///// </summary> | |||||
| // public abstract class DebuffMine : Prop | |||||
| //{ | |||||
| // public DebuffMine(XYPosition initPos) : base(initPos) { } | |||||
| // } | |||||
| #region 所有增益道具 | |||||
| /// <summary> | |||||
| /// 增加速度 | |||||
| /// </summary> | |||||
| public sealed class AddSpeed : BuffProp | |||||
| { | |||||
| public AddSpeed(XY initPos) : | |||||
| base(initPos) | |||||
| { | |||||
| } | |||||
| public override PropType GetPropType() => PropType.addSpeed; | |||||
| } | |||||
| /// <summary> | |||||
| /// 复活甲 | |||||
| /// </summary> | |||||
| public sealed class AddLIFE : BuffProp | |||||
| { | |||||
| public AddLIFE(XY initPos) : | |||||
| base(initPos) | |||||
| { | |||||
| } | |||||
| public override PropType GetPropType() => PropType.addLIFE; | |||||
| } | |||||
| /// <summary> | |||||
| /// 护盾 | |||||
| /// </summary> | |||||
| public sealed class Shield : BuffProp | |||||
| { | |||||
| public Shield(XY initPos) : | |||||
| base(initPos) | |||||
| { | |||||
| } | |||||
| public override PropType GetPropType() => PropType.Shield; | |||||
| } | |||||
| /// <summary> | |||||
| /// 矛 | |||||
| /// </summary> | |||||
| public sealed class Spear : BuffProp | |||||
| { | |||||
| public Spear(XY initPos) : | |||||
| base(initPos) | |||||
| { | |||||
| } | |||||
| public override PropType GetPropType() => PropType.Spear; | |||||
| } | |||||
| #endregion | |||||
| // #region 所有坑人地雷 | |||||
| ///// <summary> | |||||
| ///// 减速 | |||||
| ///// </summary> | |||||
| // public sealed class MinusSpeed : DebuffMine | |||||
| //{ | |||||
| // public MinusSpeed(XYPosition initPos) : base(initPos) { } | |||||
| // public override PropType GetPropType() => PropType.minusSpeed; | |||||
| // } | |||||
| ///// <summary> | |||||
| ///// 减少攻击力 | |||||
| ///// </summary> | |||||
| // public sealed class MinusAP : DebuffMine | |||||
| //{ | |||||
| // public MinusAP(XYPosition initPos) : base(initPos) { } | |||||
| // public override PropType GetPropType() => PropType.minusAP; | |||||
| // } | |||||
| ///// <summary> | |||||
| ///// 增加冷却 | |||||
| ///// </summary> | |||||
| // public sealed class AddCD : DebuffMine | |||||
| //{ | |||||
| // public AddCD(XYPosition initPos) : base(initPos) { } | |||||
| // public override PropType GetPropType() => PropType.addCD; | |||||
| // } | |||||
| // #endregion | |||||
| } | |||||
| @@ -13,7 +13,8 @@ namespace GameClass.GameObj | |||||
| private readonly List<Character> playerList; | private readonly List<Character> playerList; | ||||
| public int Score | public int Score | ||||
| { | { | ||||
| get { | |||||
| get | |||||
| { | |||||
| int score = 0; | int score = 0; | ||||
| foreach (var player in playerList) | foreach (var player in playerList) | ||||
| score += player.Score; | score += player.Score; | ||||
| @@ -0,0 +1,219 @@ | |||||
| using GameClass.GameObj; | |||||
| using System.Threading; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| using Preparation.GameData; | |||||
| using System; | |||||
| using Timothy.FrameRateTask; | |||||
| namespace GameClass.Skill | |||||
| { | |||||
| public class BecomeVampire : ICommonSkill //化身吸血鬼 | |||||
| { | |||||
| private const int moveSpeed = GameData.basicMoveSpeed; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| 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 bool SkillEffect(Character player) | |||||
| { | |||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| { | |||||
| player.Vampire += 0.5; | |||||
| Debugger.Output(player, "becomes vampire!"); | |||||
| }, | |||||
| () => | |||||
| { | |||||
| double tempVam = player.Vampire - 0.5; | |||||
| player.Vampire = tempVam < player.OriVampire ? player.OriVampire : tempVam; | |||||
| }); | |||||
| } | |||||
| } | |||||
| public class BecomeAssassin : ICommonSkill //化身刺客,隐身 | |||||
| { | |||||
| 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 bool SkillEffect(Character player) | |||||
| { | |||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| { | |||||
| player.IsInvisible = true; | |||||
| Debugger.Output(player, "uses atombomb!"); | |||||
| }, | |||||
| () => { player.IsInvisible = false; }); | |||||
| } | |||||
| } | |||||
| public class NuclearWeapon : ICommonSkill //核武器 | |||||
| { | |||||
| private const int moveSpeed = GameData.basicMoveSpeed / 3 * 4; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| 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 bool SkillEffect(Character player) | |||||
| { | |||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| { | |||||
| player.BulletOfPlayer = BulletType.AtomBomb; | |||||
| Debugger.Output(player, "uses atombomb!"); | |||||
| }, | |||||
| () => { player.BulletOfPlayer = player.OriBulletOfPlayer; }); | |||||
| } | |||||
| } | |||||
| public class SuperFast : ICommonSkill //3倍速 | |||||
| { | |||||
| private const int moveSpeed = GameData.basicMoveSpeed * 4 / 3; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| 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 bool SkillEffect(Character player) | |||||
| { | |||||
| return CommonSkillFactory.SkillEffect(this, player, () => | |||||
| { | |||||
| player.AddMoveSpeed(this.DurationTime, 3.0); | |||||
| Debugger.Output(player, "moves very fast!"); | |||||
| }, | |||||
| () => { }); | |||||
| } | |||||
| } | |||||
| public class NoCommonSkill : ICommonSkill //这种情况不该发生,定义着以防意外 | |||||
| { | |||||
| private const int moveSpeed = GameData.basicMoveSpeed; | |||||
| public int MoveSpeed => moveSpeed; | |||||
| 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 bool SkillEffect(Character player) | |||||
| { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| public static class CommonSkillFactory | |||||
| { | |||||
| public static bool SkillEffect(ICommonSkill commonSkill, Character player, Action startSkill, Action endSkill) | |||||
| { | |||||
| lock (commonSkill.CommonSkillLock) | |||||
| { | |||||
| if (player.TimeUntilCommonSkillAvailable == 0) | |||||
| { | |||||
| player.TimeUntilCommonSkillAvailable = commonSkill.SkillCD; | |||||
| new Thread | |||||
| (() => | |||||
| { | |||||
| startSkill(); | |||||
| new FrameRateTaskExecutor<int> | |||||
| ( | |||||
| () => !player.IsResetting, | |||||
| () => | |||||
| { | |||||
| player.TimeUntilCommonSkillAvailable -= (int)GameData.frameDuration; | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| () => 0, | |||||
| maxTotalDuration: (long)(commonSkill.DurationTime) | |||||
| ) | |||||
| { | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| }.Start(); | |||||
| endSkill(); | |||||
| Debugger.Output(player, "return to normal."); | |||||
| new FrameRateTaskExecutor<int> | |||||
| ( | |||||
| () => player.TimeUntilCommonSkillAvailable > 0 && !player.IsResetting, | |||||
| () => | |||||
| { | |||||
| player.TimeUntilCommonSkillAvailable -= (int)GameData.frameDuration; | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| () => 0, | |||||
| maxTotalDuration: (long)(commonSkill.SkillCD - commonSkill.DurationTime) | |||||
| ) | |||||
| { | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| }.Start(); | |||||
| player.TimeUntilCommonSkillAvailable = 0; | |||||
| Debugger.Output(player, "CommonSkill is ready."); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| return true; | |||||
| } | |||||
| else | |||||
| { | |||||
| Debugger.Output(player, "CommonSkill is cooling down!"); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,23 @@ | |||||
| using GameClass.GameObj; | |||||
| using Preparation.Utility; | |||||
| using System.Threading; | |||||
| namespace GameClass.Skill | |||||
| { | |||||
| public interface IPassiveSkill | |||||
| { | |||||
| public BulletType InitBullet { get; } | |||||
| public void SkillEffect(Character player); | |||||
| } | |||||
| public interface ICommonSkill | |||||
| { | |||||
| 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; } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,152 @@ | |||||
| using System; | |||||
| using System.Threading; | |||||
| using GameClass.GameObj; | |||||
| using Preparation.GameData; | |||||
| using Preparation.Interface; | |||||
| using Preparation.Utility; | |||||
| using Timothy.FrameRateTask; | |||||
| namespace GameClass.Skill //被动技能开局时就释放,持续到游戏结束 | |||||
| { | |||||
| public class RecoverAfterBattle : IPassiveSkill //脱战回血,普通子弹 | |||||
| { | |||||
| private readonly BulletType initBullet = BulletType.OrdinaryBullet; | |||||
| public BulletType InitBullet => initBullet; | |||||
| //以上参数以后再改 | |||||
| public void SkillEffect(Character player) | |||||
| { | |||||
| const int recoverDegree = 5; //每帧回复血量 | |||||
| int nowHP = player.HP; | |||||
| int lastHP = nowHP; | |||||
| long waitTime = 0; | |||||
| const long interval = 10000; //每隔interval时间不受伤害,角色即开始回血 | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int> | |||||
| ( | |||||
| () => true, | |||||
| () => | |||||
| { | |||||
| lastHP = nowHP; //lastHP等于上一帧的HP | |||||
| nowHP = player.HP; //nowHP更新为这一帧的HP | |||||
| if (lastHP > nowHP) //这一帧扣血了 | |||||
| { | |||||
| waitTime = 0; | |||||
| } | |||||
| else if (waitTime < interval) | |||||
| { | |||||
| waitTime += GameData.frameDuration; | |||||
| } | |||||
| if (waitTime >= interval) //回复时,每帧(50ms)回复5,即1s回复100。 | |||||
| player.TryAddHp(recoverDegree); | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| () => 0, | |||||
| maxTotalDuration: GameData.gameDuration | |||||
| ) | |||||
| { | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| TimeExceedAction = b => | |||||
| { | |||||
| if (b) Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||||
| #if DEBUG | |||||
| else | |||||
| { | |||||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| }.Start(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| } | |||||
| } | |||||
| public class SpeedUpWhenLeavingGrass : IPassiveSkill // 3倍速 | |||||
| { | |||||
| private readonly BulletType initBullet = BulletType.FastBullet; | |||||
| public BulletType InitBullet => initBullet; | |||||
| //以上参数以后再改 | |||||
| public void SkillEffect(Character player) | |||||
| { | |||||
| PlaceType nowPlace = player.Place; | |||||
| PlaceType lastPlace = nowPlace; | |||||
| bool speedup = false; | |||||
| const int SpeedUpTime = 2000; //加速时间:2s | |||||
| new Thread | |||||
| ( | |||||
| () => | |||||
| { | |||||
| new FrameRateTaskExecutor<int> | |||||
| ( | |||||
| () => true, | |||||
| () => | |||||
| { | |||||
| lastPlace = nowPlace; | |||||
| nowPlace = player.Place; | |||||
| if ((lastPlace == PlaceType.Grass1 || lastPlace == PlaceType.Grass2 || lastPlace == PlaceType.Grass3) && nowPlace == PlaceType.Land) | |||||
| { | |||||
| if (!speedup) | |||||
| { | |||||
| new Thread(() => | |||||
| { | |||||
| speedup = true; | |||||
| player.AddMoveSpeed(SpeedUpTime, 3.0); | |||||
| speedup = false; | |||||
| }) | |||||
| { IsBackground = true }.Start(); | |||||
| } | |||||
| } | |||||
| }, | |||||
| timeInterval: GameData.frameDuration, | |||||
| () => 0, | |||||
| maxTotalDuration: GameData.gameDuration | |||||
| ) | |||||
| { | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| TimeExceedAction = b => | |||||
| { | |||||
| if (b) Console.WriteLine("Fetal Error: The computer runs so slow that passive skill time exceeds!!!!!!"); | |||||
| #if DEBUG | |||||
| else | |||||
| { | |||||
| Console.WriteLine("Debug info: passive skill time exceeds for once."); | |||||
| } | |||||
| #endif | |||||
| } | |||||
| }.Start(); | |||||
| } | |||||
| ) | |||||
| { IsBackground = true }.Start(); | |||||
| } | |||||
| } | |||||
| public class Vampire : IPassiveSkill //被动就是吸血,普通子弹 | |||||
| { | |||||
| private readonly BulletType initBullet = BulletType.LineBullet; | |||||
| public BulletType InitBullet => initBullet; | |||||
| //以上参数以后再改 | |||||
| public void SkillEffect(Character player) | |||||
| { | |||||
| player.OriVampire = 0.5; | |||||
| player.Vampire = player.OriVampire; | |||||
| } | |||||
| } | |||||
| public class NoPassiveSkill : IPassiveSkill //没技能,这种情况不应该发生,先定义着以防意外 | |||||
| { | |||||
| private readonly BulletType initBullet = BulletType.OrdinaryBullet; | |||||
| public BulletType InitBullet => initBullet; | |||||
| //以上参数以后再改 | |||||
| public void SkillEffect(Character player) | |||||
| { | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -66,65 +66,28 @@ namespace GameEngine | |||||
| { | { | ||||
| if (!obj.IsAvailable && gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况 | if (!obj.IsAvailable && gameTimer.IsGaming) //不能动就直接return,后面都是能动的情况 | ||||
| return; | return; | ||||
| lock (obj.MoveLock) | |||||
| obj.IsMoving = true; | |||||
| double moveVecLength = 0.0; | |||||
| double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差 | |||||
| IGameObj? collisionObj = null; | |||||
| bool isDestroyed = false; | |||||
| new FrameRateTaskExecutor<int>( | |||||
| () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting, | |||||
| () => | |||||
| { | |||||
| moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||||
| bool flag; // 循环标志 | |||||
| do | |||||
| { | |||||
| flag = false; | |||||
| collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength)); | |||||
| if (collisionObj == null) | |||||
| break; | |||||
| lock (obj.MoveLock) | |||||
| obj.IsMoving = true; | |||||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||||
| double moveVecLength = 0.0; | |||||
| double deltaLen = moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); // 转向,并用deltaLen存储行走的误差 | |||||
| IGameObj? collisionObj = null; | |||||
| bool isDestroyed = false; | |||||
| new FrameRateTaskExecutor<int>( | |||||
| () => gameTimer.IsGaming && obj.CanMove && !obj.IsResetting, | |||||
| () => | |||||
| { | { | ||||
| case AfterCollision.ContinueCheck: | |||||
| flag = true; | |||||
| break; | |||||
| case AfterCollision.Destroyed: | |||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||||
| isDestroyed = true; | |||||
| return false; | |||||
| case AfterCollision.MoveMax: | |||||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||||
| moveVecLength = 0; | |||||
| break; | |||||
| } | |||||
| } while (flag); | |||||
| moveVecLength = obj.MoveSpeed / GameData.numOfStepPerSecond; | |||||
| deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); | |||||
| return true; | |||||
| }, | |||||
| GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond, | |||||
| () => | |||||
| { | |||||
| int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||||
| bool flag; | |||||
| do | |||||
| { | |||||
| flag = false; | |||||
| if (!isDestroyed) | |||||
| { | |||||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||||
| if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null) | |||||
| { | |||||
| obj.Move(new XY(direction, moveVecLength)); | |||||
| } | |||||
| else | |||||
| // 越界情况处理:如果越界,则与越界方块碰撞 | |||||
| bool flag; // 循环标志 | |||||
| do | |||||
| { | { | ||||
| flag = false; | |||||
| collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength)); | |||||
| if (collisionObj == null) | |||||
| break; | |||||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | ||||
| { | { | ||||
| case AfterCollision.ContinueCheck: | case AfterCollision.ContinueCheck: | ||||
| @@ -133,43 +96,81 @@ namespace GameEngine | |||||
| case AfterCollision.Destroyed: | case AfterCollision.Destroyed: | ||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | ||||
| isDestroyed = true; | isDestroyed = true; | ||||
| break; | |||||
| return false; | |||||
| case AfterCollision.MoveMax: | case AfterCollision.MoveMax: | ||||
| MoveMax(obj, new XY(direction, moveVecLength)); | MoveMax(obj, new XY(direction, moveVecLength)); | ||||
| moveVecLength = 0; | moveVecLength = 0; | ||||
| break; | break; | ||||
| } | } | ||||
| } while (flag); | |||||
| deltaLen += moveVecLength - Math.Sqrt(obj.Move(new XY(direction, moveVecLength))); | |||||
| return true; | |||||
| }, | |||||
| GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond, | |||||
| () => | |||||
| { | |||||
| int leftTime = moveTime % (GameData.numOfPosGridPerCell / GameData.numOfStepPerSecond); | |||||
| bool flag; | |||||
| do | |||||
| { | |||||
| flag = false; | |||||
| if (!isDestroyed) | |||||
| { | |||||
| moveVecLength = deltaLen + leftTime * obj.MoveSpeed / GameData.numOfPosGridPerCell; | |||||
| if ((collisionObj = collisionChecker.CheckCollision(obj, new XY(direction, moveVecLength))) == null) | |||||
| { | |||||
| obj.Move(new XY(direction, moveVecLength)); | |||||
| } | |||||
| else | |||||
| { | |||||
| switch (OnCollision(obj, collisionObj, new XY(direction, moveVecLength))) | |||||
| { | |||||
| case AfterCollision.ContinueCheck: | |||||
| flag = true; | |||||
| break; | |||||
| case AfterCollision.Destroyed: | |||||
| Debugger.Output(obj, " collide with " + collisionObj.ToString() + " and has been removed from the game."); | |||||
| isDestroyed = true; | |||||
| break; | |||||
| case AfterCollision.MoveMax: | |||||
| MoveMax(obj, new XY(direction, moveVecLength)); | |||||
| moveVecLength = 0; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } while (flag); | |||||
| if (leftTime > 0) | |||||
| { | |||||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||||
| } | } | ||||
| } | |||||
| } while (flag); | |||||
| if (leftTime > 0) | |||||
| lock (obj.MoveLock) | |||||
| obj.IsMoving = false; // 结束移动 | |||||
| EndMove(obj); | |||||
| return 0; | |||||
| }, | |||||
| maxTotalDuration: moveTime | |||||
| ) | |||||
| { | { | ||||
| Thread.Sleep(leftTime); // 多移动的在这里补回来 | |||||
| } | |||||
| lock (obj.MoveLock) | |||||
| obj.IsMoving = false; // 结束移动 | |||||
| EndMove(obj); | |||||
| return 0; | |||||
| }, | |||||
| maxTotalDuration: moveTime | |||||
| ) { | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| TimeExceedAction = b => | |||||
| { | |||||
| if (b) | |||||
| Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!"); | |||||
| AllowTimeExceed = true, | |||||
| MaxTolerantTimeExceedCount = ulong.MaxValue, | |||||
| TimeExceedAction = b => | |||||
| { | |||||
| if (b) | |||||
| Console.WriteLine("Fatal Error: The computer runs so slow that the object cannot finish moving during this time!!!!!!"); | |||||
| #if DEBUG | #if DEBUG | ||||
| else | |||||
| { | |||||
| Console.WriteLine("Debug info: Object moving time exceed for once."); | |||||
| } | |||||
| else | |||||
| { | |||||
| Console.WriteLine("Debug info: Object moving time exceed for once."); | |||||
| } | |||||
| #endif | #endif | ||||
| } | |||||
| }.Start(); | |||||
| } | } | ||||
| }.Start(); | |||||
| } | |||||
| ).Start(); | ).Start(); | ||||
| } | |||||
| } | } | ||||
| } | } | ||||
| } | |||||
| @@ -54,7 +54,8 @@ namespace Gaming | |||||
| // ActivateMine((Character)obj, (Mine)collisionObj); | // ActivateMine((Character)obj, (Mine)collisionObj); | ||||
| // return MoveEngine.AfterCollision.ContinueCheck; | // return MoveEngine.AfterCollision.ContinueCheck; | ||||
| //} | //} | ||||
| return MoveEngine.AfterCollision.MoveMax; }, | |||||
| return MoveEngine.AfterCollision.MoveMax; | |||||
| }, | |||||
| EndMove: obj => | EndMove: obj => | ||||
| { | { | ||||
| // Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | // Debugger.Output(obj, " end move at " + obj.Position.ToString() + " At time: " + Environment.TickCount64); | ||||
| @@ -4,7 +4,7 @@ namespace Preparation.GameData | |||||
| { | { | ||||
| public static class GameData | public static class GameData | ||||
| { | { | ||||
| #region 基本常数与常方法 | |||||
| #region 基本常数与常方法 | |||||
| public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | public const int numOfPosGridPerCell = 1000; // 每格的【坐标单位】数 | ||||
| public const int numOfStepPerSecond = 20; // 每秒行走的步数 | public const int numOfStepPerSecond = 20; // 每秒行走的步数 | ||||
| public const int lengthOfMap = 50000; // 地图长度 | public const int lengthOfMap = 50000; // 地图长度 | ||||
| @@ -35,8 +35,8 @@ namespace Preparation.GameData | |||||
| } | } | ||||
| public static int numOfBirthPoint = 5; | public static int numOfBirthPoint = 5; | ||||
| #endregion | |||||
| #region 角色相关 | |||||
| #endregion | |||||
| #region 角色相关 | |||||
| /// <summary> | /// <summary> | ||||
| /// 玩家相关 | /// 玩家相关 | ||||
| /// </summary> | /// </summary> | ||||
| @@ -71,9 +71,9 @@ namespace Preparation.GameData | |||||
| public const long GemProduceTime = 10000; | public const long GemProduceTime = 10000; | ||||
| public const long PropProduceTime = 10000; | public const long PropProduceTime = 10000; | ||||
| public const int PropDuration = 10000; | public const int PropDuration = 10000; | ||||
| #endregion | |||||
| #region 游戏帧相关 | |||||
| #endregion | |||||
| #region 游戏帧相关 | |||||
| public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | public const long checkInterval = 50; // 检查位置标志、补充子弹的帧时长 | ||||
| #endregion | |||||
| #endregion | |||||
| } | } | ||||
| } | } | ||||
| @@ -21,7 +21,7 @@ namespace Preparation.Utility | |||||
| { | { | ||||
| return "(" + x.ToString() + "," + y.ToString() + ")"; | return "(" + x.ToString() + "," + y.ToString() + ")"; | ||||
| } | } | ||||
| public static int operator*(XY v1, XY v2) | |||||
| public static int operator *(XY v1, XY v2) | |||||
| { | { | ||||
| return (v1.x * v2.x) + (v1.y * v2.y); | return (v1.x * v2.x) + (v1.y * v2.y); | ||||
| } | } | ||||
| @@ -5,23 +5,17 @@ VisualStudioVersion = 17.0.32014.148 | |||||
| MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}" | ||||
| EndProject | EndProject | ||||
| <<<<<<< HEAD | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameClass", "GameClass\GameClass.csproj", "{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameClass", "GameClass\GameClass.csproj", "{39D838F6-2B84-49E1-9CAF-1DFF22960B5D}" | ||||
| EndProject | EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{91448D70-61C3-499F-9B27-979E16DC9E64}" | |||||
| EndProject | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gaming", "Gaming\Gaming.csproj", "{BE9E3584-93C0-4E0F-8DAC-967CF4792709}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gaming", "Gaming\Gaming.csproj", "{BE9E3584-93C0-4E0F-8DAC-967CF4792709}" | ||||
| EndProject | EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MapGenerator", "MapGenerator\MapGenerator.csproj", "{9BC673F1-14B1-4203-944D-474BD0F64EDC}" | |||||
| EndProject | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preparation", "Preparation\Preparation.csproj", "{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Preparation", "Preparation\Preparation.csproj", "{E3DC4A37-8A83-40CC-AE47-68E70064C9DB}" | ||||
| ======= | |||||
| EndProject | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}" | ||||
| EndProject | EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\proto\Protos.csproj", "{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\proto\Protos.csproj", "{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}" | ||||
| >>>>>>> 9f4b5ac18b94330559cd560708f4100ae913260e | |||||
| EndProject | EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}" | |||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameEngine", "GameEngine\GameEngine.csproj", "{1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}" | |||||
| EndProject | EndProject | ||||
| Global | Global | ||||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| @@ -33,28 +27,18 @@ Global | |||||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU | {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU | {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.Build.0 = Release|Any CPU | {D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| <<<<<<< HEAD | |||||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU | {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU | {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.Build.0 = Release|Any CPU | {39D838F6-2B84-49E1-9CAF-1DFF22960B5D}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {91448D70-61C3-499F-9B27-979E16DC9E64}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.Build.0 = Debug|Any CPU | {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.ActiveCfg = Release|Any CPU | {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.Build.0 = Release|Any CPU | {BE9E3584-93C0-4E0F-8DAC-967CF4792709}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {9BC673F1-14B1-4203-944D-474BD0F64EDC}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU | {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU | {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.Build.0 = Release|Any CPU | {E3DC4A37-8A83-40CC-AE47-68E70064C9DB}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| ======= | |||||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU | {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU | {F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| @@ -63,14 +47,10 @@ Global | |||||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.Build.0 = Debug|Any CPU | {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.ActiveCfg = Release|Any CPU | {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.Build.0 = Release|Any CPU | {9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| <<<<<<< HEAD | |||||
| >>>>>>> 9f4b5ac18b94330559cd560708f4100ae913260e | |||||
| ======= | |||||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {C7A82045-5EE5-46E8-AD0C-04103EFEAF7E}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| >>>>>>> 3fa94addd0e0b62765b62c0788f217f7cf25b7c1 | |||||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
| {1D1D07F3-C332-4407-AC1B-EAD73F8BB3F3}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
| EndGlobalSection | EndGlobalSection | ||||
| GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
| HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||