Merge remote-tracking branch 'origin/master'
# Conflicts: # CityGame/Classes/Rendering/Particles/Explosion.cs
This commit is contained in:
commit
18dce569c0
8 changed files with 102 additions and 14 deletions
|
|
@ -1,11 +1,14 @@
|
||||||
using CityGame.Classes.Rendering;
|
using CityGame.Classes.Rendering;
|
||||||
|
using CityGame.Classes.Rendering.Particles;
|
||||||
using CityGame.Classes.World;
|
using CityGame.Classes.World;
|
||||||
using OrpticonGameHelper.Classes.Effects;
|
using OrpticonGameHelper.Classes.Effects;
|
||||||
|
using OrpticonGameHelper.Classes.Elements;
|
||||||
|
|
||||||
namespace CityGame.Classes.Entities
|
namespace CityGame.Classes.Entities
|
||||||
{
|
{
|
||||||
public abstract class Entity : ISelectable
|
public abstract class Entity : ISelectable
|
||||||
{
|
{
|
||||||
|
public bool IsSingleSelect() => SingleSelect;
|
||||||
public float X { get; set; }
|
public float X { get; set; }
|
||||||
public float Y { get; set; }
|
public float Y { get; set; }
|
||||||
protected float visualX;
|
protected float visualX;
|
||||||
|
|
@ -38,6 +41,21 @@ namespace CityGame.Classes.Entities
|
||||||
{
|
{
|
||||||
car.Path = null;
|
car.Path = null;
|
||||||
car.Target = target;
|
car.Target = target;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(this is GasPipe pipe)
|
||||||
|
{
|
||||||
|
if (pipe.Exploded > 0) return false;
|
||||||
|
Explosion x = new Explosion();
|
||||||
|
pipe.canvas.Children.Add(x);
|
||||||
|
Canvas.SetLeft(x, pipe.GetParticleOrigin().X);
|
||||||
|
Canvas.SetTop(x, pipe.GetParticleOrigin().Y);
|
||||||
|
x.RotationOrigin = new Microsoft.Xna.Framework.Point(MainWindow.TileSize / 2);
|
||||||
|
x.Size = 16;
|
||||||
|
x.MaxParticleDistance = 32;
|
||||||
|
x.Emit();
|
||||||
|
pipe.Exploded = 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,62 @@
|
||||||
using CityGame.Classes.Rendering;
|
using CityGame.Classes.Rendering;
|
||||||
|
using CityGame.Classes.Rendering.Particles;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
using OrpticonGameHelper.Classes.Elements;
|
using OrpticonGameHelper.Classes.Elements;
|
||||||
|
|
||||||
namespace CityGame.Classes.Entities
|
namespace CityGame.Classes.Entities
|
||||||
{
|
{
|
||||||
public class GasPipe : Entity
|
public class GasPipe : Entity
|
||||||
{
|
{
|
||||||
public int Exploded { get; set; }
|
public long Exploded { get; set; }
|
||||||
|
public Image image { get; set; }
|
||||||
|
public OCanvas canvas { get; set; }
|
||||||
|
public Explosion Smoke { get; set; }
|
||||||
public GasPipe()
|
public GasPipe()
|
||||||
{
|
{
|
||||||
if (MainWindow.random.Next(0, 2) == 0) Rotation += 180;
|
if (MainWindow.random.Next(0, 2) == 0) Rotation += 180;
|
||||||
SingleSelect = true;
|
SingleSelect = true;
|
||||||
}
|
}
|
||||||
|
public Vector2 GetParticleOrigin()
|
||||||
|
{
|
||||||
|
return new Vector2(MainWindow.TileSize / 2);
|
||||||
|
}
|
||||||
public override OCanvas Render()
|
public override OCanvas Render()
|
||||||
{
|
{
|
||||||
return new SourcedImage("ManholeCover.png") { ZIndex = 98, Effects = { selectedEffect } };
|
image = new SourcedImage("ManholeCover.png") { ZIndex = 98, Effects = { selectedEffect } };
|
||||||
|
canvas = image;
|
||||||
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Tick(long deltaTime)
|
public override void Tick(long deltaTime)
|
||||||
{
|
{
|
||||||
|
if (Exploded > 0)
|
||||||
|
{
|
||||||
|
Exploded += deltaTime;
|
||||||
|
if(Smoke is null)
|
||||||
|
{
|
||||||
|
CreateSmoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void CreateSmoke()
|
||||||
|
{
|
||||||
|
Explosion smoke = new Explosion();
|
||||||
|
smoke.DirectionTendency = MainWindow.Wind;
|
||||||
|
smoke.DirectionVariance = 22.5f;
|
||||||
|
smoke.MinColor = Color.LightGray;
|
||||||
|
smoke.MaxColor = Color.DarkGray;
|
||||||
|
smoke.MaxParticleDistance = MainWindow.TileSize * 3;
|
||||||
|
smoke.EmissionTime = 3;
|
||||||
|
smoke.ParticleCountMin = 1;
|
||||||
|
smoke.ParticleCountMax = 2;
|
||||||
|
smoke.Size = 16;
|
||||||
|
smoke.RotationOrigin = new Microsoft.Xna.Framework.Point(MainWindow.TileSize / 2);
|
||||||
|
smoke.EaseMovement = false;
|
||||||
|
Smoke = smoke;
|
||||||
|
Object.Children.Add(Smoke);
|
||||||
|
Canvas.SetLeft(Smoke, GetParticleOrigin().X);
|
||||||
|
Canvas.SetTop(Smoke, GetParticleOrigin().Y);
|
||||||
|
smoke.Emit().ContinueWith(t => CreateSmoke());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
|
|
||||||
namespace CityGame
|
namespace CityGame
|
||||||
{
|
{
|
||||||
|
|
@ -25,5 +27,23 @@ namespace CityGame
|
||||||
{
|
{
|
||||||
return A == B;
|
return A == B;
|
||||||
}
|
}
|
||||||
|
public static Microsoft.Xna.Framework.Vector2 RotateBy(this Microsoft.Xna.Framework.Vector2 v, float angleInDegrees)
|
||||||
|
{
|
||||||
|
float radians = (float)(angleInDegrees * Math.PI / 180f);
|
||||||
|
float sin = (float)Math.Sin(radians);
|
||||||
|
float cos = (float)Math.Cos(radians);
|
||||||
|
float rotatedX = v.X * cos - v.Y * sin;
|
||||||
|
float rotatedY = v.X * sin + v.Y * cos;
|
||||||
|
return new Microsoft.Xna.Framework.Vector2(rotatedX, rotatedY);
|
||||||
|
}
|
||||||
|
public static System.Numerics.Vector2 RotateBy(this System.Numerics.Vector2 v, float angleInDegrees)
|
||||||
|
{
|
||||||
|
float radians = (float)(angleInDegrees * Math.PI / 180f);
|
||||||
|
float sin = (float)Math.Sin(radians);
|
||||||
|
float cos = (float)Math.Cos(radians);
|
||||||
|
float rotatedX = v.X * cos - v.Y * sin;
|
||||||
|
float rotatedY = v.X * sin + v.Y * cos;
|
||||||
|
return new System.Numerics.Vector2(rotatedX, rotatedY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,7 +20,12 @@ public sealed class Explosion : ParticleEmitter, IParticleHandler
|
||||||
|
|
||||||
private static Effect? _explosionShader = null;
|
private static Effect? _explosionShader = null;
|
||||||
|
|
||||||
public Color Color = Color.Yellow;
|
public Color MinColor = Color.Yellow;
|
||||||
|
public Color MaxColor = Color.OrangeRed;
|
||||||
|
public Vector2 DirectionTendency = Vector2.UnitX;
|
||||||
|
public float DirectionVariance = 180;
|
||||||
|
public int ParticleCountMin = 8;
|
||||||
|
public int ParticleCountMax = 8;
|
||||||
|
|
||||||
public Explosion()
|
public Explosion()
|
||||||
: base(Explosion.GetShader())
|
: base(Explosion.GetShader())
|
||||||
|
|
@ -41,13 +46,16 @@ public sealed class Explosion : ParticleEmitter, IParticleHandler
|
||||||
public ICollection<IParticle> Generate()
|
public ICollection<IParticle> Generate()
|
||||||
{
|
{
|
||||||
List<IParticle> particles = new List<IParticle>();
|
List<IParticle> particles = new List<IParticle>();
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < Random.Shared.Next(ParticleCountMin, ParticleCountMax + 1); i++)
|
||||||
{
|
{
|
||||||
ExplosionParticle particle = new ExplosionParticle();
|
ExplosionParticle particle = new ExplosionParticle();
|
||||||
particle.OriginalPosition = particle.Position = Vector2.Zero;
|
particle.OriginalPosition = particle.Position = Vector2.Zero;
|
||||||
|
|
||||||
Vector2 direction = new Vector2(Random.Shared.NextSingle(-1, 1), Random.Shared.NextSingle(-1,1));
|
float variance = ((float)Random.Shared.NextSingle() * 2 - 1) * DirectionVariance;
|
||||||
particle.Direction = direction;
|
Vector2 direction = DirectionTendency.RotateBy(variance);
|
||||||
|
particle.Direction = direction * Random.Shared.NextSingle();
|
||||||
|
|
||||||
|
particle.color = Color.Lerp(MinColor, MaxColor, Random.Shared.NextSingle());
|
||||||
|
|
||||||
particle.LifeTime = EmissionTime;
|
particle.LifeTime = EmissionTime;
|
||||||
particle.LifeTimeScale = Random.Shared.NextSingle(1, 1.5f);
|
particle.LifeTimeScale = Random.Shared.NextSingle(1, 1.5f);
|
||||||
|
|
@ -59,7 +67,7 @@ public sealed class Explosion : ParticleEmitter, IParticleHandler
|
||||||
|
|
||||||
return particles;
|
return particles;
|
||||||
}
|
}
|
||||||
|
public bool EaseMovement { get; set; } = true;
|
||||||
public void Move(ICollection<IParticle> particles, float deltatime, ParticleEmitter emitter)
|
public void Move(ICollection<IParticle> particles, float deltatime, ParticleEmitter emitter)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -72,7 +80,7 @@ public sealed class Explosion : ParticleEmitter, IParticleHandler
|
||||||
time = ParticleEmitter.CalculateNormalizedReversedTime(explParticle.LifeTime, this.EmissionTime);
|
time = ParticleEmitter.CalculateNormalizedReversedTime(explParticle.LifeTime, this.EmissionTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
float distanceCalc = Easing.Easing.OutExpo(time);
|
float distanceCalc = EaseMovement ? Easing.Easing.OutExpo(time) : time;
|
||||||
float distance = distanceCalc * emitter.MaxParticleDistance;
|
float distance = distanceCalc * emitter.MaxParticleDistance;
|
||||||
particle.Position = particle.OriginalPosition + particle.Direction * distance;
|
particle.Position = particle.OriginalPosition + particle.Direction * distance;
|
||||||
|
|
||||||
|
|
@ -82,10 +90,9 @@ public sealed class Explosion : ParticleEmitter, IParticleHandler
|
||||||
public void Draw(ref ParticleDrawContext context)
|
public void Draw(ref ParticleDrawContext context)
|
||||||
{
|
{
|
||||||
context.Effect.Parameters["view_projection"].SetValue(context.View * context.Projection);
|
context.Effect.Parameters["view_projection"].SetValue(context.View * context.Projection);
|
||||||
context.Effect.Parameters["color"].SetValue(this.Color.ToVector4());
|
context.Effect.Parameters["color"].SetValue(this.MinColor.ToVector4());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
context.SpriteBatch.Begin(
|
context.SpriteBatch.Begin(
|
||||||
effect: Effect,
|
effect: Effect,
|
||||||
blendState: BlendState.NonPremultiplied,
|
blendState: BlendState.NonPremultiplied,
|
||||||
|
|
@ -110,6 +117,7 @@ public sealed class Explosion : ParticleEmitter, IParticleHandler
|
||||||
if (particle is ExplosionParticle explParticle)
|
if (particle is ExplosionParticle explParticle)
|
||||||
{
|
{
|
||||||
normTime = ParticleEmitter.CalculateNormalizedReversedTime(explParticle.LifeTime, this.EmissionTime);
|
normTime = ParticleEmitter.CalculateNormalizedReversedTime(explParticle.LifeTime, this.EmissionTime);
|
||||||
|
context.Effect.Parameters["color"].SetValue(explParticle.color.ToVector4());
|
||||||
context.Effect.Parameters["noiseOffset"].SetValue(explParticle.UVOffset);
|
context.Effect.Parameters["noiseOffset"].SetValue(explParticle.UVOffset);
|
||||||
}
|
}
|
||||||
float time = Easing.Easing.OutExpo(normTime);
|
float time = Easing.Easing.OutExpo(normTime);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ public sealed class ExplosionParticle: Particle
|
||||||
public float LifeTimeScale = 1;
|
public float LifeTimeScale = 1;
|
||||||
public float LifeTime = 1;
|
public float LifeTime = 1;
|
||||||
public Vector2 UVOffset = Vector2.Zero;
|
public Vector2 UVOffset = Vector2.Zero;
|
||||||
|
public Color color;
|
||||||
|
|
||||||
public void ReduceLifeTime(float deltatime)
|
public void ReduceLifeTime(float deltatime)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ namespace CityGame.Classes.World
|
||||||
public bool RunAction(ISelectable target);
|
public bool RunAction(ISelectable target);
|
||||||
public int X();
|
public int X();
|
||||||
public int Y();
|
public int Y();
|
||||||
|
public bool IsSingleSelect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ namespace CityGame.Classes.World
|
||||||
{
|
{
|
||||||
public struct Tile : ISelectable
|
public struct Tile : ISelectable
|
||||||
{
|
{
|
||||||
|
public bool IsSingleSelect() => false;
|
||||||
public int BlockID;
|
public int BlockID;
|
||||||
public TileType Type;
|
public TileType Type;
|
||||||
public Pattern Pattern;
|
public Pattern Pattern;
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ namespace CityGame
|
||||||
public static Tile[,] Grid;
|
public static Tile[,] Grid;
|
||||||
public static ISelectable Selected;
|
public static ISelectable Selected;
|
||||||
public static OCanvas[,] ImageGrid;
|
public static OCanvas[,] ImageGrid;
|
||||||
|
public static Vector2 Wind = new Vector2(0.5f, -0.5f);
|
||||||
|
|
||||||
Canvas MainCanvas = new OCanvas();
|
Canvas MainCanvas = new OCanvas();
|
||||||
Canvas BGCanvas = new OCanvas();
|
Canvas BGCanvas = new OCanvas();
|
||||||
|
|
@ -509,7 +510,8 @@ namespace CityGame
|
||||||
ISelectable select = GetSelectableFromClick(state);
|
ISelectable select = GetSelectableFromClick(state);
|
||||||
if (select is not null)
|
if (select is not null)
|
||||||
{
|
{
|
||||||
Selected = select;
|
if (select.IsSingleSelect()) select.RunAction(select);
|
||||||
|
else Selected = select;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (state.RightButton == ButtonState.Pressed)
|
else if (state.RightButton == ButtonState.Pressed)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue