Cloud.cs
using Sandbox.UI;
using SpriteTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using static Manager;

public class Cloud : Component
{
	[Property] public SpriteRendererLayer Sprite { get; set; }

	private TimeSince _spawnTime;
	public float Lifetime { get; set; }
	public Vector2 Velocity { get; set; }
	public float Deceleration { get; set; }

	protected override void OnAwake()
	{
		base.OnAwake();

		LocalRotation = new Angles( 0f, -90f, 0f );
		LocalScale = new Vector3( Game.Random.Float( 0.65f, 0.75f ), Game.Random.Float( 0.7f, 0.9f ), 1f ) * Globals.SPRITE_SCALE;
		_spawnTime = 0f;

		if ( Game.Random.Float( 0f, 1f ) < 0.5f )
			Sprite.SpriteFlags = SpriteFlags.HorizontalFlip;

		Deceleration = 1.5f;
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();

		WorldPosition += (Vector3)Velocity * Time.Delta;
		Velocity *= (1f - Time.Delta * Deceleration);
		WorldPosition = WorldPosition.WithZ( Globals.GetZPos( WorldPosition.y ) );

		var opacity = Utils.Map( _spawnTime, 0f, 0.2f, 0f, 1f ) * Utils.Map( _spawnTime, 0f, Lifetime - 0.03f, 1f, 0f );
		Sprite.Tint = Color.White.WithAlpha( opacity );

		if ( _spawnTime > Lifetime )
		{
			Manager.Instance.RemoveCloud( this );
			GameObject.Destroy();
		}
	}
}