DiamondDebris.Smoke.cs
using System;
using System.Collections.Generic;
using Sandbox;
namespace Diamonds;
public sealed partial class DiamondDebris
{
/// <summary>Presentation-only dust: deliberately has no physics body or collision shape.</summary>
public sealed class SmokePuff
{
public Vector2 Position { get; internal set; }
public float Age { get; internal set; }
public float Lifetime { get; internal set; }
public float Radius { get; internal set; }
internal Vector2 Velocity;
}
const int MaxSmoke = 192;
readonly List<SmokePuff> smoke = new();
public IReadOnlyList<SmokePuff> Smoke => smoke;
void EmitSmoke( Particle chip, bool crushed )
{
int count = crushed ? random.Next( 2, 5 ) : random.Next( 1, 3 );
var velocity = chip.Body.Velocity;
var position = chip.Position;
var inherited = new Vector2( velocity.x, velocity.y );
inherited *= 0.1f * MathF.Min( 1, 60 / MathF.Max( 1, inherited.Length ) );
for ( int i = 0; i < count; i++ )
{
if ( smoke.Count >= MaxSmoke ) smoke.RemoveAt( 0 );
float angle = Range( -MathF.PI, MathF.PI );
var direction = new Vector2( MathF.Cos( angle ), MathF.Sin( angle ) );
smoke.Add( new SmokePuff
{
Position = position + direction * Range( 0, chip.Radius * 0.4f ),
Velocity = direction * Range( 12, 30 ) + new Vector2( 0, -Range( 14, 25 ) ) + inherited,
Radius = Range( 2, 4 ), Lifetime = Range( 0.45f, 0.75f )
} );
}
}
void UpdateSmoke( float delta )
{
for ( int i = smoke.Count - 1; i >= 0; i-- )
{
var puff = smoke[i];
puff.Age += delta;
if ( puff.Age >= puff.Lifetime ) { smoke.RemoveAt( i ); continue; }
puff.Velocity = (puff.Velocity + new Vector2( 0, -8 * delta )) * MathF.Exp( -1.8f * delta );
puff.Position += puff.Velocity * delta;
}
}
}