예제 #1
0
        public void Validate()
        {
            string message;

            var negativeXPosition = new XYPosition(x: -1, y: 10);
            var validation        = new BoardConfigurationValidation(width: 100, height: 100, position: negativeXPosition, orientation: Orientation.Horizontal, size: 2);

            Assert.False(validation.Validate(out message));
            Assert.Equal("X position '-1' cannot be negative", message);

            var outOfBoundXPosition = new XYPosition(x: 100, y: 10);

            validation = new BoardConfigurationValidation(width: 100, height: 100, position: outOfBoundXPosition, orientation: Orientation.Horizontal, size: 2);
            Assert.False(validation.Validate(out message));
            Assert.Contains("X position '100' is outside the board width bound '100'", message); // 0-start-index

            var negativeYPosition = new XYPosition(x: 10, y: -1);

            validation = new BoardConfigurationValidation(width: 100, height: 100, position: negativeYPosition, orientation: Orientation.Horizontal, size: 2);
            Assert.False(validation.Validate(out message));
            Assert.Equal("Y position '-1' cannot be negative", message);

            var outOfBoundYPosition = new XYPosition(x: 10, y: 100);

            validation = new BoardConfigurationValidation(width: 100, height: 100, position: outOfBoundYPosition, orientation: Orientation.Horizontal, size: 2);
            Assert.False(validation.Validate(out message));
            Assert.Equal("Y position '100' is outside the board height bound '100'", message); // 0-start-index
        }
예제 #2
0
        public void TestSetAndGet()
        {
            var position = new XYPosition(x: 10, y: 20);

            Assert.Equal(10, position.X);
            Assert.Equal(20, position.Y);
        }
예제 #3
0
            public const int shieldTimeAtBirth = 5 * 1000;                  //出生时的盾牌时间

            public static XYPosition CellToGrid(int x, int y)               //求格子的中心坐标
            {
                XYPosition ret = new XYPosition(x * numOfGridPerCell + numOfGridPerCell / 2,
                                                y * numOfGridPerCell + numOfGridPerCell / 2);

                return(ret);
            }
예제 #4
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public void SetLaid(XYPosition pos)
 {
     if (laid)
     {
         return;
     }
     laid     = true;
     Position = pos;
     shape    = ShapeType.Circle;
 }
예제 #5
0
        /// <summary>
        /// 在无碰撞的前提下行走最远的距离
        /// </summary>
        /// <param name="obj">移动物体,默认obj.Rigid为true</param>
        /// <param name="moveVec">移动的位移向量</param>
        private void MoveMax(GameObject obj, Vector moveVec)
        {
            /*由于四周是墙,所以人物永远不可能与越界方块碰撞*/

            XYPosition nextPos = obj.Position + Vector.Vector2XY(moveVec);

            uint maxLen = collisionChecker.FindMax(obj, nextPos, moveVec);

            maxLen = (uint)Math.Min(maxLen, (obj.MoveSpeed / Map.Constant.numOfStepPerSecond));
            obj.Move(new Vector(moveVec.angle, maxLen));
        }
예제 #6
0
        /// <summary>
        /// 碰撞检测,如果这样行走是否会与之碰撞,返回与之碰撞的物体
        /// </summary>
        /// <param name="obj">移动的物体</param>
        /// <param name="moveVec">移动的位移向量</param>
        /// <returns>和它碰撞的物体</returns>
        public GameObject?CheckCollision(GameObject obj, Vector moveVec)
        {
            XYPosition nextPos = obj.Position + Vector.Vector2XY(moveVec);

            if (!obj.IsRigid)
            {
                if (gameMap.OutOfBound(obj))
                {
                    return(new OutOfBoundBlock(nextPos));
                }
                return(null);
            }

            //在某列表中检查碰撞
            Func <ArrayList, ReaderWriterLockSlim, GameObject> CheckCollisionInList =
                (ArrayList lst, ReaderWriterLockSlim listLock) =>
            {
                GameObject?collisionObj = null;
                listLock.EnterReadLock();
                try
                {
                    foreach (GameObject listObj in lst)
                    {
                        if (WillCollide(obj, listObj, nextPos))
                        {
                            collisionObj = listObj;
                            break;
                        }
                    }
                }
                finally { listLock.ExitReadLock(); }
                return(collisionObj);
            };

            GameObject collisionObj = null;

            foreach (var list in lists)
            {
                if ((collisionObj = CheckCollisionInList(list.Item1, list.Item2)) != null)
                {
                    return(collisionObj);
                }
            }

            //如果越界,则与越界方块碰撞
            if (gameMap.OutOfBound(obj))
            {
                return(new OutOfBoundBlock(nextPos));
            }

            return(null);
        }
