Basic Code Samples

Here’s the simplest entry point. This should give you a window and some console output:

Init

Basic Start

using Dinghy;

Engine.Run(new Engine.RunOptions(800,600,"dinghy", 
	() =>
	{
		Console.WriteLine("setup");
	}, 
	() =>
	{
		Console.WriteLine("update");
	}
));

Entity Init

Any entity can be initied like normal objects:

var s = new Sprite();

Demos

Animation

public class Animation : Scene
{
    private Resources.Texture conscriptImage;
    private AnimatedSpriteData animatedConscript;
    public override void Preload()
    {
        conscriptImage = new Resources.Texture("res/conscript.png");
        var rects = Quick.CreateTextureSlices(512, 512, 64, 64);
        animatedConscript = new AnimatedSpriteData(
            conscriptImage,
            new() { new("test", rects[..3],
                0.4f) });
    }

    public override void Create()
    {
        new AnimatedSprite(animatedConscript){X = Engine.Width/2f,Y = Engine.Height/2f};
    }
}

Collision

public class Collision : Scene
{
    Color pt = Palettes.ENDESGA[1];
    Color pointer_col = Palettes.ENDESGA[9];
    Color no_collide = Palettes.ENDESGA[7];
    Color collide = Palettes.ENDESGA[3];

    private Shape static_colliderA;
    private Shape static_colliderB;
    private Shape static_colliderC;
    private Shape pointer;
    private Shape ptA;
    private Shape ptB;
    private Shape ptC;
    public override void Create()
    {
        pointer = new Shape(pointer_col,1,1){Name = "pointer",ColliderActive = true};
        pointer.OnCollision += CollisionCallbackTest;
        static_colliderA = new Shape(no_collide)
        {
            Name = "static_colliderA",
            X = Engine.Width/2f,
            Y = Engine.Height/2f,
            ColliderActive = true
        };
        
        static_colliderB = new Shape(no_collide)
        {
            Name = "static_colliderB",
            X = Engine.Width/2f - 200f,
            Y = Engine.Height/2f - 200f,
            ColliderActive = true
        };
        
        static_colliderC = new Shape(no_collide)
        {
            Name = "static_colliderB",
            X = Engine.Width/2f + 200f,
            Y = Engine.Height/2f - 200f,
            ColliderActive = true
        };
    }

    private bool collidedThisFrameA = false;
    private bool collidedThisFrameB = false;
    private bool collidedThisFrameC = false;
    public void CollisionCallbackTest(Entity pointer, Entity other)
    {
        if (other == static_colliderA)
        {
            collidedThisFrameA = true;
        }
        if (other == static_colliderB)
        {
            collidedThisFrameB = true;
        }
        if (other == static_colliderC)
        {
            collidedThisFrameC = true;
        }
        // way to get other collision meta
        // Console.WriteLine(CollisionChecks.GetCollisionInfo(pointer,static_collider));
    }

    public override void Update(double dt)
    {
        if(ptA != null){ptA.DestroyImmediate();}
        if(ptB != null){ptB.DestroyImmediate();}
        if(ptC != null){ptC.DestroyImmediate();}
        
        static_colliderA.Rotation = (float)Engine.Time;
        static_colliderA.ScaleX = MathF.Sin((float)Engine.Time) + 2;
        static_colliderA.ScaleY = MathF.Sin((float)Engine.Time) + 2;
        static_colliderA.X = Engine.Width/2f + MathF.Cos((float)Engine.Time) * 50;
        static_colliderB.Rotation = (float)Engine.Time;
        static_colliderB.ScaleX = MathF.Sin((float)Engine.Time) + 2;
        static_colliderB.ScaleY = MathF.Sin((float)Engine.Time) + 2;
        static_colliderC.Rotation = (float)Engine.Time;
        static_colliderC.ScaleX = MathF.Sin((float)Engine.Time) + 2;
        static_colliderC.ScaleY = MathF.Sin((float)Engine.Time) + 2;
        
        Quick.MoveToMouse(pointer);
        // raw way to get collision data instead of relying on the system callbacks
        // static_collider.Color = CollisionChecks.CheckCollision(pointer, static_collider)
        //     ? collide
        //     : no_collide;
        static_colliderA.Color = collidedThisFrameA ? collide : no_collide;
        static_colliderB.Color = collidedThisFrameB ? collide : no_collide;
        static_colliderC.Color = collidedThisFrameC ? collide : no_collide;
        
        var ptsA = Dinghy.Collision.GetClosestPoints(pointer, static_colliderA);
        ptA = new Shape(pt,5,5)
        {
            X = ptsA.b.X,
            Y = ptsA.b.Y
        };
        var ptsB = Dinghy.Collision.GetClosestPoints(pointer, static_colliderB);
        ptB = new Shape(pt,5,5)
        {
            X = ptsB.b.X,
            Y = ptsB.b.Y
        };
        var ptsC = Dinghy.Collision.GetClosestPoints(pointer, static_colliderC);
        ptC = new Shape(pt,5,5)
        {
            X = ptsC.b.X,
            Y = ptsC.b.Y
        };
        
        
        collidedThisFrameA = false;
        collidedThisFrameB = false;
        collidedThisFrameC = false;
    }

