Jypeli  5
The simple game programming library
PhysicsGameBase.cs
Siirry tämän tiedoston dokumentaatioon.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using Physics2DDotNet;
6 using Physics2DDotNet.Joints;
7 
8 namespace Jypeli
9 {
13  public abstract class PhysicsGameBase : Game
14  {
15  protected struct CollisionRecord
16  {
19  public object targetTag;
20  public Delegate handler;
21 
22  public CollisionRecord( IPhysicsObject obj, IPhysicsObject target, object targetTag, Delegate handler )
23  {
24  this.obj = obj;
25  this.target = target;
26  this.targetTag = targetTag;
27  this.handler = handler;
28  }
29  }
30 
31  protected PhysicsEngine phsEngine;
32  private SynchronousList<Joint> Joints = new SynchronousList<Joint>();
33  protected Dictionary<CollisionRecord, CollisionHandler<IPhysicsObject, IPhysicsObject>> collisionHandlers =
34  new Dictionary<CollisionRecord, CollisionHandler<IPhysicsObject, IPhysicsObject>>();
35  protected Dictionary<CollisionRecord, CollisionHandler<IPhysicsObject, IPhysicsObject>> protectedCollisionHandlers =
36  new Dictionary<CollisionRecord, CollisionHandler<IPhysicsObject, IPhysicsObject>>();
37 
41  public bool PhysicsEnabled { get; set; }
42 
47  public PhysicsGameBase( int device )
48  : base( device )
49  {
50  PhysicsEnabled = true;
51  phsEngine = new PhysicsEngine();
52 
53  Joints.ItemAdded += OnJointAdded;
54  Joints.ItemRemoved += OnJointRemoved;
55  }
56 
57  void OnJointAdded( Joint j )
58  {
59  j.Lifetime.IsExpired = false;
60  phsEngine.AddJoint( j );
61  }
62 
63  void OnJointRemoved( Joint j )
64  {
65  j.Lifetime.IsExpired = true;
66  }
67 
68  protected override void OnObjectAdded( IGameObject obj )
69  {
70  if ( obj is PhysicsObject )
71  {
72  AddToEngine( (PhysicsObject)obj );
73  }
74 
75  base.OnObjectAdded( obj );
76  }
77 
78  protected override void OnObjectRemoved( IGameObject obj )
79  {
80  if ( obj is PhysicsObject )
81  {
82  RemoveFromEngine( (PhysicsObject)obj );
83  }
84 
85  base.OnObjectRemoved( obj );
86  }
87 
91  public void StopAll()
92  {
93  foreach ( var layer in Layers )
94  {
95  foreach ( var obj in layer.Objects )
96  {
97  if ( obj is PhysicsObject )
98  ( (PhysicsObject)obj ).Stop();
99  }
100  }
101  }
102 
106  public override void ClearAll()
107  {
108  ClearPhysics();
109  base.ClearAll();
110  }
111 
115  private void ClearPhysics()
116  {
117  phsEngine.Clear();
118  }
119 
120  private void AddToEngine( PhysicsObject po )
121  {
122  if ( po.Body.Engine != null )
123  return;
124 
125  po.Body.Lifetime.IsExpired = false;
126  phsEngine.AddBody( po.Body );
127  }
128 
129  private void RemoveFromEngine( PhysicsObject po )
130  {
131  if ( po.Body.Engine == null )
132  return;
133 
134  po.Body.Lifetime.IsExpired = true;
135  }
136 
140  public void Add( Physics2DDotNet.Joints.Joint j )
141  {
142  Joints.Add( j );
143  }
144 
149  internal void Remove( Physics2DDotNet.Joints.Joint j )
150  {
151  Joints.Remove( j );
152  }
153 
158  internal void Remove( AxleJoint j )
159  {
160  Joints.Remove( j.innerJoint );
161  }
162 
166  public void Add( AxleJoint j )
167  {
168  bool obj1ok = j.Object1.IsAddedToGame;
169  bool obj2ok = j.Object2 == null || j.Object2.IsAddedToGame;
170 
171  if ( obj1ok && obj2ok )
172  {
173  Add( j.innerJoint );
174  }
175  else
176  {
177  if ( !obj1ok ) j.Object1.AddedToGame += j.DelayedAddJoint;
178  if ( !obj2ok ) j.Object2.AddedToGame += j.DelayedAddJoint;
179  }
180  }
181 
187  protected override void Update( Time time )
188  {
189  double dt = time.SinceLastUpdate.TotalSeconds;
190 
191  if ( PhysicsEnabled )
192  {
193  phsEngine.Update( dt );
194  }
195 
196  base.Update( time );
197 
198  // Updating joints must be after base.Update so that the bodies
199  // are added to the engine before the joints
200  Joints.Update( time );
201  }
202 
203  #region Collision handlers
204 
213  where O : IPhysicsObject
214  where T : IPhysicsObject
215  {
216  if ( obj == null ) throw new NullReferenceException( "Colliding object must not be null" );
217  if ( handler == null ) throw new NullReferenceException( "Handler must not be null" );
218 
219  CollisionHandler<IPhysicsObject, IPhysicsObject> targetHandler =
220  delegate( IPhysicsObject collider, IPhysicsObject collidee )
221  {
222  if ( collidee is T )
223  handler( (O)collider, (T)collidee );
224  };
225 
226  obj.Collided += targetHandler;
227  collisionHandlers.Add( new CollisionRecord( obj, null, null, handler ), targetHandler );
228  }
229 
238  internal void AddProtectedCollisionHandler<O, T>( O obj, CollisionHandler<O, T> handler )
239  where O : IPhysicsObject
240  where T : IPhysicsObject
241  {
242  if ( obj == null ) throw new NullReferenceException( "Colliding object must not be null" );
243  if ( handler == null ) throw new NullReferenceException( "Handler must not be null" );
244 
245  CollisionHandler<IPhysicsObject, IPhysicsObject> targetHandler =
246  delegate( IPhysicsObject collider, IPhysicsObject collidee )
247  {
248  if ( collidee is T )
249  handler( (O)collider, (T)collidee );
250  };
251 
252  obj.Collided += targetHandler;
253  protectedCollisionHandlers.Add( new CollisionRecord( obj, null, null, handler ), targetHandler );
254  }
255 
262  public void AddCollisionHandler( IPhysicsObject obj, CollisionHandler<IPhysicsObject, IPhysicsObject> handler )
263  {
264  AddCollisionHandler<IPhysicsObject, IPhysicsObject>( obj, handler );
265  }
266 
272  public void AddCollisionHandler( PhysicsObject obj, CollisionHandler<PhysicsObject, PhysicsObject> handler )
273  {
274  AddCollisionHandler<PhysicsObject, PhysicsObject>( obj, handler );
275  }
276 
282  public void AddCollisionHandler( PhysicsObject obj, CollisionHandler<PhysicsObject, PhysicsStructure> handler )
283  {
284  AddCollisionHandler<PhysicsObject, PhysicsStructure>( obj, handler );
285  }
286 
292  public void AddCollisionHandler( PhysicsStructure obj, CollisionHandler<PhysicsStructure, PhysicsObject> handler )
293  {
294  AddCollisionHandler<PhysicsStructure, PhysicsObject>( obj, handler );
295  }
296 
302  public void AddCollisionHandler( PhysicsStructure obj, CollisionHandler<PhysicsStructure, PhysicsStructure> handler )
303  {
304  AddCollisionHandler<PhysicsStructure, PhysicsStructure>( obj, handler );
305  }
306 
315  where O : IPhysicsObject
316  where T : IPhysicsObject
317  {
318  if ( obj == null ) throw new NullReferenceException( "Colliding object must not be null" );
319  if ( target == null ) throw new NullReferenceException( "Collision target must not be null" );
320  if ( handler == null ) throw new NullReferenceException( "Handler must not be null" );
321 
322  CollisionHandler<IPhysicsObject, IPhysicsObject> targetHandler =
323  delegate( IPhysicsObject collider, IPhysicsObject collidee )
324  {
325  if ( object.ReferenceEquals( collidee, target ) )
326  handler( (O)collider, (T)collidee );
327  };
328 
329  obj.Collided += targetHandler;
330  collisionHandlers.Add( new CollisionRecord( obj, target, null, handler ), targetHandler );
331  }
332 
341  where O : IPhysicsObject
342  where T : IPhysicsObject
343  {
344  if ( obj == null ) throw new NullReferenceException( "Colliding object must not be null" );
345  if ( tag == null ) throw new NullReferenceException( "Tag must not be null" );
346  if ( handler == null ) throw new NullReferenceException( "Handler must not be null" );
347 
348  CollisionHandler<IPhysicsObject, IPhysicsObject> targetHandler =
349  delegate( IPhysicsObject collider, IPhysicsObject collidee )
350  {
351  if ( collidee is T && StringHelpers.StringEquals( collidee.Tag, tag ) )
352  handler( (O)collider, (T)collidee );
353  };
354 
355  obj.Collided += targetHandler;
356  collisionHandlers.Add( new CollisionRecord( obj, null, tag, handler ), targetHandler );
357  }
358 
367  where O : IPhysicsObject
368  where T : IPhysicsObject
369  {
370  if ( target is T )
371  AddCollisionHandlerByRef( obj, (T)target, handler );
372  else
373  AddCollisionHandlerByTag( obj, target, handler );
374  }
375 
383  public void AddCollisionHandler( IPhysicsObject obj, object tag, CollisionHandler<IPhysicsObject, IPhysicsObject> handler )
384  {
385  AddCollisionHandler<IPhysicsObject, IPhysicsObject>( obj, tag, handler );
386  }
387 
395  public void AddCollisionHandler( PhysicsObject obj, object tag, CollisionHandler<PhysicsObject, PhysicsObject> handler )
396  {
397  AddCollisionHandler<PhysicsObject, PhysicsObject>( obj, tag, handler );
398  }
399 
407  public void RemoveCollisionHandlers( PhysicsObject obj = null, PhysicsObject target = null, object tag = null, Delegate handler = null )
408  {
409  Predicate<CollisionRecord> pred = rec =>
410  ( obj == null || object.ReferenceEquals( obj, rec.obj ) ) &&
411  ( target == null || target == rec.target ) &&
412  ( tag == null || StringHelpers.StringEquals( tag, rec.targetTag ) ) &&
413  ( handler == null || object.ReferenceEquals( handler, rec.handler ) );
414 
415  List<CollisionRecord> remove = new List<CollisionRecord>();
416 
417  foreach (var key in collisionHandlers.Keys)
418  {
419  if (pred(key)) remove.Add(key);
420  }
421 
422  foreach (var key in remove)
423  {
424  key.obj.Collided -= collisionHandlers[key];
425  collisionHandlers.Remove(key);
426  }
427  }
428 
437  internal void RemoveProtectedCollisionHandlers( PhysicsObject obj = null, PhysicsObject target = null, object tag = null, Delegate handler = null )
438  {
439  Predicate<CollisionRecord> pred = rec =>
440  ( obj == null || object.ReferenceEquals( obj, rec.obj ) ) &&
441  ( target == null || target == rec.target ) &&
442  ( tag == null || tag.Equals( rec.targetTag ) ) &&
443  ( handler == null || object.ReferenceEquals( handler, rec.handler ) );
444 
445  List<CollisionRecord> remove = new List<CollisionRecord>();
446 
447  foreach ( var key in collisionHandlers.Keys )
448  {
449  if ( pred( key ) ) remove.Add( key );
450  }
451 
452  foreach ( var key in remove )
453  {
454  key.obj.Collided -= protectedCollisionHandlers[key];
455  protectedCollisionHandlers.Remove( key );
456  }
457  }
458 
459  #endregion
460  }
461 }
void AddCollisionHandler(IPhysicsObject obj, CollisionHandler< IPhysicsObject, IPhysicsObject > handler)
Määrää, mihin aliohjelmaan siirrytään kun yleinen fysiikkaolio
bool IsAddedToGame
Onko olio lisätty peliin.
Dictionary< CollisionRecord, CollisionHandler< IPhysicsObject, IPhysicsObject > > protectedCollisionHandlers
delegate void CollisionHandler< O, T >(O collidingObject, T otherObject)
Törmäystapahtumiin liitettävän metodin tyyppi. Törmäyksen käsittelevällä metodilla ei ole paluuarvoa ja se ott...
void Add(Physics2DDotNet.Joints.Joint j)
Lisää liitoksen peliin.
override void OnObjectAdded(IGameObject obj)
void AddCollisionHandlerByRef< O, T >(O obj, T target, CollisionHandler< O, T > handler)
Määrää, mihin aliohjelmaan siirrytään kun olio
Yhteinen rajapinta kaikille fysiikkaolioille.
void AddCollisionHandler(PhysicsObject obj, CollisionHandler< PhysicsObject, PhysicsStructure > handler)
Määrää, mihin aliohjelmaan siirrytään kun fysiikkaolio
void Update(Time time)
Lisää ja poistaa jonossa olevat elementit sekä kutsuu niiden Update-metodia.
object Tag
Definition: Tagged.cs:8
void AddCollisionHandler(IPhysicsObject obj, object tag, CollisionHandler< IPhysicsObject, IPhysicsObject > handler)
Määrää, mihin aliohjelmaan siirrytään kun yleinen fysiikkaolio
override void ClearAll()
Nollaa kaiken (kontrollit, näyttöobjektit, ajastimet ja fysiikkamoottorin).
void StopAll()
Pysäyttää kaiken liikkeen.
Peliolio, joka noudattaa fysiikkamoottorin määräämiä fysiikan lakeja. Voidaan kuitenkin myös laittaa ...
Definition: Coefficients.cs:36
void AddCollisionHandler(PhysicsStructure obj, CollisionHandler< PhysicsStructure, PhysicsObject > handler)
Määrää, mihin aliohjelmaan siirrytään kun fysiikkarakenne
TimeSpan SinceLastUpdate
Aika joka on kulunut viime päivityksestä.
Definition: Time.cs:24
PhysicsObject Object2
Toinen olio (null jos ensimmäinen olio on sidottu pisteeseen)
Definition: AxleJoint.cs:58
void AddCollisionHandler< O, T >(O obj, CollisionHandler< O, T > handler)
Määrää, mihin aliohjelmaan siirrytään kun olio
Sisältää tiedon ajasta, joka on kulunut pelin alusta ja viime päivityksestä.
Definition: Time.cs:13
Saranaliitos kahden olion välille.
Definition: AxleJoint.cs:45
Rakenne, joka pitää fysiikkaoliot kiinteän matkan päässä toisistaan.
static bool StringEquals(object o1, object o2)
Vertaa kahta oliota, jotka ovat joko merkkijonoja tai StringBuildereita, merkki kerrallaan.
SynchronousList< Layer > Layers
Kerrokset, joilla pelioliot viihtyvät.
Definition: Game.cs:95
Peliluokka reaaliaikaisille peleille.
Definition: DebugScreen.cs:10
PhysicsObject Object1
Ensimmäinen olio.
Definition: AxleJoint.cs:53
void AddCollisionHandler(PhysicsObject obj, CollisionHandler< PhysicsObject, PhysicsObject > handler)
Määrää, mihin aliohjelmaan siirrytään kun fysiikkaolio
CollisionRecord(IPhysicsObject obj, IPhysicsObject target, object targetTag, Delegate handler)
void AddCollisionHandlerByTag< O, T >(O obj, object tag, CollisionHandler< O, T > handler)
Määrää, mihin aliohjelmaan siirrytään kun olio
Action< T > ItemAdded
Tapahtuu kun uusi elementti on lisätty listaan.
Action AddedToGame
Tapahtuu, kun olio lisätään peliin.
Body Body
Fysiikkamoottorin käyttämä tietorakenne.
Definition: Dimensions.cs:42
Kantaluokka fysiikkapeleille.
bool PhysicsEnabled
Onko fysiikan laskenta käytössä vai ei.
void AddCollisionHandler(PhysicsStructure obj, CollisionHandler< PhysicsStructure, PhysicsStructure > handler)
Määrää, mihin aliohjelmaan siirrytään kun fysiikkarakenne
void Add(AxleJoint j)
Lisää liitoksen peliin.
override void Update(Time time)
Ajetaan kun pelin tilannetta päivitetään. Päivittämisen voi toteuttaa perityssä luokassa toteuttamall...
Yhteinen rajapinta kaikille peliolioille.
Definition: IGameObject.cs:14
void RemoveCollisionHandlers(PhysicsObject obj=null, PhysicsObject target=null, object tag=null, Delegate handler=null)
Poistaa kaikki ehdot täyttävät törmäyksenkäsittelijät.
override void OnObjectRemoved(IGameObject obj)
PhysicsGameBase(int device)
Alustaa uuden fysiikkapelin.
Action< T > ItemRemoved
Tapahtuu kun elementti on poistettu listasta.
void AddCollisionHandler(PhysicsObject obj, object tag, CollisionHandler< PhysicsObject, PhysicsObject > handler)
Määrää, mihin aliohjelmaan siirrytään kun fysiikkaolio
Dictionary< CollisionRecord, CollisionHandler< IPhysicsObject, IPhysicsObject > > collisionHandlers