Skip to content

Instantly share code, notes, and snippets.

@profexorgeek
Created July 31, 2020 14:32
Show Gist options
  • Save profexorgeek/01c4fe51998b06c6a9645864e723eccc to your computer and use it in GitHub Desktop.
Save profexorgeek/01c4fe51998b06c6a9645864e723eccc to your computer and use it in GitHub Desktop.
namespace Narfox.Utilities
{
public enum EmitterScale
{
Small = 16,
Medium = 64,
Large = 256
}
public class EasyEmitter : Emitter
{
const float DefaultDrag = 3.5f;
const float VelocityRangePercent = 0.5f;
const float VelocitySizeCoefficient = 6f;
const float StartingScaleCoefficient = 0.75f;
const float ScaleRangePercent = 0.65f;
const float RotationVelocity = 0.25f;
const float PiFloat = (float)Math.PI;
private static readonly Dictionary<EmitterScale, int> ExplosionParticlesPerScale = new Dictionary<EmitterScale, int>
{
{EmitterScale.Small, 8},
{EmitterScale.Medium, 20},
{EmitterScale.Large, 35}
};
private static readonly Dictionary<EmitterScale, int> ContrailParticlesPerScale = new Dictionary<EmitterScale, int>
{
{EmitterScale.Small, 2},
{EmitterScale.Medium, 8},
{EmitterScale.Large, 12}
};
public Color Color
{
get
{
return color;
}
set
{
color = value;
EmissionSettings.Red = color.R / 255f;
EmissionSettings.Green = color.G / 255f;
EmissionSettings.Blue = color.B / 255f;
EmissionSettings.ColorOperation = FlatRedBall.Graphics.ColorOperation.Modulate;
}
}
SpriteList particles { get; set; } = new SpriteList();
Vector3 lastEmissionPosition;
EmitterScale emitterScale = EmitterScale.Medium;
float emissionDistance = 0;
Color color;
private EasyEmitter() { }
private static Vector2 GetTextureScale(AnimationChain particleChain)
{
var frame1 = particleChain[0];
return new Vector2
{
X = frame1.Texture.Width * (frame1.RightCoordinate - frame1.LeftCoordinate) / 2f,
Y = frame1.Texture.Height * (frame1.BottomCoordinate - frame1.TopCoordinate) / 2f
};
}
public static EasyEmitter BuildExplosion(
AnimationChain particleChain,
EmitterScale scale = EmitterScale.Medium,
float lifeSeconds = 1f,
float wedgeDegrees = 360f,
float scalePerSecond = 0f,
float area = 1f)
{
var emitter = new EasyEmitter();
emitter.emitterScale = scale;
var textureScale = GetTextureScale(particleChain);
var radialVelocity = (float)scale * VelocitySizeCoefficient * (1 - VelocityRangePercent);
var radialRange = (float)scale * VelocitySizeCoefficient * VelocityRangePercent;
emitter.EmissionSettings = new EmissionSettings
{
Alpha = 1f,
AlphaRate = -1f / lifeSeconds,
AnimationChain = particleChain,
Animate = true,
Drag = DefaultDrag,
ScaleX = textureScale.X * StartingScaleCoefficient,
ScaleY = textureScale.Y * StartingScaleCoefficient,
ScaleXRange = textureScale.X * ScaleRangePercent,
ScaleYRange = textureScale.Y * ScaleRangePercent,
ScaleXVelocity = scalePerSecond,
ScaleYVelocity = scalePerSecond,
RotationZ = -PiFloat,
RotationZRange = PiFloat * 2f,
RotationZVelocity = -RotationVelocity,
RotationZVelocityRange = RotationVelocity * 2f,
RadialVelocity = radialVelocity,
RadialVelocityRange = radialRange,
VelocityRangeType = RangeType.Wedge,
WedgeAngle = 0,
WedgeSpread = wedgeDegrees * (PiFloat / 180f)
};
emitter.TimedEmission = false;
emitter.SecondFrequency = 0.1f;
emitter.RemovalEvent = Emitter.RemovalEventType.Alpha0;
emitter.AreaEmission = AreaEmissionType.Rectangle;
emitter.ScaleX = area / 2f;
emitter.ScaleY = area / 2f;
emitter.NumberPerEmission = ExplosionParticlesPerScale[scale];
return emitter;
}
public static EasyEmitter BuildContrail(
AnimationChain particleChain,
EmitterScale scale = EmitterScale.Medium,
float distance = 8f,
float lifeSeconds = 3f,
float scalePerSecond = 2f,
float area = 1f)
{
var emitter = new EasyEmitter();
emitter.emitterScale = scale;
emitter.emissionDistance = distance;
var textureScale = GetTextureScale(particleChain);
emitter.EmissionSettings = new EmissionSettings
{
Alpha = 1f,
AlphaRate = -1f / lifeSeconds,
AnimationChain = particleChain,
Animate = true,
Drag = DefaultDrag,
ScaleY = textureScale.Y * StartingScaleCoefficient,
ScaleX = textureScale.X * StartingScaleCoefficient,
ScaleYRange = textureScale.Y * StartingScaleCoefficient * ScaleRangePercent,
ScaleXRange = textureScale.X * StartingScaleCoefficient * ScaleRangePercent,
ScaleYVelocity = scalePerSecond,
ScaleXVelocity = scalePerSecond,
RotationZ = -PiFloat,
RotationZRange = PiFloat * 2f,
RotationZVelocity = -0.5f,
RotationZVelocityRange = 1f,
VelocityRangeType = RangeType.Radial
};
emitter.TimedEmission = false;
emitter.RemovalEvent = Emitter.RemovalEventType.Alpha0;
emitter.AreaEmission = AreaEmissionType.Rectangle;
emitter.ScaleX = area / 2f;
emitter.ScaleY = area / 2f;
emitter.NumberPerEmission = ContrailParticlesPerScale[scale];
return emitter;
}
public new SpriteList Emit()
{
particles.Clear();
Emit(particles);
return particles;
}
public void DistanceEmit()
{
var currentPos = Parent?.Position ?? Vector3.Zero;
var vectorDelta = (currentPos - lastEmissionPosition).Length();
var elapsedDistance = Math.Abs(vectorDelta);
if (elapsedDistance >= emissionDistance)
{
this.Emit();
lastEmissionPosition = currentPos;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment