public ComputerControlledTank(
            ISoundManager soundManager,
            World world, 
            Collection<IDoodad> doodads, 
            Team team, 
            Vector2 position, 
            float rotation,
            Random random, 
            DoodadFactory doodadFactory,
            IEnumerable<Waypoint> waypoints)
            : base(soundManager, world, doodads, team, position, rotation, doodadFactory)
        {
            this.world = world;
            this.random = random;
            this.states = new Dictionary<Type, ITankState>();
            this.states.Add(typeof(MovingState), new MovingState(world, this.Body, this, waypoints, random));
            this.states.Add(typeof(AttackingState), new AttackingState(world, this.Body, this));
            this.states.Add(typeof(TurningState), new TurningState(this.Body, this));
            this.currentState = this.states[typeof(MovingState)];
            this.currentState.StateChanged += this.OnStateChanged;
            this.currentState.NavigateTo();

            this.sensor = BodyFactory.CreateBody(world, this.Position);

            var shape = new CircleShape(6, 0);
            Fixture sensorFixture = this.sensor.CreateFixture(shape);
            sensorFixture.Friction = 1f;
            sensorFixture.IsSensor = true;
            sensorFixture.CollisionCategories = PhysicsConstants.SensorCategory;
            sensorFixture.CollidesWith = PhysicsConstants.PlayerCategory | PhysicsConstants.ObstacleCategory |
                                         PhysicsConstants.MissileCategory;
        }
        protected override void OnUpdate(GameTime gameTime)
        {
            this.sensor.SetTransform(this.Position, this.Rotation);

            if (!(this.currentState is AttackingState) &&
                this.closestTarget != null &&
                this.closestTarget.Item2 is PlayerControlledTank)
            {
                this.Target = (Tank)this.closestTarget.Item2;
                this.closestTarget = null;
                this.interruptedState = this.currentState;
                this.ChangeState(this.states[typeof(AttackingState)]);
                return;
            }

            if (this.currentState is AttackingState &&
                this.closestTarget != null &&
                !(this.closestTarget.Item2 is PlayerControlledTank))
            {
                this.Target = null;
                this.closestTarget = null;
                this.ChangeState(this.interruptedState);
                this.interruptedState = null;
            }

            this.elapsedTime += gameTime.ElapsedGameTime;

            bool isEnemyInRange = false;
            ContactEdge edge = this.sensor.ContactList;
            while (edge != null)
            {
                if (edge.Contact.IsTouching() &&
                    (edge.Contact.FixtureA.Body.UserData is PlayerControlledTank || edge.Contact.FixtureB.UserData is PlayerControlledTank))
                {
                    Fixture enemy = edge.Contact.FixtureA.Body.UserData is PlayerControlledTank
                                        ? edge.Contact.FixtureA
                                        : edge.Contact.FixtureB;

                    isEnemyInRange = true;
                    if (this.elapsedTime.TotalSeconds > 0.1)
                    {
                        this.elapsedTime = TimeSpan.Zero;
                        this.closestTarget = null;
                        this.TryToTargetEnemny(((Tank)enemy.Body.UserData));
                    }

                    break;
                }

                if (edge.Contact.FixtureA.Body.UserData is Missile ||
                    edge.Contact.FixtureB.Body.UserData is Missile)
                {
                    Missile missile = edge.Contact.FixtureA.Body.UserData is Missile
                                          ? edge.Contact.FixtureA.Body.UserData as Missile
                                          : edge.Contact.FixtureB.Body.UserData as Missile;

                    this.TestForDanger(missile);
                }

                edge = edge.Next;
            }

            if (!isEnemyInRange && this.currentState is AttackingState)
            {
                this.Target = null;
                this.closestTarget = null;
                this.ChangeState(this.interruptedState);
                this.interruptedState = null;
            }

            this.currentState.Update(gameTime);
        }
 private void ChangeState(ITankState nextState)
 {
     this.currentState.StateChanged -= this.OnStateChanged;
     this.currentState = nextState;
     this.currentState.StateChanged += this.OnStateChanged;
     this.currentState.NavigateTo();
 }
Exemple #4
0
 public void ChangeState(ITankState newState)
 {
     State.Exit(this);
     State = newState;
     State.Enter(this);
 }