예제 #7
0
        public void TestCompare()
        {
            var equalPosition     = new XYPosition(x: 10, y: 20);
            var notEqualXPosition = new XYPosition(x: 0, y: 20);
            var notEqualYPosition = new XYPosition(x: 10, y: 0);
            var notEqualPosition  = new XYPosition(x: 0, y: 0);

            var position = new XYPosition(x: 10, y: 20);

            Assert.True(position.Equals(equalPosition));
            Assert.False(position.Equals(notEqualXPosition));
            Assert.False(position.Equals(notEqualYPosition));
            Assert.False(position.Equals(notEqualPosition));
        }
        public void TestBuild_Vertical()
        {
            var position = new XYPosition(x: 50, y: 50);

            var verticalBattleship        = BattleshipBuilderProvider.GetBuilder(Orientation.Vertical).Build(position, 3);
            var verticalBattleshipForTest = new XYBattleshipForTest(verticalBattleship);
            var xyOccupiedPositions       = verticalBattleshipForTest
                                            .OccupiedPositionsForTest
                                            .Select(occupiedPosition => occupiedPosition.Position)
                                            .Cast <XYPosition>()
                                            .Select(occupiedPosition => $"{occupiedPosition.X},{occupiedPosition.Y}");

            Assert.Equal(new[] { "50,50", "50,51", "50,52" }, xyOccupiedPositions.ToArray());
        }
예제 #9
0
        /// <summary>
        /// 检查obj下一步位于nextPos时是否会与listObj碰撞
        /// </summary>
        /// <param name="obj">主动碰撞物,默认obj.Rigid为true</param>
        /// <param name="listObj">被动碰撞物</param>
        /// <param name="nextPos">obj下一步想走的位置</param>
        /// <returns>如果会碰撞,返回true</returns>
        public bool WillCollide(GameObject obj, GameObject listObj, XYPosition nextPos)
        {
            if (!listObj.IsRigid || listObj.ID == obj.ID)
            {
                return(false);                                                      //不检查自己和非刚体
            }
            if (IgnoreCollision(obj, listObj))
            {
                return(false);                                                      // 可以忽略碰撞
            }
            int deltaX = Math.Abs(nextPos.x - listObj.Position.x), deltaY = Math.Abs(nextPos.y - listObj.Position.y);

            //默认obj是圆形的,因为能移动的物体目前只有圆形;且会移动的道具尚未被捡起,其形状没有意义,可默认为圆形

            switch (listObj.Shape)
            {
            case GameObject.ShapeType.Circle:                           //圆与圆碰撞
            {
                return((long)deltaX * deltaX + (long)deltaY * deltaY < ((long)obj.Radius + listObj.Radius) * ((long)obj.Radius + listObj.Radius));
            }

            case GameObject.ShapeType.Sqare:                            //圆与正方形碰撞
            {
                if (deltaX >= listObj.Radius + obj.Radius || deltaY >= listObj.Radius + obj.Radius)
                {
                    return(false);
                }
                if (deltaX < listObj.Radius || deltaY < listObj.Radius)
                {
                    return(true);
                }
                return((long)(deltaX - listObj.Radius) * (deltaX - listObj.Radius) + (long)(deltaY - listObj.Radius) * (deltaY - listObj.Radius) < (long)obj.Radius * (long)obj.Radius);
            }
            }
            return(false);
        }
예제 #10
0
파일: Wall.cs 프로젝트: mrasamu/THUAI4-1
 public Wall(XYPosition initPos, int radius) : base(initPos, radius, true, 0, ObjType.Wall, ShapeType.Sqare)
 {
 }