    public override void Cleanup()
    {
        pointer.OnCollision -= CollisionCallbackTest;
    }
}

Grid

public class GridDemo : Scene
{
    Color shape1c = Palettes.ENDESGA[9];
    Color shape2c = Palettes.ENDESGA[8];
    List<Shape> shapes1 = new();
    List<Shape> shapes2 = new();
    Grid g = new Grid(new ((Engine.Width / 2f, Engine.Height / 2f), (0.5f, 0.5f), 10, 10, (0.5f, 0.5f), 30, 30));
    public override void Create()
    {
        foreach (var p in g.Points)
        {
            shapes1.Add(new Shape(shape1c,5,5) { X = (int)p.X, Y = (int)p.Y, ColliderActive = false, PivotX = 2.5f, PivotY = 2.5f});
            shapes2.Add(new Shape(shape2c,5,5) { X = (int)p.X, Y = (int)p.Y, ColliderActive = false, PivotX = 2.5f, PivotY = 2.5f});
        }
    }

    public override void Update(double dt)
    {
        g.SetAndApplyGridTransforms((float)Engine.Time,1f,1f);
        g.ApplyPositionsToEntites(shapes1);
        g.SetAndApplyGridTransforms(-(float)Engine.Time,MathF.Sin((float)Engine.Time) + 2,MathF.Sin((float)Engine.Time) + 2);
        g.ApplyPositionsToEntites(shapes2);
    }
}

Interaction

public class Interaction : Scene
{
    private Resources.Texture conscriptImage;
    private AnimatedSpriteData animatedConscript;
    public override void Preload()
    {
        conscriptImage = new Resources.Texture("res/conscript.png");
        var rects = Quick.CreateTextureSlices(512, 512, 64, 64);
        animatedConscript = new AnimatedSpriteData(
            conscriptImage,
            new() { new("test", rects[..3],
                0.4f) });
    }

    private AnimatedSprite e;
    public override void Create()
    {
        e = new AnimatedSprite(animatedConscript){X = Engine.Width/2f,Y = Engine.Height/2f, PivotX = 32,PivotY = 32};
        Console.WriteLine("subbing");
        InputSystem.Events.Key.Down += KeyDownListener;
    }

    void KeyDownListener(Key key, List<Modifiers> mods)
    {
        (float dx, float dy) v = key switch {
            Key.LEFT => (-1f, 0),
            Key.RIGHT => (1f, 0),
            Key.UP => (0, -1f),
            Key.DOWN => (0, 1f),
            _ => (0, 0)
        };
        e.DX += v.dx;
        e.DY += v.dy;
    }

    public override void Cleanup()
    {
	    Console.WriteLine("unsubbing");
	    InputSystem.Events.Key.Down -= KeyDownListener;
    }
}

Particle System

public class ParticleSystem : Scene
{
    // Color startColor = Palettes.ENDESGA[4];
    private Color startColor = new Color(1.0f, 1.0f, 0f, 0f);
    private Color endColor = new Color(1.0f, 0.0f, 1.0f, 0f);
    // Color endColor = Palettes.ENDESGA[16];
    ParticleEmitter emitter;
    public override void Create()
    {
        emitter = new ParticleEmitter(
            new(100000, 100, new ParticleEmitterComponent.ParticleConfig()
            {
                Color = new Transition<Color>(startColor,endColor,Easing.Option.EaseInOutExpo)
            }))
        {
            X = 200,
            Y = 200
        };
    }

    public override void Update(double time)
    {
        MoveToMouse(emitter);
        DrawEditGUIForObject("emitter",ref emitter);
        // var rand = RandUnitCircle();
        // emitter.Config.particleConfig.DX.StartValue = rand.x * 4;
        // emitter.Config.particleConfig.DY.StartValue = rand.y * 4;
    }
}

Physics

public class Physics : Scene
{
    private Resources.Texture conscriptImage;
    private SpriteData conscript;
    public override void Preload()
    {
        conscriptImage = new Resources.Texture("res/conscript.png");
        
        conscript = new(conscriptImage, new Rect(0,0,64,64));
        VoltConfig.AreaMassRatio = 0.000007f;
    }
    
    Dictionary<Sprite, VoltBody> bods = new Dictionary<Sprite, VoltBody>();
    public override void Create()
    {
        var bot = new Vector2(0, Engine.Height / 2f);
        var poly = Engine.PhysicsWorld.CreatePolygonWorldSpace(
            new Vector2[]
            {
                new Vector2(0, Engine.Height),
                new Vector2(0, Engine.Height + 100),
                new Vector2(Engine.Width, Engine.Height + 100),
                new Vector2(Engine.Width, Engine.Height)
            }, 0f);
        var bod = Engine.PhysicsWorld.CreateStaticBody(bot, 0f, new[] { poly });
        bod.Set(bot,0f);

    }

