Jypeli  5
The simple game programming library
Explosion.cs
Siirry tämän tiedoston dokumentaatioon.
1 #region MIT License
2 /*
3  * Copyright (c) 2009 University of Jyväskylä, Department of Mathematical
4  * Information Technology.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #endregion
25 
26 /*
27  * Authors: Tero Jäntti, Tomi Karppinen, Janne Nikkanen.
28  */
29 
30 using AdvanceMath;
31 using Microsoft.Xna.Framework;
32 using Microsoft.Xna.Framework.Graphics;
33 using System;
34 using Physics2DDotNet.Shapes;
35 using Microsoft.Xna.Framework.Audio;
36 
37 namespace Jypeli.Assets
38 {
42  public class Explosion : GameObject
43  {
45  private static Image commonImage = null;
46  private static SoundEffect commonSound = null;
47 
48  private GameObject shockWave;
49  private bool initialized;
50 
54  public bool UseShockWave { get; set; }
55 
59  public double MaxRadius { get; set; }
60 
64  public SoundEffect Sound { get; set; }
65 
69  public double CurrentRadius
70  {
71  get { return Size.X; }
72  private set
73  {
74  Size = new Vector( value, value );
75  }
76  }
77 
84  public Color ShockwaveColor
85  {
86  get { return shockWave.Color; }
87  set { shockWave.Color = value; }
88  }
89 
93  public double Speed { get; set; }
94 
99  public double Force { get; set; }
100 
104  public event Action<IPhysicsObject, Vector> ShockwaveReachesObject;
105 
110  public Explosion( Explosion src )
111  : this( src.MaxRadius )
112  {
113  this.UseShockWave = src.UseShockWave;
114  this.ShockwaveColor = src.ShockwaveColor;
115  this.Speed = src.Speed;
116  this.Force = src.Force;
117  }
118 
123  public Explosion( double radius )
124  : base( 0.1, 0.1, Shape.Circle )
125  {
126  UseShockWave = true;
127  MaxRadius = radius;
128  Speed = 250.0;
129  Force = 1000.0;
130  shockWave = new GameObject( 1, 1, Shape.Circle );
131  shockWave.Color = new Color( 240, 248, 255, 60 );
132  Add( shockWave );
133 
134  Game.AssertInitialized( PreloadContent );
135 
136  initialized = false;
137  IsUpdated = true;
138  }
139 
140  private void PreloadContent()
141  {
142  if ( commonImage == null ) commonImage = Game.LoadImageFromResources( "explosion" );
143  if ( commonSound == null ) commonSound = Game.LoadSoundEffectFromResources( "explosionSound" );
144 
145  Image = commonImage;
146  Sound = commonSound;
147  }
148 
149  private void OnShockwaveReachesObject( IPhysicsObject obj, Vector swForce )
150  {
151  if ( ShockwaveReachesObject != null )
152  ShockwaveReachesObject( obj, swForce );
153  }
154 
160  public void AddShockwaveHandler( IPhysicsObject o, Action<IPhysicsObject, Vector> handler )
161  {
162  if ( o == null ) throw new NullReferenceException( "Object must not be null" );
163  if ( handler == null ) throw new NullReferenceException( "Handler must not be null" );
164 
165  this.ShockwaveReachesObject += delegate( IPhysicsObject target, Vector shockForce )
166  {
167  if ( target == o )
168  handler( target, shockForce );
169  };
170  }
171 
177  public void AddShockwaveHandler(string tag, Action<IPhysicsObject, Vector> handler)
178  {
179  if (tag == null) throw new NullReferenceException("Tag must not be null");
180  if (handler == null) throw new NullReferenceException("Handler must not be null");
181 
182  this.ShockwaveReachesObject += delegate(IPhysicsObject target, Vector shockForce)
183  {
184  if (target.Tag == tag)
185  handler(target, shockForce);
186  };
187  }
188 
189  private void applyShockwave( PhysicsObject target, Vector distance )
190  {
191  double distanceFromEdge = distance.Magnitude - CurrentRadius;
192  if ( distanceFromEdge >= 0 )
193  return;
194 
195  double relDistance = ( CurrentRadius + distanceFromEdge ) / CurrentRadius;
196  double shockQuotient = 1 / Math.Pow( relDistance, 2 );
197  double shockForce = Force * shockQuotient;
198 
199  if ( Math.Abs( shockForce ) > float.Epsilon )
200  {
201  Vector shockVector = Vector.FromLengthAndAngle( shockForce, distance.Angle );
202  target.Hit( shockVector );
203 
204  if ( !shockwaveHitObjects.Contains( target ) )
205  {
206  OnShockwaveReachesObject( target, shockVector );
207  shockwaveHitObjects.Add( target );
208  }
209  }
210  }
211 
216  public override void Update( Time time )
217  {
218  // this is done only once, after being added to the game.
219  if ( !initialized )
220  {
221  PlaySound();
222  shockwaveHitObjects.Clear();
223  initialized = true;
224  }
225 
226  if ( CurrentRadius > MaxRadius )
227  {
228  this.Destroy();
229  return;
230  }
231 
232  double dt = time.SinceLastUpdate.TotalSeconds;
233  CurrentRadius += dt * Speed;
234  shockwaveHitObjects.Update( time );
235 
236  if ( UseShockWave )
237  {
238  if ( Force > 0 )
239  {
240  shockWave.Size = new Vector( 2 * CurrentRadius, 2 * CurrentRadius );
241  }
242 
243  foreach ( var layer in Jypeli.Game.Instance.Layers )
244  {
245  foreach ( var o in layer.Objects )
246  {
247  if ( o is PhysicsObject )
248  {
249  PhysicsObject po = (PhysicsObject)o;
250 
251  if ( po.IgnoresExplosions )
252  {
253  // No shockwave
254  continue;
255  }
256 
257  // Shockwave
258  Vector distance = o.AbsolutePosition - this.AbsolutePosition;
259  applyShockwave( po, distance );
260  }
261  }
262  }
263  }
264 
265  base.Update( time );
266  }
267 
268  private void PlaySound()
269  {
270  if ( Sound == null )
271  return;
272 
273  // play the sound
274  double pitch = RandomGen.NextDouble( -0.1, 0.1 ); // add some variation to explosion sound
275  double pan = this.Position.X / ( Game.Screen.Width / 2 ); // sound comes from left or right speaker
276  pan = AdvanceMath.MathHelper.Clamp( (float)pan, (float)-1.0, (float)1.0 );
277  if ( !double.IsNaN( pan ) ) // sometimes pan can be Nan, that is why this check is here
278  {
279  Sound.Play( 1.0f, pitch, pan );
280  }
281  }
282  }
283 }
Color Color
Väri, jonka värisenä olio piirretään, jos tekstuuria ei ole määritelty.
Explosion(Explosion src)
Luo uuden räjähdyksen entisen pohjalta.
Definition: Explosion.cs:110
static Image LoadImageFromResources(string name)
Definition: Game.cs:1613
Kuvio.
Definition: Shapes.cs:48
double Magnitude
Vektorin pituus.
Definition: Vector.cs:281
Angle Angle
Kulma radiaaneina.
Definition: Vector.cs:308
Color ShockwaveColor
Paineaallon väri. Shockwave.Color = Color.White
Definition: Explosion.cs:85
Explosion(double radius)
Luo uuden räjähdyksen.
Definition: Explosion.cs:123
Yhteinen rajapinta kaikille fysiikkaolioille.
void Update(Time time)
Lisää ja poistaa jonossa olevat elementit sekä kutsuu niiden Update-metodia.
Satunnaisgeneraattori. Luo satunnaisia arvoja, mm. lukuja, vektoreita sekä kulmia.
Definition: RandomGen.cs:39
void AddShockwaveHandler(string tag, Action< IPhysicsObject, Vector > handler)
Laukaisee aliohjelman handler, kun tämän räjähdyksen paineaalto osuu olioon o.
Definition: Explosion.cs:177
object Tag
Definition: Tagged.cs:8
Ääniefekti. Yhdestä efektistä voi luoda CreateSound-metodilla monta ääntä (Sound), jotka voivat soida yhtäaikaa. Ääntä ei tarvitse kuitenkaan luoda itse, jos vain kutsuu Play-metodia.
Definition: SoundEffect.cs:15
static double NextDouble(double min, double max)
Palauttaa satunnaisen liukuluvun parametrien
Definition: RandomGen.cs:78
override Vector Size
Olion koko pelimaailmassa. Kertoo olion äärirajat, ei muotoa.
Definition: __GameObject.cs:98
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
Sisältää tiedon ajasta, joka on kulunut pelin alusta ja viime päivityksestä.
Definition: Time.cs:13
Kuva.
Definition: Image.cs:24
static SoundEffect LoadSoundEffectFromResources(string name)
Definition: Game.cs:1618
SynchronousList< Layer > Layers
Kerrokset, joilla pelioliot viihtyvät.
Definition: Game.cs:95
bool UseShockWave
Onko paineaalto käytössä.
Definition: Explosion.cs:54
static ScreenView Screen
Näytön dimensiot, eli koko ja reunat.
Definition: Game.cs:194
virtual void Hit(Vector impulse)
Kohdistaa kappaleeseen impulssin. Tällä kappaleen saa nopeasti liikkeeseen.
Definition: Movement.cs:147
Peliluokka reaaliaikaisille peleille.
Definition: DebugScreen.cs:10
void AddShockwaveHandler(IPhysicsObject o, Action< IPhysicsObject, Vector > handler)
Laukaisee aliohjelman handler, kun tämän räjähdyksen paineaalto osuu olioon o.
Definition: Explosion.cs:160
override void Update(Time time)
Ajetaan kun pelitilannetta päivitetään. Päivityksen voi toteuttaa omassa luokassa toteuttamalla tämän...
Definition: Explosion.cs:216
static readonly Ellipse Circle
Ympyrä tai ellipsi.
Definition: Shapes.cs:62
double Speed
Räjähdyksen leviämisnopeus (pikseliä sekunnissa)
Definition: Explosion.cs:93
Väri.
Definition: Color.cs:13
bool IgnoresExplosions
Jättääkö olio räjähdyksen paineaallon huomiotta.
Synkroninen lista, eli lista joka päivittyy vasta kun sen Update-metodia kutsutaan. Jos listalle lisätään IUpdatable-rajapinnan toteuttavia olioita, kutsutaan myös niiden Update-metodeja samalla.
Action< IPhysicsObject, Vector > ShockwaveReachesObject
Tapahtuu, kun paineaalto osuu peliolioon.
Definition: Explosion.cs:104
void Play()
Definition: Sound.cs:62
2D-vektori.
Definition: Vector.cs:56
double Width
Näytön leveys x-suunnassa.
Definition: View.cs:66
double Force
Voima, jolla räjähdyksen paineaallon uloin reuna heittää olioita räjähdyksestä poispäin. Vihje: voit käyttää myös negatiivisia arvoja, jolloin räjähdys imee olioita sisäänsä.
Definition: Explosion.cs:99
Pelialueella liikkuva olio. Käytä fysiikkapeleissä PhysicsObject-olioita.
Definition: __GameObject.cs:54
static void AssertInitialized(Action actionMethod)
Suorittaa aliohjelman kun peli on varmasti alustettu.
Definition: Game.cs:630