コード例 #1
0
        public bool UpdateNPC(NPC npc, Player player, List<Obstacle> visibleObstacles, GameTime gameTime)
        {
            if (npc.CanSeePlayer(player, visibleObstacles)) return true;
            switch (npc.tag)
            {
                case NPCType.PoliceA:
                    {
                        npc.MoveForward(gameTime, 1.0f);
                        if(collisionController.IllegalMove(npc)) npc.MoveBackward(gameTime, 1.0f);
                        npc.RotateRight(gameTime, 1.0f);
                    }
                    break;
                case NPCType.PoliceB:
                    npc.stateTime += gameTime.ElapsedGameTime.Milliseconds;

                    double angleToPlayer = Math.Atan2(-1*((double)(player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2))),
                                ((double)(player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))));

                    double facingAngle = Math.Atan2(-1*npc.vision.viewDirection.Y, npc.vision.viewDirection.X);

                    double turnToAngle = facingAngle - angleToPlayer;

                    while (turnToAngle < -1 * MathHelper.Pi) turnToAngle += MathHelper.TwoPi;
                    while (turnToAngle > MathHelper.Pi) turnToAngle -= MathHelper.TwoPi;

                    switch (npc.state)
                    {
                        case NPCState.PatrolRight:
                            npc.MoveForward(gameTime, 1.0f);
                            if (collisionController.IllegalMove(npc))
                            {
                                npc.MoveBackward(gameTime, 1.0f);
                                npc.state = NPCState.PatrolRightBackwards;
                                npc.stateTime = 0;
                            }
                            if (Math.Abs(turnToAngle) < npc.vision.viewAngle && visibleObstacles.Count == 0 && player.isVisible && npc.vision.maxViewDistance * 1.5 >
                                Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Chase;
                                npc.stateTime = 0;
                            }
                            else if (player.isVisible && npc.vision.maxViewDistance / 2.5 > Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Investigate;
                                npc.stateTime = 0;
                            }
                            else if (npc.stateTime > 3000)
                            {
                                npc.state = NPCState.PatrolLeft;
                                npc.stateTime = 0;
                            }
                            else npc.RotateRight(gameTime, 1.0f);

                            break;

                        case NPCState.PatrolLeft:
                            npc.MoveForward(gameTime, 1.0f);
                            if (collisionController.IllegalMove(npc))
                            {
                                npc.MoveBackward(gameTime, 1.0f);
                                npc.state = NPCState.PatrolLeftBackwards;
                                npc.stateTime = 0;
                            }
                            if (Math.Abs(turnToAngle) < npc.vision.viewAngle && visibleObstacles.Count == 0 && player.isVisible && npc.vision.maxViewDistance * 1.5 >
                                Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Chase;
                                npc.stateTime = 0;
                            }
                            else if (player.isVisible && npc.vision.maxViewDistance / 2.5 > Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Investigate;
                                npc.stateTime = 0;
                            }
                            else if (npc.stateTime > 3000)
                            {
                                npc.state = NPCState.PatrolRight;
                                npc.stateTime = 0;
                            }
                            else npc.RotateLeft(gameTime, 1.0f);

                            break;

                        case NPCState.PatrolLeftBackwards:
                            npc.MoveBackward(gameTime, 1.0f);
                            if (collisionController.IllegalMove(npc))
                            {
                                npc.MoveForward(gameTime, 1.0f);
                                npc.state = NPCState.PatrolLeft;
                                npc.stateTime = 0;
                            }
                            if (Math.Abs(turnToAngle) < npc.vision.viewAngle && visibleObstacles.Count == 0 && player.isVisible && npc.vision.maxViewDistance * 1.5 >
                                Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Chase;
                                npc.stateTime = 0;
                            }
                            else if (player.isVisible && npc.vision.maxViewDistance / 2.5 > Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Investigate;
                                npc.stateTime = 0;
                            }
                            else if (npc.stateTime > 250)
                            {
                                npc.state = NPCState.PatrolLeft;
                                npc.stateTime = 0;
                            }
                            else npc.RotateLeft(gameTime, 2.5f);

                            break;

                        case NPCState.PatrolRightBackwards:
                            npc.MoveBackward(gameTime, 1.0f);
                            if (collisionController.IllegalMove(npc))
                            {
                                npc.MoveForward(gameTime, 1.0f);
                                npc.state = NPCState.PatrolRight;
                                npc.stateTime = 0;
                            }
                            if (Math.Abs(turnToAngle) < npc.vision.viewAngle && visibleObstacles.Count == 0 && player.isVisible && npc.vision.maxViewDistance * 1.5 >
                                Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Chase;
                                npc.stateTime = 0;
                            }
                            else if (player.isVisible && npc.vision.maxViewDistance / 2.5 > Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.Investigate;
                                npc.stateTime = 0;
                            }
                            else if (npc.stateTime > 250)
                            {
                                npc.state = NPCState.PatrolRight;
                                npc.stateTime = 0;
                            }
                            else npc.RotateRight(gameTime, 2.5f);

                            break;

                        case NPCState.Chase:
                            if (!player.isVisible || npc.vision.maxViewDistance*2 < Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.PatrolLeft; //Randomize
                                npc.stateTime = 0;
                                break;
                            }
                            if (Math.Abs(turnToAngle) > .05)
                            {
                                if (turnToAngle > 0) npc.RotateLeft(gameTime, 2.0f);
                                else if (turnToAngle < 0) npc.RotateRight(gameTime, 2.0f);
                            }

                            npc.MoveForward(gameTime, 2.0f);
                            if (collisionController.IllegalMove(npc))
                            {
                                npc.MoveBackward(gameTime, 2.0f);
                                npc.MoveRight(gameTime, 2.0f);
                                npc.state = NPCState.PatrolLeft; //Randomize
                                npc.stateTime = 0;
                                //if (turnToAngle > 0)
                                //{
                                //    npc.MoveUp(gameTime, 2.0f);
                                //    if (collisionController.IllegalMove(npc))
                                //    {
                                //        npc.MoveDown(gameTime, 2.0f);
                                //        if (Math.Abs(turnToAngle) < MathHelper.PiOver2)
                                //        {
                                //            npc.MoveRight(gameTime, 2.0f);
                                //            if (collisionController.IllegalMove(npc))
                                //            {
                                //                npc.MoveLeft(gameTime, 2.0f);
                                //                npc.state = NPCState.PatrolLeft; //Randomize
                                //                npc.stateTime = 0;
                                //            }
                                //        }
                                //    }
                                //}
                                //else if (turnToAngle < 0)
                                //{
                                //    npc.MoveDown(gameTime, 2.0f);
                                //    if (collisionController.IllegalMove(npc))
                                //    {
                                //        npc.MoveUp(gameTime, 2.0f);
                                //        if (Math.Abs(turnToAngle) < MathHelper.PiOver2)
                                //        {
                                //            npc.MoveLeft(gameTime, 2.0f);
                                //            if (collisionController.IllegalMove(npc))
                                //            {
                                //                npc.MoveRight(gameTime, 2.0f);
                                //                npc.state = NPCState.PatrolLeft; //Randomize
                                //                npc.stateTime = 0;
                                //            }
                                //        }
                                //    }
                                //}
                            }

                            break;
                        case NPCState.Investigate:
                            if (!player.isVisible || npc.vision.maxViewDistance / 2 < Math.Abs(((player.worldRectangle.Y + (player.worldRectangle.Height / 2)) - (npc.worldRectangle.Y + (npc.worldRectangle.Height / 2)))) +
                                Math.Abs((player.worldRectangle.X + (player.worldRectangle.Width / 2)) - (npc.worldRectangle.X + (npc.worldRectangle.Width / 2))))
                            {
                                npc.state = NPCState.PatrolLeft; //Randomize
                                npc.stateTime = 0;
                            }
                            else if (Math.Abs(turnToAngle) < npc.vision.viewAngle / 2 && visibleObstacles.Count == 0 && player.isVisible)
                            {
                                npc.state = NPCState.Chase;
                                npc.stateTime = 0;
                            }
                            else if (turnToAngle > 0) npc.RotateLeft(gameTime, 3.0f);
                            else if (turnToAngle < 0) npc.RotateRight(gameTime, 3.0f);
                            break;
                    }

                    break;
            }
            return false;
        }