Jypeli  5
The simple game programming library
FollowerBrain.cs
Siirry tämän tiedoston dokumentaatioon.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 
6 namespace Jypeli
7 {
12  {
13  double _logicDelay = 0;
14  double remainingDelay = 0;
15  Vector targetPosition;
16 
17  #region Properties
18 
22  public List<string> TagsToFollow { get; set; }
23 
27  public List<IGameObject> ObjectsToFollow { get; set; }
28 
33  public Comparison<IGameObject> FollowComparer { get; set; }
34 
38  public IGameObject CurrentTarget { get; protected set; }
39 
43  public DoubleMeter DistanceToTarget { get; protected set; }
44 
48  public double DistanceClose { get; set; }
49 
53  public double DistanceFar { get; set; }
54 
59  public Brain FarBrain { get; set; }
60 
64  public Brain CloseBrain { get; set; }
65 
69  public event Action TargetClose;
70 
77  public bool StopWhenTargetClose { get; set; }
78 
82  public double Delay
83  {
84  get { return _logicDelay; }
85  set
86  {
87  _logicDelay = value;
88  remainingDelay = ( Owner == null ) ? 0 : value;
89  }
90  }
91 
92  #endregion
93 
94  #region Comparers
95 
104  public Comparison<IGameObject> CreateDistanceComparer( double changeTargetDistance )
105  {
106  return delegate ( IGameObject obj1, IGameObject obj2 )
107  {
108  if ( Owner == null ) return 0;
109  if ( obj1 == null ) return 1;
110  if ( obj2 == null ) return -1;
111 
114  double diff = Math.Abs( d1 - d2 );
115 
116  if ( CurrentTarget == obj1 && diff < changeTargetDistance ) return -1;
117  if ( CurrentTarget == obj2 && diff < changeTargetDistance ) return 1;
118 
119  return d1.CompareTo( d2 );
120  };
121  }
122 
123  #endregion
124 
128  public FollowerBrain()
129  : this( null )
130  {
131  }
132 
137  public FollowerBrain( params object[] targets )
138  : base()
139  {
140  ObjectsToFollow = new List<IGameObject>();
141  TagsToFollow = new List<string>();
142  DistanceToTarget = new DoubleMeter( double.PositiveInfinity, 0, double.PositiveInfinity );
144  DistanceFar = double.PositiveInfinity;
145  DistanceClose = 100.0;
146  StopWhenTargetClose = false;
147  FarBrain = Brain.None;
148 
149  if (targets == null)
150  return;
151 
152  for (int i = 0; i < targets.Length; i++)
153  {
154  if (targets[i] is IGameObject)
155  ObjectsToFollow.Add((IGameObject)targets[i]);
156  else if (targets[i] is string)
157  TagsToFollow.Add((string)targets[i]);
158  else
159  throw new ArgumentException(string.Format("Target type not recognized: {0} ({1})", targets[i].ToString(), targets[i].GetType().Name));
160  }
161  }
162 
163  private void SelectTarget()
164  {
165  CurrentTarget = null;
166 
167  foreach ( var layer in Game.Instance.Layers )
168  {
169  foreach ( var obj in layer.Objects )
170  {
171  if (obj == Owner || obj.IsDestroyed)
172  continue;
173 
174  if ( !ObjectsToFollow.Contains( obj ) && !TagsToFollow.Contains( obj.Tag as string ) )
175  continue;
176 
177  if ( CurrentTarget == null || FollowComparer( CurrentTarget, obj ) > 0 )
178  CurrentTarget = obj;
179  }
180  }
181 
182  if ( Owner != null && CurrentTarget != null )
184  else
185  DistanceToTarget.Value = double.PositiveInfinity;
186  }
187 
188  private void SetTargetPosition( double dt )
189  {
190  targetPosition = CurrentTarget.AbsolutePosition;
191 
192  if ( Delay > 0 && DistanceToTarget.Value > float.Epsilon )
193  {
194  double maxlength = Math.Sqrt( Math.Pow( Game.Instance.Level.Width, 2 ) + Math.Pow( Game.Instance.Level.Height, 2 ) );
195  targetPosition += Vector.FromLengthAndAngle( maxlength, ( CurrentTarget.AbsolutePosition - Owner.AbsolutePosition ).Angle );
196  }
197 
199 
200  if ( physTarget != null )
201  {
202  // Take speed and acceleration into account
203  targetPosition += ( ( physTarget.Acceleration * dt ) + physTarget.Velocity ) * dt;
204  }
205  }
206 
211  protected override void Update( Time time )
212  {
213  double dt = Game.Time.SinceLastUpdate.TotalSeconds;
214  if ( dt <= 0 ) return;
215 
216  remainingDelay -= dt;
217  if ( remainingDelay <= 0 || CurrentTarget == null || !CurrentTarget.IsAddedToGame )
218  {
219  SelectTarget();
220  if ( CurrentTarget == null )
221  return;
222 
223  SetTargetPosition( dt );
224  remainingDelay = Delay;
225  }
226  else
227  {
229 
230  if ( TurnWhileMoving )
231  {
233  if ( !double.IsNaN( realDist.Magnitude ) && !double.IsInfinity( realDist.Magnitude ) )
234  Turn( realDist.Angle );
235  }
236  }
237 
238  double distance = DistanceToTarget.Value;
239  bool targetClose = Math.Abs( distance ) < DistanceClose;
240  bool targetFar = Math.Abs( distance ) > DistanceFar;
241  if ( targetClose && TargetClose != null ) TargetClose();
242 
243  if ( targetClose )
244  {
245  if ( StopWhenTargetClose )
246  {
247  if ( Owner is PhysicsObject )
248  ( (PhysicsObject)Owner ).Stop();
249 
250  return;
251  }
252 
253  if (CloseBrain != null)
254  {
255  CloseBrain.Owner = this.Owner;
256  CloseBrain.DoUpdate(time);
257  return;
258  }
259  }
260 
261  if ( targetFar )
262  {
263  FarBrain.Owner = this.Owner;
264  FarBrain.DoUpdate( time );
265  return;
266  }
267 
268  Vector d = targetPosition - Owner.AbsolutePosition;
269  if ( d.Magnitude > float.Epsilon )
270  Move( d / dt );
271  else if ( Owner is PhysicsObject )
272  ( (PhysicsObject)Owner ).Stop();
273 
274  base.Update( time );
275  }
276  }
277 }
static readonly Brain None
Tyhjät aivot, eivät sisällä mitään toiminnallisuutta.
Definition: Brain.cs:45
double Magnitude
Vektorin pituus.
Definition: Vector.cs:281
Angle Angle
Kulma radiaaneina.
Definition: Vector.cs:308
double Delay
Viive seuraamislogiikassa. Oletuksena nolla (seuraa reaaliajassa)
Comparison< IGameObject > FollowComparer
Metodi, joka vertailee kahta oliota keskenään. Kumpi olio tulee ensimmäiseksi, sitä seurataan...
Comparison< IGameObject > CreateDistanceComparer(double changeTargetDistance)
Luo FollowComparer-vertailijan, jolla aivot seuraavat aina lähintä oliota.
Yhteinen rajapinta kaikille fysiikkaolioille.
FollowerBrain(params object[] targets)
Luo aivot ja asettaa ne seuraamaan yhtä tai useampaa kohdetta.
Aivot, joiden tehtävänä on laittaa omistajansa seuraamaan jotakin kohdetta.
DoubleMeter DistanceToTarget
Etäisyys lähimpään kohteeseen.
Peliolio, joka noudattaa fysiikkamoottorin määräämiä fysiikan lakeja. Voidaan kuitenkin myös laittaa ...
Definition: Coefficients.cs:36
static Game Instance
Definition: Game.cs:149
TimeSpan SinceLastUpdate
Aika joka on kulunut viime päivityksestä.
Definition: Time.cs:24
Aivoluokka peliolioille. Voidaan käyttää tekoälyn ja tilannekohtaisten toimintamallien luomiseen peli...
Definition: Brain.cs:40
Mittari, joka mittaa double-tyyppisiä arvoja. Sidottavissa näyttöihin, kuten ValueDisplay ja BarGauge...
Definition: Meter.cs:515
Sisältää tiedon ajasta, joka on kulunut pelin alusta ja viime päivityksestä.
Definition: Time.cs:13
override void Update(Time time)
Kutsutaan, kun tilaa päivitetään. Suurin osa päätöksenteosta tapahtuu täällä.
bool TurnWhileMoving
Käännytäänkö siihen suuntaan mihin liikutaan.
Yleiset liikkumiseen tarkoitetut aivot.
SynchronousList< Layer > Layers
Kerrokset, joilla pelioliot viihtyvät.
Definition: Game.cs:95
Peliluokka reaaliaikaisille peleille.
Definition: DebugScreen.cs:10
Action TargetClose
Tapahtuma, joka suoritetaan, kun ollaan tarpeeksi lähellä seurattavaa.
bool StopWhenTargetClose
Pysähdytäänkö, kun ollaan lähellä kohdetta.
Brain FarBrain
Aivot, joita käytetään näiden sijasta kun ollaan kaukana kaikista kohteista, esim. RandomMoverBrain
double Height
Kentän korkeus.
Definition: Level.cs:126
Level Level
Aktiivinen kenttä.
Definition: Game.cs:299
FollowerBrain()
Luo aivot.
static double Distance(Vector p1, Vector p2)
Etäisyys kahden pisteen välillä.
Definition: Vector.cs:126
double Width
Kentän leveys.
Definition: Level.cs:117
Yhteinen rajapinta kaikille peliolioille.
Definition: IGameObject.cs:14
double DistanceFar
Etäisyys, jolloin ollaan kaukana kohteesta ja lopetetaan sen seuraaminen.
static Time Time
Peliaika. Sisältää tiedon siitä, kuinka kauan peliä on pelattu (Time.SinceStartOfGame) ja kuinka kaua...
Definition: Game.cs:309
List< string > TagsToFollow
Tagit, joita seurataan.
List< IGameObject > ObjectsToFollow
Oliot, joita seurataan.
2D-vektori.
Definition: Vector.cs:56
Vector AbsolutePosition
Definition: IGameObject.cs:46
Brain CloseBrain
Aivot, joita käytetään näiden sijasta kun ollaan lähellä kohdestta
IGameObject Owner
Aivojen haltija.
Definition: Brain.cs:69
double DistanceClose
Etäisyys, jolloin ollaan lähellä kohdetta.
void Move(Vector direction)
IGameObject CurrentTarget
Olio, jota parhaillaan seurataan.
void DoUpdate(Time time)
Definition: Brain.cs:86