예제 #11
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Amplifier(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #12
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Bike(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #13
0
 public static int GridToCellY(XYPosition pos)                  //求坐标所在的格子的y坐标
 {
     return(pos.y / numOfGridPerCell);
 }
예제 #14
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Divider(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #15
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Attenuator(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #16
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Spear(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #17
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Totem(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #18
0
            private void ProduceOneProp()
            {
                Random     r          = new Random((int)Environment.TickCount64);
                XYPosition newPropPos = new XYPosition();

                while (true)
                {
                    newPropPos.x = r.Next(0, gameMap.Rows * Map.Constant.numOfGridPerCell);
                    newPropPos.y = r.Next(0, gameMap.Cols * Map.Constant.numOfGridPerCell);
                    int  cellX = Map.Constant.GridToCellX(newPropPos), cellY = Map.Constant.GridToCellY(newPropPos);
                    bool canLayProp = true;
                    gameMap.ObjListLock.EnterReadLock();
                    try
                    {
                        foreach (GameObject obj in gameMap.ObjList)
                        {
                            if (cellX == Map.Constant.GridToCellX(obj.Position) && cellY == Map.Constant.GridToCellY(obj.Position) && (obj is Wall || obj is BirthPoint))
                            {
                                canLayProp = false;
                                break;
                            }
                        }
                    }
                    finally { gameMap.ObjListLock.ExitReadLock(); }
                    if (canLayProp)
                    {
                        newPropPos = Map.Constant.CellToGrid(cellX, cellY);
                        break;
                    }
                }

                PropType propType = (PropType)r.Next(Prop.MinPropTypeNum, Prop.MaxPropTypeNum + 1);

                Prop?newProp = null;

                switch (propType)
                {
                case PropType.Bike: newProp = new Bike(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Amplifier: newProp = new Amplifier(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.JinKeLa: newProp = new JinKeLa(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Rice: newProp = new Rice(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Shield: newProp = new Shield(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Totem: newProp = new Totem(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Spear: newProp = new Spear(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Dirt: newProp = new Dirt(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Attenuator: newProp = new Attenuator(newPropPos, Map.Constant.unpickedPropRadius); break;

                case PropType.Divider: newProp = new Divider(newPropPos, Map.Constant.unpickedPropRadius); break;
                }
                if (newProp != null)
                {
                    unpickedPropListLock.EnterWriteLock();
                    try { unpickedPropList.AddLast(newProp); }
                    finally { unpickedPropListLock.ExitWriteLock(); }
                    newProp.CanMove = true;
                }
            }
예제 #19
0
 public BirthPoint(XYPosition initPos, int radius) : base(initPos, radius, true, 0, ObjType.BirthPoint, ShapeType.Circle)
 {
 }
예제 #20
0
 public OutOfBoundBlock(XYPosition initPos) : base(initPos, int.MaxValue, true, 0, ObjType.OutOfBoundBlock, ShapeType.Sqare)
 {
 }
예제 #21
0
        public long AddPlayer(PlayerInitInfo playerInitInfo)
        {
            if (!Team.teamExists(playerInitInfo.teamID) ||
                !MapInfo.ValidBirthPointIdx(playerInitInfo.birthPointIdx) ||
                gameMap.BirthPointList[playerInitInfo.birthPointIdx].Parent != null)
            {
                return(GameObject.invalidID);
            }

            XYPosition pos       = gameMap.BirthPointList[playerInitInfo.birthPointIdx].Position;
            Character  newPlayer = new Character(pos, Map.Constant.playerRadius, playerInitInfo.jobType, Map.Constant.basicPlayerMoveSpeed);

            gameMap.BirthPointList[playerInitInfo.birthPointIdx].Parent = newPlayer;
            gameMap.PlayerListLock.EnterWriteLock(); try { gameMap.PlayerList.Add(newPlayer); } finally { gameMap.PlayerListLock.ExitWriteLock(); }
            ((Team)teamList[(int)playerInitInfo.teamID]).AddPlayer(newPlayer);
            newPlayer.TeamID = playerInitInfo.teamID;

            //设置出生点的颜色

            int cellX = Map.Constant.GridToCellX(pos), cellY = Map.Constant.GridToCellY(pos);

            gameMap.SetCellColor(cellX, cellY, Map.TeamToColor(playerInitInfo.teamID));

            //开启装弹线程

            new Thread
            (
                () =>
            {
                while (!gameMap.Timer.IsGaming)
                {
                    Thread.Sleep(newPlayer.CD);
                }
                while (gameMap.Timer.IsGaming)
                {
                    var beginTime = Environment.TickCount64;

                    var cellX = Map.Constant.GridToCellX(newPlayer.Position);
                    var cellY = Map.Constant.GridToCellY(newPlayer.Position);
                    if (gameMap.GetCellColor(cellX, cellY) == Map.TeamToColor(newPlayer.TeamID))
                    {
                        newPlayer.AddBulletNum();
                    }

                    var endTime   = Environment.TickCount64;
                    var deltaTime = endTime - beginTime;
                    if (deltaTime < newPlayer.CD)
                    {
                        Thread.Sleep(newPlayer.CD - (int)deltaTime);
                    }
                    else
                    {
                        Console.WriteLine("The computer runs so slow that the player cannot finish adding bullet during this time!!!!!!");
                    }
                }
            }
            )
            {
                IsBackground = true
            }.Start();
            return(newPlayer.ID);
        }
예제 #22
0
        static void Main(string[] args)
        {
            Game game = new Game(MapInfo.defaultMap, 1);
            long tmpID;

            long[] player2ID = new long[2];

            XYPosition player1Pos = Map.Constant.CellToGrid(1, 1);
            XYPosition player2Pos = Map.Constant.CellToGrid(2, 2);

            if ((tmpID = game.AddPlayer(new Game.PlayerInitInfo(0u, (JobType)0, 0))) == GameObject.invalidID)
            {
                Console.WriteLine("Add player failed!");
            }
            else
            {
                player2ID[0] = (tmpID);
            }

            if (((tmpID) = game.AddPlayer(new Game.PlayerInitInfo(1u, (JobType)0, 0))) == GameObject.invalidID)
            {
                Console.WriteLine("Add player failed!");
            }
            else
            {
                player2ID[1] = tmpID;
            }

            new Thread
            (
                () =>
            {
                game.StartGame(5 * 60 * 1000);
            }
            )
            {
                IsBackground = true
            }.Start();

            new Thread
            (
                () =>
            {
                double[] direct = new double[16];
                int[] time      = new int[16];

                const int WKey = 0x1;
                const int AKey = 0x2;
                const int SKey = 0x4;
                const int DKey = 0x8;

                for (int i = 1; i < time.Length; ++i)
                {
                    time[i] = 500;
                }

                direct[WKey]        = Math.PI / 2;
                direct[AKey]        = Math.PI;
                direct[SKey]        = -Math.PI / 2;
                direct[DKey]        = 0.0;
                direct[WKey | AKey] = Math.PI / 4 * 3;
                direct[WKey | DKey] = Math.PI / 4;
                direct[SKey | AKey] = Math.PI / 4 * 5;
                direct[SKey | DKey] = Math.PI / 4 * 7;

                while (true)
                {
                    Thread.Sleep(500);
                    int key     = 0;
                    bool WPress = Win32Api.GetKeyState((Int32)ConsoleKey.UpArrow) < 0,
                    APress      = Win32Api.GetKeyState((Int32)ConsoleKey.LeftArrow) < 0,
                    SPress      = Win32Api.GetKeyState((Int32)ConsoleKey.DownArrow) < 0,
                    DPress      = Win32Api.GetKeyState((Int32)ConsoleKey.RightArrow) < 0;
                    if (WPress)
                    {
                        key |= WKey;
                    }
                    if (APress)
                    {
                        key |= AKey;
                    }
                    if (SPress)
                    {
                        key |= SKey;
                    }
                    if (DPress)
                    {
                        key |= DKey;
                    }
                    if (key != 0)
                    {
                        game.MovePlayer((long)player2ID[1], time[key], direct[key]);
                    }
                }
            }
            )
            {
                IsBackground = true
            }.Start();

            double[] direct = new double[16];
            int[]    time   = new int[16];

            const int WKey = 0x1;
            const int AKey = 0x2;
            const int SKey = 0x4;
            const int DKey = 0x8;

            for (int i = 1; i < time.Length; ++i)
            {
                time[i] = 500;
            }

            direct[WKey]        = Math.PI / 2;
            direct[AKey]        = Math.PI;
            direct[SKey]        = -Math.PI / 2;
            direct[DKey]        = 0.0;
            direct[WKey | AKey] = Math.PI / 4 * 3;
            direct[WKey | DKey] = Math.PI / 4;
            direct[SKey | AKey] = Math.PI / 4 * 5;
            direct[SKey | DKey] = Math.PI / 4 * 7;

            while (true)
            {
                Thread.Sleep(500);
                int  key    = 0;
                bool WPress = Win32Api.GetKeyState((Int32)ConsoleKey.W) < 0,
                     APress = Win32Api.GetKeyState((Int32)ConsoleKey.A) < 0,
                     SPress = Win32Api.GetKeyState((Int32)ConsoleKey.S) < 0,
                     DPress = Win32Api.GetKeyState((Int32)ConsoleKey.D) < 0;
                if (WPress)
                {
                    key |= WKey;
                }
                if (APress)
                {
                    key |= AKey;
                }
                if (SPress)
                {
                    key |= SKey;
                }
                if (DPress)
                {
                    key |= DKey;
                }
                if (key != 0)
                {
                    game.MovePlayer((long)player2ID[0], time[key], direct[key]);
                }

                if (Win32Api.GetKeyState((Int32)ConsoleKey.J) < 0)
                {
                    game.Attack((long)player2ID[0], 10000000, Math.PI);
                }
            }
        }
예제 #23
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public JinKeLa(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #24
0
파일: Prop.cs 프로젝트: godfather991/THUAI4
 public Shield(XYPosition initPos, int radius) : base(initPos, radius)
 {
 }
예제 #25
0
        /// <summary>
        /// 寻找最大可能移动距离
        /// </summary>
        /// <param name="obj">移动物体,默认obj.Rigid为true</param>
        /// <param name="nextPos">下一步要到达的位置</param>
        /// <param name="moveVec">移动的位移向量,默认与nextPos协调</param>
        /// <returns>最大可能的移动距离</returns>
        public uint FindMax(GameObject obj, XYPosition nextPos, Vector moveVec)
        {
            uint maxLen = uint.MaxValue;
            uint tmpMax;

            foreach (var listWithLock in lists)
            {
                var lst      = listWithLock.Item1;
                var listLock = listWithLock.Item2;
                listLock.EnterReadLock();
                try
                {
                    foreach (GameObject listObj in lst)
                    {
                        //如果再走一步发生碰撞
                        if (WillCollide(obj, listObj, nextPos))
                        {
                            switch (listObj.Shape)                              //默认obj为圆形
                            {
                            case GameObject.ShapeType.Circle:
                            {
                                //计算两者之间的距离
                                int    orgDeltaX = listObj.Position.x - obj.Position.x;
                                int    orgDeltaY = listObj.Position.y - obj.Position.y;
                                double mod       = Math.Sqrt((long)orgDeltaX * orgDeltaX + (long)orgDeltaY * orgDeltaY);

                                if (mod == 0.0)                                                     //如果两者重合
                                {
                                    tmpMax = 0;
                                }
                                else
                                {
                                    Vector2 relativePosUnitVector = new Vector2(orgDeltaX / mod, orgDeltaY / mod);                                                      //相对位置的单位向量
                                    Vector2 moveUnitVector        = new Vector2(Math.Cos(moveVec.angle), Math.Sin(moveVec.angle));                                      //运动方向的单位向量
                                    if (relativePosUnitVector * moveUnitVector <= 0)
                                    {
                                        continue;                                                                                                       //如果它们的内积小于零,即反向,那么不会发生碰撞
                                    }
                                }

                                double tmp = mod - obj.Radius - listObj.Radius;
                                if (tmp <= 0)                                                           //如果它们已经贴合了,那么不能再走了
                                {
                                    tmpMax = 0;
                                }
                                else
                                {
                                    //计算最多能走的距离
                                    tmp = tmp / Math.Cos(Math.Atan2(orgDeltaY, orgDeltaX) - moveVec.angle);
                                    if (tmp < 0 || tmp > uint.MaxValue || tmp == double.NaN)
                                    {
                                        tmpMax = uint.MaxValue;
                                    }
                                    else
                                    {
                                        tmpMax = (uint)tmp;
                                    }
                                }
                                break;
                            }

                            case GameObject.ShapeType.Sqare:
                            {
                                //如果当前已经贴合,那么不能再行走了
                                if (WillCollide(obj, listObj, obj.Position))
                                {
                                    tmpMax = 0;
                                }
                                else
                                {
                                    //二分查找最大可能移动距离
                                    int left = 0, right = (int)moveVec.length;
                                    while (left < right - 1)
                                    {
                                        int mid = (right - left) / 2 + left;
                                        if (WillCollide(obj, listObj, obj.Position + new XYPosition((int)(mid * Math.Cos(moveVec.angle)), (int)(mid * Math.Sin(moveVec.angle)))))
                                        {
                                            right = mid;
                                        }
                                        else
                                        {
                                            left = mid;
                                        }
                                    }
                                    tmpMax = (uint)left;
                                }
                                break;
                            }

                            default:
                                tmpMax = int.MaxValue;
                                break;
                            }

                            if (tmpMax < maxLen)
                            {
                                maxLen = tmpMax;
                            }
                        }
                    }
                }
                finally { listLock.ExitReadLock(); }
            }
            return(maxLen);
        }