    double timer = 0;
    public override void Update(double dt)
    {
        timer += dt;
        if (timer > 0.1)
        {
            var startPos = new Vector2(InputSystem.MouseX, InputSystem.MouseY);
            var a = new Sprite(conscript) {
                X = (int)startPos.x,
                Y = (int)startPos.y,
                ColliderActive = false
            };
            var poly = Engine.PhysicsWorld.CreatePolygonWorldSpace(
                new Vector2[]
                {
                    new Vector2(startPos.x, startPos.y),
                    new Vector2(startPos.x, startPos.y + 64),
                    new Vector2(startPos.x + 64, startPos.y + 64),
                    new Vector2(startPos.x + 64, startPos.y)
                },1f);
            var bod = Engine.PhysicsWorld.CreateDynamicBody(startPos, 0f, new []{poly});
            bods.Add(a,bod);
            // bod.AddForce(new Vector2(0,9.8f));
            // a.SetVelocity(-2,0);
            timer = 0;
        }

        foreach (var b in bods)
        {
            b.Value.AddForce(new Vector2(0,9.8f));
            b.Key.SetPosition((int)b.Value.Position.x,(int)b.Value.Position.y,b.Value.Angle,b.Key.ScaleX,b.Key.ScaleY,b.Key.PivotX,b.Key.PivotY);
        }
    }
}

Physics Shape

public class PhysicsShape : Scene
{
    public override void Preload()
    {
        VoltConfig.AreaMassRatio = 0.000007f;
    }
    
    Dictionary<Shape, VoltBody> bods = new Dictionary<Shape, VoltBody>();
    public override void Create()
    {
        var bot = new Vector2(0, Engine.Height / 2f);
        var poly = Engine.PhysicsWorld.CreatePolygonWorldSpace(
            new Vector2[]
            {
                new Vector2(0, Engine.Height),
                new Vector2(0, Engine.Height + 100),
                new Vector2(Engine.Width, Engine.Height + 100),
                new Vector2(Engine.Width, Engine.Height)
            }, 0f);
        var bod = Engine.PhysicsWorld.CreateStaticBody(bot, 0f, new[] { poly });
        bod.Set(bot,0f);

    }

    double timer = 0;
    public override void Update(double dt)
    {
        timer += dt;
        if (timer > 0.1)
        {
            var startPos = new Vector2(InputSystem.MouseX, InputSystem.MouseY);
            var a = new Shape(new Color(Palettes.ENDESGA[Quick.Random.Next(Palettes.ENDESGA.Count)])) {
                X = (int)startPos.x,
                Y = (int)startPos.y,
                ColliderActive = false
            };
            var poly = Engine.PhysicsWorld.CreatePolygonWorldSpace(
                new Vector2[]
                {
                    new Vector2(startPos.x, startPos.y),
                    new Vector2(startPos.x, startPos.y + 32),
                    new Vector2(startPos.x + 32, startPos.y + 32),
                    new Vector2(startPos.x + 32, startPos.y)
                },1f);
            var bod = Engine.PhysicsWorld.CreateDynamicBody(startPos, 0f, new []{poly});
            bods.Add(a,bod);
            timer = 0;
        }

        foreach (var b in bods)
        {
            b.Value.AddForce(new Vector2(0,9.8f));
            b.Key.SetPosition((int)b.Value.Position.x,(int)b.Value.Position.y,b.Value.Angle,b.Key.ScaleX,b.Key.ScaleY,b.Key.PivotX,b.Key.PivotY);
        }
    }
}

Simple Update

public class SimpleUpdate : Scene
{
    private Resources.Texture conscriptImage;
    private SpriteData conscriptFrame0;
    public override void Preload()
    {
        conscriptImage = new Resources.Texture("res/conscript.png");
        
        conscriptFrame0 = new(conscriptImage, new Rect(0,0,64,64));
    }

    Sprite e;
    Point startPos = (0,0);
    public override void Create()
    {
        startPos = ((Engine.Width / 2f) - 32, (Engine.Height / 2f) - 32);
        e = new Sprite(conscriptFrame0)
        {
            X = (int)startPos.X,
            Y = (int)startPos.Y,
            PivotX = 32,
            PivotY = 32
        };
    }

    public override void Update(double dt)
    {
        e.X = (int)startPos.X + (int)(Math.Sin(Engine.Time) * 100);
        e.Rotation = (float)Engine.Time;
        var scale = (Math.Cos(Engine.Time) * 2);
        e.ScaleX = (float)scale;
        e.ScaleY = (float)scale;
    }
}

Texture

public class Texture : Scene
{
    public override void Create()
    {
        var tex = Res.Assets.conscript.CreateSprite();
        tex.X = Engine.Width / 2f;
        tex.Y = Engine.Height / 2f;
        tex.PivotX = 256;
        tex.PivotY = 256;
    }
}

Texture Frame

public class TextureFrame : Scene
{
    private Resources.Texture conscriptImage;
    private SpriteData conscriptFrame0;
    public override void Preload()
    {
        conscriptImage = new Resources.Texture("res/conscript.png");
        
        conscriptFrame0 = new(conscriptImage, new Rect(0,0,64,64));
    }

    public override void Create()
    {
        new Sprite(conscriptFrame0){X = Engine.Width/2f,Y = Engine.Height/2f,PivotX = 32,PivotY = 32};
    }
}