source: 2013/30/MiskaK/MW2(My Warfare 2)/Paranneltu Jypeli/Brains/LabyrinthWandererBrain.cs @ 4742

Revision 4742, 6.9 KB checked in by anlakane, 8 years ago (diff)
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6namespace Jypeli
7{
8    /// <summary>
9    /// Aivot, jotka saavat omistajansa liikkumaan labyrinttimäisessä kentässä satunnaisesti edeten.
10    /// </summary>
11    public class LabyrinthWandererBrain : AbstractMoverBrain
12    {
13        private const double defaultSpeed = 100.0;
14        private double tileSize;
15        private string labyrinthWallTag;
16        private Vector direction;
17        private Vector destination;
18        private double timeSinceNewDestination;
19        private double directionChangeTimeout = 1.0;
20       
21        /// <summary>
22        /// Jos jäädään jumiin, kuinka pian arvotaan uusi suunta. Oletuksena 1 sekunti.
23        /// </summary>
24        public double DirectionChangeTimeout
25        {
26            get
27            {
28                return directionChangeTimeout;
29            }
30            set
31            {
32                directionChangeTimeout = value;
33            }
34        }
35
36        /// <summary>
37        /// Tagi, jolla varustetut oliot tulkitaan seiniksi. Muilla tageilla varustettuja olioita ei väistetä.
38        /// </summary>
39        public string LabyrinthWallTag
40        {
41            get
42            {
43                return labyrinthWallTag;
44            }
45            set
46            {
47                labyrinthWallTag = value;
48            }
49        }
50
51       
52        /// <summary>
53        /// Luo uudet aivot, jotka saavat omistajansa vaeltelemaan labyrintissä.
54        /// </summary>
55        /// <param name="tileSize">Kentän ruudun koko.</param>
56        public LabyrinthWandererBrain(double tileSize)
57            : base(defaultSpeed)
58        {
59            this.tileSize = tileSize;
60        }
61
62
63        /// <summary>
64        /// Luo uudet aivot, jotka saavat omistajansa vaeltelemaan labyrintissä.
65        /// </summary>
66        /// <param name="tileSize">Kentän ruudun koko.</param>
67        /// <param name="speed">Nopeus.</param>
68        public LabyrinthWandererBrain(double tileSize, double speed)
69            : base(speed)
70        {
71            this.tileSize = tileSize;
72        }
73
74        /// <summary>
75        /// Luo uudet aivot, jotka saavat omistajansa vaeltelemaan labyrintissä.
76        /// </summary>
77        /// <param name="tileSize">Kentän ruudun koko.</param>
78        /// <param name="speed">Nopeus.</param>
79        /// <param name="wallTag">Tagilla varustetut oliot tulkitaan seiniksi, muita ei väistetä.</param>
80        public LabyrinthWandererBrain(double tileSize, double speed, string wallTag)
81            :base(speed)
82        {
83            this.tileSize = tileSize;
84            labyrinthWallTag = wallTag;
85        }
86
87
88        protected override void OnAdd(IGameObject newOwner)
89        {
90            direction = RandomGen.NextDirection().GetVector() * tileSize;
91            destination = newOwner.Position + direction;
92            base.OnAdd(newOwner);
93        }
94
95       
96        protected override void OnAddToGame()
97        {
98            Game.DoNextUpdate(SetNextDirectionAndDestination);
99            base.OnAddToGame();
100        }
101
102        /// <summary>
103        /// Asetetaan uusi suunta. Hakee olioita edestä ja sivuilta ja arpoo tyhjistä kohdista uuden suunnan.
104        /// Jos eteen tai sivuille ei pääse, uusi suunta on taaksepäin.
105        /// </summary>
106        private void SetNextDirectionAndDestination()
107        {
108            PhysicsObject owner = this.Owner as PhysicsObject;
109
110            if (owner == null || owner.Game == null) return;
111
112            Game game = owner.Game;
113            List<Vector> directions = new List<Vector>{direction, 
114                                                        Vector.FromLengthAndAngle(tileSize, direction.Angle - Angle.RightAngle),
115                                                        Vector.FromLengthAndAngle(tileSize, direction.Angle + Angle.RightAngle)};
116           
117            GameObject tile;
118            double radius =  tileSize / 5;
119           
120            while (directions.Count > 0)
121            {
122                Vector directionCandidate = RandomGen.SelectOne<Vector>(directions);
123                directions.Remove(directionCandidate);
124
125                if (labyrinthWallTag != null)
126                {
127                    tile = game.GetObjectAt(owner.Position + directionCandidate, labyrinthWallTag,  radius);
128                }
129                else
130                {
131                    tile = game.GetObjectAt(owner.Position + directionCandidate, radius);
132                }
133
134                //PhysicsObjects only!
135                if (tile == null || tile as PhysicsObject == null || (owner.CollisionIgnoreGroup != 0 && (tile as PhysicsObject).CollisionIgnoreGroup == owner.CollisionIgnoreGroup))
136                {
137                    direction = directionCandidate.Normalize() * tileSize;
138                    //direction.X = Math.Round(direction.X);
139                    //direction.Y = Math.Round(direction.Y);
140                   
141                    destination = owner.Position + direction;
142                    return;
143                }
144               
145            }
146
147            direction = -direction.Normalize() * tileSize;
148            //direction.X = Math.Round(direction.X);
149            //direction.Y = Math.Round(direction.Y);
150           
151            destination = owner.Position + direction;
152        }
153
154       
155        /// <summary>
156        /// Liikuttaa omistajaa Move-metodilla.
157        /// Asetetaan uusi suunta jos ollaan saavutettu annettu määränpää, annettu määränpää on kauempana kuin yksi ruudun koko tai edellisestä suunnan asettamisesta on kulunut riittävän pitkä aika.
158        /// </summary>
159        /// <param name="time"></param>
160        protected override void Update(Time time)
161        {
162            base.Update(time);
163
164            if (Owner != null)
165            {
166                Vector distanceToTravel = destination - Owner.Position;
167                if (distanceToTravel.Magnitude < 0.1)
168                {
169                    SetNextDirectionAndDestination();
170                    timeSinceNewDestination = time.SinceStartOfGame.TotalSeconds;
171                }
172                else if (distanceToTravel.Magnitude > tileSize)
173                {
174                    SetNextDirectionAndDestination();
175                    timeSinceNewDestination = time.SinceStartOfGame.TotalSeconds;
176                }
177                else if (time.SinceStartOfGame.TotalSeconds - timeSinceNewDestination > DirectionChangeTimeout)
178                {
179                    //If stuck, let's change to opposite direction:
180                    direction = -direction.Normalize() * tileSize;
181                    SetNextDirectionAndDestination();
182                    timeSinceNewDestination = time.SinceStartOfGame.TotalSeconds;
183                }
184               
185                Move(direction.Angle);
186            }
187        }
188    }
189}
Note: See TracBrowser for help on using the repository browser.