using System.Collections.Generic; using System.Drawing; using Amphora; using Azimuth; using Blacklight.Core; using Blacklight.Core.Cameras; using Blacklight.Core.Drawables; using Konis.Blacklight; namespace Konis.Testbed { /// /// A particle world and what it takes to draw it with Blacklight. /// public class ParticleDemo { private const SpriteBatch.Varying WrittenColumns = SpriteBatch.Varying.TintColor | SpriteBatch.Varying.Transform; private readonly WindowHandle window; private readonly Camera camera; private readonly Scene scene = new Scene(); private readonly Cel cel = new Cel(); private readonly SpriteSheet sheet; private readonly SpriteSource source; // One set for each emitter, since a batch reads its set in place until the cel is next cleared. private readonly List entrySets = new List(); /// /// Makes a demo that draws into , which must already be bound. /// public ParticleDemo(WindowHandle window, Camera camera, Rand random) { this.window = window; this.camera = camera; World = new ParticleWorld(random); scene.Cels.Add(cel); sheet = SpriteSheet.Create( window, SoftDisc.Build(), spriteSize: new Size(SoftDisc.Side, SoftDisc.Side), borderSize: 0); source = sheet.Frame(new Point(0, 0)); } /// /// Gets the world the demo runs. /// public ParticleWorld World { get; } /// /// Gets or sets which of a spawn makes. /// public int EffectIndex { get; set; } /// /// Gets or sets how the world's three dimensions land on the screen. /// public ViewProjection Projection { get; set; } = ViewProjection.Dimetric2To1; /// /// Starts the chosen effect at . /// public Emitter Spawn(Vector3 position, float preWarmSeconds) { return World.Spawn(Effects.All[EffectIndex].Def, position, preWarmSeconds); } /// /// Draws one complete frame. /// public void Draw() { // Only FrameReset empties the batch pools, so the reset/queue/submit triple has to stay together. window.FrameReset(); cel.Clear(); for (int i = 0; i < World.Count; i++) { var emitter = (StandardEmitter)World[i]; if (i == entrySets.Count) { entrySets.Add(new SpriteBatch.EntrySet()); } int count = ParticleSpriteWriter.Write(emitter, Projection, source, entrySets[i]); if (count == 0) { continue; } SpriteBatch batch = cel.NewSpriteBatchView(entrySets[i], count, WrittenColumns); batch.Texture = sheet.Texture; if (Effects.IsAdditive(emitter.Def)) { batch.Additiveness = 1; } cel.AddEntity(batch, AffineMatrix.Identity); } window.DrawScene(scene, camera); window.SubmitDrawCalls(); } } }