Jypeli 10
The simple game programming library
ParticleSystem.cs
Siirry tämän tiedoston dokumentaatioon.
1using System;
2using System.Collections.Generic;
3using Microsoft.Xna.Framework;
4using Microsoft.Xna.Framework.Graphics;
5
6namespace Jypeli.Effects
7{
11 public enum BlendMode
12 {
13#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
14 Alpha,
16#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
17 }
18
19
24 {
25 private Random random = new Random();
26
27 // Lista efektin partikkeleille
28 private LinkedList<Particle> particles;
29
30 // Jono efektin vapaille partikkeleille
31 private Queue<Particle> freeParticles;
32
36 public Image ParticleImage { get; set; }
37
41 public Image OuterParticleImage { get; set; }
42
43 // Perivien luokkien täytyy määrittää nämä muuttujat
44 #region Subclass variables
45
49 public double MinScale { get; set; }
50
54 public double MaxScale { get; set; }
55
59 public double ScaleAmount { get; set; }
60
64 public double MinVelocity { get; set; }
68 public double MaxVelocity { get; set; }
69
73 public double MinLifetime { get; set; }
74
78 public double MaxLifetime { get; set; }
79
83 public double MinAcceleration { get; set; }
84
88 public double MaxAcceleration { get; set; }
89
93 public double MinRotationSpeed { get; set; }
94
98 public double MaxRotationSpeed { get; set; }
99
103 public double MinRotation { get; set; }
104
108 public double MaxRotation { get; set; }
109
113 public double AlphaAmount { get; set; }
114
118 public double MaxAngleChange { get; set; }
119
120 #endregion
121
125 public BlendMode BlendMode { get; set; }
126
130 public Boolean IgnoreWind { get; set; }
131
132 private Boolean visible = true;
133 private Boolean fadeIn = false;
134 private Boolean fadeOut = false;
135 private double originalAlpha = 1.0;
136 private double fadeTime = 0.0;
137 private double fadeTimePassed = 0.0;
138
143 public void FadeIn(double timeInSeconds)
144 {
145 if (!visible)
146 {
147 fadeTimePassed = 0.0;
148 fadeIn = true;
149 fadeTime = timeInSeconds;
150 }
151 }
152
157 public void FadeOut(double TimeInSeconds)
158 {
159 if (visible)
160 {
162 fadeTimePassed = 0.0;
163 fadeOut = true;
164 fadeTime = TimeInSeconds;
165 }
166 }
172 public ParticleSystem(Image particleImage, int maxAmountOfParticles)
173 : base(0, 0)
174 {
175 this.ParticleImage = particleImage;
176 AlphaAmount = 1.0;
177 IgnoreWind = false;
178 BlendMode = BlendMode.Alpha;
179
180 IsUpdated = true;
182
183 particles = new LinkedList<Particle>();
184 freeParticles = new Queue<Particle>(maxAmountOfParticles);
185 for (int i = 0; i < maxAmountOfParticles; i++)
186 {
187 freeParticles.Enqueue(new Particle());
188 }
189 }
190
195 protected virtual void InitializeParticles()
196 {
197 }
198
205 public void AddEffect(double x, double y, int numberOfParticles)
206 {
207 AddEffect(new Vector(x, y), numberOfParticles);
208 }
209
216 public void AddEffect(Vector position, Angle angle, int numberOfParticles)
217 {
218 for (int i = 0; i < numberOfParticles && freeParticles.Count > 0; i++)
219 {
220 Particle p = freeParticles.Dequeue();
221 particles.AddLast(p);
222 InitializeParticle(p, position, angle);
223 }
224 }
225
231 public void AddEffect(Vector position, int numberOfParticles)
232 {
233 for (int i = 0; i < numberOfParticles && freeParticles.Count > 0; i++)
234 {
235 Particle p = freeParticles.Dequeue();
236 particles.AddLast(p);
237 InitializeParticle(p, position);
238 }
239 }
240
245 protected virtual Vector GiveRandomDirection()
246 {
247 double angle = random.NextDouble() * MathHelper.TwoPi;
248 return new Vector(Math.Cos(angle), Math.Sin(angle));
249 }
250
256 protected virtual void InitializeParticle(Particle p, Vector position)
257 {
258 Vector direction = GiveRandomDirection();
259
260 double scale = RandomGen.NextDouble(MinScale, MaxScale);
261 double rotation = RandomGen.NextDouble(MinRotation, MaxRotation);
262 double velocity = RandomGen.NextDouble(MinVelocity, MaxVelocity);
263 double lifetime = RandomGen.NextDouble(MinLifetime, MaxLifetime);
264 double acceleration = RandomGen.NextDouble(MinAcceleration, MaxAcceleration);
265 double rotationSpeed = RandomGen.NextDouble(MinRotationSpeed, MaxRotationSpeed);
266
267 p.Initialize(position, scale, rotation, rotationSpeed, velocity * direction, acceleration * direction, lifetime);
268 }
269
270 protected virtual void InitializeParticle(Particle p, Vector position, Angle angle)
271 {
272 Vector direction = GiveRandomDirection();
273
274 double rotation = angle.Degrees;
275 double scale = RandomGen.NextDouble(MinScale, MaxScale);
276 double velocity = RandomGen.NextDouble(MinVelocity, MaxVelocity);
277 double lifetime = RandomGen.NextDouble(MinLifetime, MaxLifetime);
278 double acceleration = RandomGen.NextDouble(MinAcceleration, MaxAcceleration);
279 double rotationSpeed = RandomGen.NextDouble(MinRotationSpeed, MaxRotationSpeed);
280
281 p.Initialize(position, scale, rotation, rotationSpeed, velocity * direction, acceleration * direction, lifetime);
282 }
283
288 public override void Update(Time time)
289 {
290 double t = time.SinceLastUpdate.TotalSeconds;
291
292 LinkedListNode<Particle> node = particles.First;
293 while (node != null)
294 {
295 Particle p = node.Value;
296 if (p.Alive)
297 {
298 p.Update(t);
299 node = node.Next;
300 }
301 else
302 {
303 freeParticles.Enqueue(p);
304 LinkedListNode<Particle> previous = node;
305 node = node.Next;
306 particles.Remove(previous);
307 }
308 }
309 if (fadeOut)
310 {
312 fadeTimePassed += t;
314 {
315 AlphaAmount = 0.0;
316 fadeOut = false;
317 visible = false;
318 }
319 }
320 if (fadeIn)
321 {
323 fadeTimePassed += t;
325 {
327 fadeIn = false;
328 visible = true;
329 }
330 }
331
332 base.Update(time);
333 }
334
335
336 static readonly Vector2 textureTopLeft = new Vector2(0.0f, 0.0f);
337 static readonly Vector2 textureBottomLeft = new Vector2(0.0f, 1.0f);
338 static readonly Vector2 textureTopRight = new Vector2(1.0f, 0.0f);
339 static readonly Vector2 textureBottomRight = new Vector2(1.0f, 1.0f);
340
341 static readonly Vector3 topLeft = new Vector3(-0.5f, 0.5f, 0);
342 static readonly Vector3 bottomLeft = new Vector3(-0.5f, -0.5f, 0);
343 static readonly Vector3 topRight = new Vector3(0.5f, 0.5f, 0);
344 static readonly Vector3 bottomRight = new Vector3(0.5f, -0.5f, 0);
345
346 static readonly VertexPositionTexture[] vertices =
347 {
348 // Triangle 1
349 new VertexPositionTexture(topLeft, textureTopLeft),
350 new VertexPositionTexture(bottomLeft, textureBottomLeft),
351 new VertexPositionTexture(topRight, textureTopRight),
352
353 // Triangle 2
354 new VertexPositionTexture(bottomLeft, textureBottomLeft),
355 new VertexPositionTexture(bottomRight, textureBottomRight),
356 new VertexPositionTexture(topRight, textureTopRight),
357 };
358
359 private static BlendState ToXnaBlendState(BlendMode mode)
360 {
361 switch (mode)
362 {
363 case BlendMode.Alpha:
364 return BlendState.AlphaBlend;
365 case BlendMode.Additive:
366 return BlendState.Additive;
367 default:
368 return BlendState.AlphaBlend;
369 }
370 }
371
372 internal void Draw(Matrix worldMatrix)
373 {
374 var device = Game.GraphicsDevice;
375 var effect = Graphics.BasicTextureEffect;
376
377 Texture2D texture = ParticleImage.XNATexture;
378
379 device.RasterizerState = RasterizerState.CullClockwise;
380 device.SamplerStates[0] = SamplerState.LinearClamp;
381 device.BlendState = ToXnaBlendState(BlendMode);
382
383 effect.Texture = texture;
384 effect.CurrentTechnique.Passes[0].Apply();
385
386 if (OuterParticleImage == null)
387 {
388 foreach (Particle p in particles)
389 {
390 double nTime = p.Lifetime.TotalMilliseconds / p.MaxLifetime.TotalMilliseconds;
391 double alpha = 4 * nTime * (1 - nTime) * AlphaAmount;
392 float scale = (float)(p.Scale * (.75f + .25f * nTime * ScaleAmount));
393
394 Matrix matrix =
395 Matrix.CreateScale(scale * texture.Width / texture.Height, scale, 1f)
396 * Matrix.CreateRotationZ((float)p.Rotation)
397 * Matrix.CreateTranslation((float)p.Position.X, (float)p.Position.Y, 0f)
398 * worldMatrix
399 ;
400
401 effect.Alpha = (float)alpha;
402 effect.World = matrix;
403 effect.CurrentTechnique.Passes[0].Apply();
404
405 device.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, 2);
406 }
407 }
408 else
409 {
410 Texture2D outerTexture = OuterParticleImage.XNATexture;
411
412 foreach (Particle p in particles)
413 {
414 double nTime = p.Lifetime.TotalMilliseconds / p.MaxLifetime.TotalMilliseconds;
415 double alpha = 4 * nTime * (1 - nTime) * AlphaAmount;
416 float scale = (float)(p.Scale * (.75f + .25f * nTime * ScaleAmount));
417
418 Matrix matrix =
419 Matrix.CreateScale(scale, scale, 1f)
420 * Matrix.CreateRotationZ((float)p.Rotation)
421 * Matrix.CreateTranslation((float)p.Position.X, (float)p.Position.Y, 0f)
422 * worldMatrix
423 ;
424 Matrix matrix2 =
425 Matrix.CreateScale(0.65f, 0.65f, 1f)
426 * matrix;
427
428 effect.Texture = texture;
429 effect.Alpha = (float)alpha;
430 effect.World = matrix;
431 effect.CurrentTechnique.Passes[0].Apply();
432
433 device.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, 2);
434
435 effect.Texture = outerTexture;
436 effect.World = matrix2;
437 effect.CurrentTechnique.Passes[0].Apply();
438
439 device.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleList, vertices, 0, 2);
440 }
441 }
442 }
443 }
444}
System.Numerics.Vector2 Vector2
Vector Position
Partikkelin sijainti
Definition: Particle.cs:25
TimeSpan Lifetime
Partikkelin tämän hetkinen ikä
Definition: Particle.cs:96
void Initialize(Vector position, double scale, double rotation, double rotationSpeed, Vector velocity, Vector acceleration, double lifetime)
Alusta partikkeli
Definition: Particle.cs:112
TimeSpan MaxLifetime
Partikkelin elinikä
Definition: Particle.cs:87
double Scale
Partikkelin skaalaus
Definition: Particle.cs:34
bool Alive
Onko partikkelin "elossa", eli päivitetäänkö ja piirretäänkö se
Definition: Particle.cs:79
void Update(double time)
Päivittää partikkelin sijannin, nopeuden ja kierron
Definition: Particle.cs:131
double Rotation
Partikkelin kierto
Definition: Particle.cs:43
Järjestelmä partikkelien käsittelyyn
static readonly VertexPositionTexture[] vertices
void AddEffect(double x, double y, int numberOfParticles)
Lisää efektin kentälle
Boolean IgnoreWind
Vaikuttaako efektiin tuuli
double MinScale
Pienin skaalaus joka efektin partikkeleilla voi olla
Queue< Particle > freeParticles
LinkedList< Particle > particles
static readonly Vector3 topLeft
static readonly Vector2 textureBottomLeft
override void Update(Time time)
Kutsutaan kun luokka päivitetään
static readonly Vector3 topRight
double AlphaAmount
Efektin läpinäkyvyyskerroin (0.0-1.0)
Image ParticleImage
Yksittäisen partikkelin kuva.
double MaxRotation
Suurin kierre mikä efektin partikkelilla voi olla
virtual Vector GiveRandomDirection()
Antaa satunnaisen suunnan
Image OuterParticleImage
Partikkelin toissijainen kuva. Jos null niin käytetään vain yhtä kuvaa.
static readonly Vector3 bottomLeft
double MaxLifetime
Efektin partikkelin pisin mahdollinen elinaika
double MaxScale
Suurin skaalaus joka efektin partikkeleilla voi olla
virtual void InitializeParticle(Particle p, Vector position)
Alustaa yhden partikkelin
double MinLifetime
Efektin partikkelin lyhin mahdollinen elinaika
double MaxAngleChange
Suurin sallittu suunnan poikkeama asteina
double ScaleAmount
Määrä jonka partikkeli skaalautuu päivityksessä
void Draw(Matrix worldMatrix)
ParticleSystem(Image particleImage, int maxAmountOfParticles)
Muodostaja
double MaxRotationSpeed
Suurin pyörimisnopeus joka efektin partikkelilla voi olla
virtual void InitializeParticles()
Metodi joka asettaa partikkeleille attribuutit Täytyy kutsua perityistä luokista
double MinVelocity
Pienin nopeus joka efektin partikkelilla voi olla
double MinRotation
Pienin kierre mikä efektin partikkelilla voi olla
virtual void InitializeParticle(Particle p, Vector position, Angle angle)
void FadeIn(double timeInSeconds)
Efekti tulee näkyviin tietyn sekuntimäärän aikana
static readonly Vector2 textureTopLeft
void AddEffect(Vector position, int numberOfParticles)
Lisää efektin kentälle
double MinRotationSpeed
Pienin pyörimisnopeus joka efektin partikkelilla voi olla
double MaxVelocity
Suurin nopeus joka efektin partikkelilla voi olla
void FadeOut(double TimeInSeconds)
Efekti hiipuu näkyvistä tietyn sekuntimäärän aikana
double MinAcceleration
Pienin kiihtyvyys joka efektin partikkelilla voi olla
static readonly Vector2 textureBottomRight
static readonly Vector3 bottomRight
double MaxAcceleration
Suurin kiihtyvyys joka efektin partikkelilla voi olla
static readonly Vector2 textureTopRight
void AddEffect(Vector position, Angle angle, int numberOfParticles)
Lisää efektin kentälle
static BlendState ToXnaBlendState(BlendMode mode)
static new GraphicsDevice GraphicsDevice
XNA:n grafiikkakortti.
Definition: Graphics.cs:49
Pelialueella liikkuva olio. Käytä fysiikkapeleissä PhysicsObject-olioita.
Definition: Appearance.cs:34
bool IsUpdated
Tarvitseeko olio päivittämistä. Kun perit oman luokkasi tästä luokasta, aseta tämä arvoon true,...
Contains graphics resources.
Definition: Graphics.cs:36
static BasicEffect BasicTextureEffect
Definition: Graphics.cs:37
Kuva.
Definition: Image.cs:30
Texture2D XNATexture
Definition: Image.cs:72
Satunnaisgeneraattori. Luo satunnaisia arvoja, mm. lukuja, vektoreita sekä kulmia.
Definition: RandomGen.cs:39
static double NextDouble(double min, double max)
Palauttaa satunnaisen liukuluvun parametrien
Definition: RandomGen.cs:70
BlendMode
Sekoitusmoodi, kuinka päällekkäin olevat osittain läpinäkyvät kappaleet näkyvät
Microsoft.Xna.Framework.Matrix Matrix
Definition: Mouse.cs:36
Suuntakulma (rajoitettu -180 ja 180 asteen välille) asteina ja radiaaneina. Tietoja kulmasta: http://...
Definition: Angle.cs:40
double Degrees
Palauttaa tai asettaa kulman asteina.
Definition: Angle.cs:69
Sisältää tiedon ajasta, joka on kulunut pelin alusta ja viime päivityksestä.
Definition: Time.cs:14
TimeSpan SinceLastUpdate
Aika joka on kulunut viime päivityksestä.
Definition: Time.cs:27
2D-vektori.
Definition: Vector.cs:67
double Y
Vektorin Y-komponentti
Definition: Vector.cs:339
double X
Vektorin X-komponentti.
Definition: Vector.cs:334