Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ImDrawList coding party - deadline Nov 30, 2020! #3606

Open
ocornut opened this issue Nov 19, 2020 · 82 comments
Open

ImDrawList coding party - deadline Nov 30, 2020! #3606

ocornut opened this issue Nov 19, 2020 · 82 comments

Comments

@ocornut
Copy link
Owner

ocornut commented Nov 19, 2020

ImDrawList coding party!

  • create small visual effects
  • 1024 bytes of source code
  • 320x180 output
  • only use dear imgui's crappy low-level shape drawing api

Two days ago I thought:
"It'd be fun to organize a contest for writing special effects using the ImDrawList api, with a constraint on source code size. May be fun to see what people can come up with using shape/vector-based api (quite different from a pixel-shading function). Would you participate?"

It's by no mean a great api but it has served many well, to draw custom widgets etc, let's get it some extra love..

Here's a testbed imdrawlist_party.cpp which you can paste in your application or any dear imgui example:
https://gist.github.com/ocornut/51367cc7dfd2c41d607bb0acfa6caf66

Rules:

  • Your source file fx.inl must be <= 1024 bytes.
  • Effect should be reasonably portable (not relying on specific render backend callback)
  • OK to use preprocessor define or other tricks as long as they are reasonably portable.
  • Included are: math.h, imgui.h, imgui_internal.h with ImVec2 maths operators
  • The effect should not use ImGui:: functions, only use ImDrawList facilities.
  • Canvas ratio is expected to be 16/9, canvas size expected to be 320 by 180.
  • For simplicity we assume you can encode a color as 0xAAGGBBRR instead of using the IM_COL32() macro, therefore IMGUI_USE_BGRA_PACKED_COLOR config option is not supported!

Prizes:

  • This is mostly for fun so please feel free to make multiple submissions or tweak them as you feel. No pressure. Mostly, I'm supposed to work and ship tables this or next week so hey why I am doing this?!
  • We could possibly include some of them in imgui_demo if they strike a good balance of cool and educational. If we end up doing that we'll rework code to be neat and proper for a demo (aka not densely packed into 1024 characters).

Function signature:

void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 mouse, float t);
     d : draw list
     a : upper-left corner
     b : lower-right corner
    sz : size (== b - a)
 mouse : x,y = mouse position (normalized so 0,0 over 'a'; 1,1 is over 'b', not clamped)
         z,w = left/right button held. <-1.0f not pressed, 0.0f just pressed, >0.0f time held.
    t  : time

If not using a given parameter, you can omit its name in your function to save a few characters.

To record gif files you can use ShareX https://getsharex.com or ScreenToGif https://www.screentogif.com/

Let's get started! You can post on this thread, on discord or on twitter!

Known issues

  • ImDrawList polygon stroking with thick lines looks broken on acute angle, good luck!!
@ocornut
Copy link
Owner Author

ocornut commented Nov 19, 2020

Here are some examples I made to get you started:

Circles

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4 mouse, float t)
{
    for (int n = 0; n < (1.0f + sinf(t * 5.7f)) * 40.0f; n++)
        d->AddCircle(V2(a.x + sz.x * 0.5f, a.y + sz.y * 0.5f), sz.y * (0.01f + n * 0.03f), 
            IM_COL32(255, 140 - n * 4, n * 3, 255));
}

drawlist fx 03

Squares

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
    float sx = 1.f / 16.f;
    float sy = 1.f / 9.f;
    for (float ty = 0.0f; ty < 1.0f; ty += sy)
        for (float tx = 0.0f; tx < 1.0f; tx += sx)
        {
            V2 c((tx + 0.5f * sx), (ty + 0.5f * sy));
            float k = 0.45f;
            d->AddRectFilled(
                V2(a.x + (c.x - k * sx) * sz.x, a.y + (c.y - k * sy) * sz.y),
                V2(a.x + (c.x + k * sx) * sz.x, a.y + (c.y + k * sy) * sz.y),
                IM_COL32(ty * 200, tx * 255, 100, 255));
        }
}

unknown

Curves

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t0)
{
    for (float t = t0; t < t0 + 1.0f; t += 1.0f / 100.0f)
    {
        V2 cp0(a.x, b.y);
        V2 cp1(b);
        float ts = t - t0;
        cp0.x += (0.4f + sin(t) * 0.3f) * sz.x;
        cp0.y -= (0.5f + cos(ts * ts) * 0.4f) * sz.y;
        cp1.x -= (0.4f + cos(t) * 0.4f) * sz.x;
        cp1.y -= (0.5f + sin(ts * t) * 0.3f) * sz.y;
        d->AddBezierCurve(V2(a.x, b.y), cp0, cp1, b, IM_COL32(100 + ts*150, 255 - ts*150, 60, ts * 200), 5.0f);
    }
}

drawlist fx 04b

Waves

#define V2 ImVec2
#define ARFM d->AddRectFilledMultiColor
#define ACF d->AddCircleFilled
#define CH s.SetCurrentChannel
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
    ARFM(a, b, 0xFF1E1E1E, 0xFF1E281E, 0xFF1E1E5A, 0xFF321E78);
    ARFM(a, V2(b.x, a.y + sz.y*0.4f), 0x1EFFDCFF, 0x14FFFFDC, 0x001E1E5A, 0x00321E78);
    auto s = d->_Splitter;
    s.Split(d, 2);
    for (int n = 0; n < 256; n++)
    {
        V2 c(a.x + n / 256.f * sz.x, b.y + 20 - cos(t - 0.1f * n / 2) * 10 + cos(t) * 5);
        float r(40 + sin(t + n / 2) * 40);
        CH(d, 0);
        ACF(c, r + 1, 0x80FFFFFF);
        CH(d, 1);
        ACF(c, r, IM_COL32(255, n / 2, n / 8, 255));
    }
    s.Merge(d);
    d->AddRect(a, b, IM_COL32(128, 128, 128, 100));
}

drawlist fx 02

@kudaba
Copy link
Contributor

kudaba commented Nov 19, 2020

Thunder Storm

#define min(x,y) ((x)<(y)?x:y)
#define wh(a) ImColor(1.f,1.f,1.f,a)
void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec2, float t)
{
    static float fl;
    if ((rand() % 500) == 0) fl = t;
    if ((t-fl) > 0)
    {
        auto ft = 0.25f;
        d->AddRectFilled(a, b, wh((ft - (t - fl)) / ft));
    }

    for (int i = 0; i < 2000; ++i) {
        unsigned h = ImGui::GetID(d+i + int(t/4));
        auto f = fmodf(t + fmodf(h / 777.f, 99), 99);
        auto tx = h % (int)sz.x;
        auto ty = h % (int)sz.y;
        if (f < 1) {
            auto py = ty - 1000 * (1 - f);
            d->AddLine({ a.x + tx, a.y + py }, { a.x + tx, a.y + min(py + 10,ty) }, (ImU32)-1);
        }
        else if (f < 1.2f)
            d->AddCircle({ a.x + tx, a.y + ty }, (f - 1) * 10 + h % 5, wh(1-(f-1)*5.f));
    }
}

imgui_storm

@ocornut
Copy link
Owner Author

ocornut commented Nov 19, 2020

The Matrix effect, slowly been shaving off spaces and making the code uglier and uglier

//v1.1
#define V2 ImVec2
void FX(ImDrawList*d,V2 a,V2,V2 sz,ImVec4,float t)
{
  static struct{int y,h,c; float t,s;} m[40]={0};
  static int S=0x1234;
  static float t0=t;
  float ZI=t*.07f,Z=ZI+1.f;
  for(int x=0;x<40;x++)
  {
    auto& M=m[x];
    int i=x>=15&&x<25;
    if(M.s==0.f||M.y>16)
    {
      M.h = (t<7.f||i)*((int)(2+t*.5f) + S%(int)(6+(t*0.3f)));
      M.y = (M.s==0.f)*-(S%15)-M.h;
      M.c += S;
      M.s = (5+(S%14))*(.01f-t*.001f);
      if(t>5.f&&i)
      {
        M.c = (340003872375972UL>>(x*5-75))&31;
        M.h = i?(x!=19):0;
      }
    }
    if((M.t-=t-t0)<0.f)
    {
      if(t<6.f||!i||M.y!=6)
        M.y++;
      M.t += M.s;
    }
    char c=64|M.c%42;
    for(int j=0; j<M.h; j++,c=64|(c^M.c+M.h^j)%42)
      for(int f=(j+1==M.h)?13:4+(M.c&1);f--;)
        d->AddText(0, 13*(i?Z:-Z), V2(a.x-(sz.x*.5f*ZI)+x*8*Z+sin(j+t*f), a.y-(sz.y*.5f*ZI)+(M.y+j)*13*Z+cos(x*f-t)), 0x3c68bb5b, &c, &c+1);
    S|=((S&1)^((S&8)>>2))<<16;
    S>>=1;
  }
  t0 = t;
}

fx matrix 2

@ocornut ocornut changed the title ImDrawList party! ImDrawList party - deadline Nov 30, 2020! Nov 19, 2020
@ocornut ocornut changed the title ImDrawList party - deadline Nov 30, 2020! ImDrawList coding party - deadline Nov 30, 2020! Nov 19, 2020
@Fuzznip
Copy link

Fuzznip commented Nov 19, 2020

Tiny Loading Screen!

Had a bunch of fun trying to get this as small I could, managed to get it just under 600 bytes for now.

b0bapW4Ez9

#define V ImVec2
#define R d->AddRectFilled
#define C(x) IM_COL32((sin(x) + 1) * 255 / 2, (cos(x) + 1) * 255 / 2, 99, 255)
#include <set>
void FX(ImDrawList* d, V a, V b, V s, ImVec4, float t) {
  static auto z = 0.f;
  if (t > z + 2) z += 2;
  auto c = C(z + 2);
  R(a, b, C(z));
  for (auto B = b.x, i = 0.f, o = s.y / 8; i < 8; ++i, B = b.x) {
    if (auto w = (i / 7) * .2f, x = std::max(t - z - w, 0.f); t - z < w + 1)
      B = a.x + (x < .5 ? 8 * x * x * x * x : std::min(1 - pow(-2 * x + 2, 4.f) / 2, 1.f)) * s.x;
    R(V(a.x, a.y + o * i), V(B, a.y + o * i + o), c);
  }
}

@sugrob9000
Copy link
Contributor

sugrob9000 commented Nov 19, 2020

Quicksort visualization.

#define V2 ImVec2
#include <vector>
#include <array>
using namespace std;
int N = 64, S, J;
#define V vector<int>
V v = [] {
	V r;
	for (; J < N; J++) r.push_back(rand() % 180);
	return r;
}();
vector<array<int,4>> st { { 0, N-1, 0, 0} };
#define A st.back()[0]
#define B st.back()[1]
#define I st.back()[2]
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4,float t)
{
	float bs = s.x / N, y, c;
	for (int i = 0; i < N; i++) {
		y=a.y+v[i];
		c=70+v[i];
		d->AddRectFilled(V2(a.x+bs*i,y),V2(a.x+bs*(i+1),b.y),IM_COL32(c,255-c,255,255));
	}
	d->AddText(a, -1u, "Quicksort");
	if (st.empty()) return;
	d->AddRect(V2(a.x+bs*A,a.y),V2(a.x+bs*(B+1),b.y),0xFF00FF00,8,ImDrawCornerFlags_Top,2);
	switch (S) {
	case 0:case 5: if(A>=B)st.pop_back(),S+=3;else I=J=A,S++;break;
	case 1:case 6:
		if(v[J]>v[B])swap(v[I],v[J]),I++;
		if(++J>B)swap(v[I],v[B]),S++;
		break;
	case 2:case 7:st.push_back({A,I-1,A,3});S=0;break;
	case 3:st.push_back({I+1,B,A,8});S=5;break;
	case 8:S = st.back()[3]; st.pop_back();
	}
}

sort
Blobs.

#define V2 ImVec2
void FX (ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
	int N = 25;
	float sp = s.y / N, y, st = sin(t) * 0.5 + 0.5,
	      r[3] = { 1500, 1087 + 200 * st, 1650 },
	      ctr[3][2] = { { 150, 140 }, { s.x * m.x, s.y * m.y },
		      { 40 + 200 * st, 73 + 20*sin(st * 5) } };
	for (int i = 0; i < N; i++) {
		y = a.y + sp*(i+.5);
		for (int x = a.x; x <= b.x; x += 2) {
			float D = 0, o = 255;
			for (int k = 0; k < 3; k++)
				D += r[k]/(pow(x-a.x-ctr[k][0], 2) + pow(y-a.y-ctr[k][1], 2));
			if (D < 1) continue;
			if (D>2.5) D = 2.5;
			if (D < 1.15) o /= 2;
			d->AddLine(V2(x, y), V2(x+2, y), IM_COL32(239, 129, 19, o), D + sin(2.3 * t + 0.3 * i));
		}
	}
}

o
3D cube.

#define V2 ImVec2
void FX (ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
	a.x += s.x/2, a.y += s.y / 2;
	float S = sin(m.x), C = cos(m.x), x = 50, y, z = (m.y * 2 - 1) * x;
	float v[8][3] { { x, x, z+x }, { x, -x, z+x }, { -x, -x, z+x }, { -x, x, z+x },
			{ x, x, z-x }, { x, -x, z-x }, { -x, -x, z-x }, { -x, x, z-x } };
	for (int i = 0; i < 8; i++) {
		x = v[i][0] * C - v[i][1] * S;
		y = v[i][0] * S + v[i][1] * C + 120;
		z = v[i][2];
		v[i][0] = x / y * 50;
		v[i][1] = z / y * 50;
		v[i][2] = y;
	}
#define L(A,B) z = 500 / (v[A][2] + v[B][2]); \
	d->AddLine(V2(a.x+v[A][0],a.y+v[A][1]),V2(a.x+v[B][0],a.y+v[B][1]),-1u,z);
	L(0, 1) L(1, 2) L(2, 3) L(0, 3)
	L(4, 5) L(5, 6) L(6, 7) L(4, 7)
	L(0, 4) L(1, 5) L(2, 6) L(3, 7)
}

cubes
Real-time visualization of the interweb blogosphere.

#define V2 ImVec2
#include <vector>
int N = 300;
auto v = [] {
	std::vector<std::pair<V2,V2>>r(N);
	for (auto&p:r)
		p.second = p.first = V2(rand() % 320, rand() % 180);
	return r;
}();
float l2 (V2 x) { return x.x*x.x + x.y*x.y; }
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4,float t)
{
	float D, T;
	for (auto&p:v) {
		D = sqrt(l2(p.first - p.second));
		if (D > 0) p.first += (p.second - p.first) / D;
		if (D < 4) p.second = V2(rand() % 320, rand() % 180);
	}
	for (int i = 0; i < N; i++) {
		for (int j = i+1; j < N; j++) {
			D = l2(v[i].first - v[j].first);
			T = l2((v[i].first + v[j].first) - s) / 200;
			if (T > 255) T = 255;
			if (D < 400) d->AddLine(a+v[i].first, a+v[j].first, IM_COL32(T, 255-T, 255, 70), 2);
		}
	}
}

interwebs

@ShironekoBen
Copy link
Collaborator

Here's my attempt at some abstract fireworks... with about four bytes to spare. The code has ended up pretty unreadable as a result, sadly.

#define V ImVec2
#define R rand()
#define I int
#define F float
#define S ((F)R/32767)
#define T(d,b,e)p[j].d=(b*(j&1^j>>1?1:-1))+(e*((j>1)?1:-1))+c.d+a.d;
#define X(a)I a=128+(R&127);
struct P {F x,y,vx,vy,a;I l,s,f,d;};P p[8192]={0};
void A(V o, I f){P t;t.x=o.x;t.y=o.y;t.vx=S*3-1.5;t.vy=S*2.5-(f?4:1);t.l=R%(f?50:99);t.s=R;t.f=f;for(I j=0;j<9;j++){t.d=j;t.a=1-(F)j/9;for(I i=0;i<8192;i++)if(!p[i].l){p[i]=t;break;}}}
void FX(ImDrawList*d,V a,V b,V sz,V mn,F t0){I g=R;for(I i=200;i;--i)d->AddLine(V(a.x,a.y+i),V(b.x,a.y+i),IM_COL32(0,0,i,255));I e=0;for(I i=0;i<8192;i++){P&c=p[i];if(c.l){if(c.d)c.d--;else{srand(c.s);c.x+=c.vx;c.y+=c.vy;c.vy+=.04;c.l-=(c.vy>0)?1:0;F s=(S*3+.1)*(c.f+1);F n=(t0*(c.l<0?0:1))+(i*S*2.5-1.5);F sa=sin(n)*s;F ca=cos(n)*s;V p[4];for(I j=0;j<4;j++){T(x,sa,ca);T(y,ca,-sa);}X(r)X(g)X(b)d->AddConvexPolyFilled(p,c.f?4:3,IM_COL32(r,g,b,(c.f?255:c.l)*c.a));if(!c.l&&c.f&&c.a==1){I l=R%40+15;for(I j=0;j<l;j++)A(V(c.x,c.y),0);}}if(c.f)e++;}}
srand(g);if(e<512)A(V(S*420-50,200),1);}

Fireworks

@heretique
Copy link

Old school plasma.

ImDrawList_Party_Plasma

#define V2 ImVec2
#define S sinf
#define C cosf
#define I int
#define F float
#define CL(x,l,h) (((x)>(h))?(h):(((x)<(l))?(l):(x)))
#define PI 3.1415926535
#define CO(c,b) (int(c*255)<<b)
void FX(ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
    t*=3;
    F ix=s.x/320;
    F iy=s.y/180;
    F sz=s.x / 15;
    for (F x=a.x;x<b.x;x+=ix)
        for (F y=a.y;y<b.y;y+=iy){
            F v=0;
            v+=S((x/sz+t));
            v+=S((y/sz+t)/2.0f);
            v+=S((x/sz+y/sz+t)/2.0f);
            F cx=x/sz/10+0.3*S(t/3.0);
            F cy=y/sz/10+0.3f*C(t/2.0);
            v+=S(sqrt(100*(cx*cx+cy*cy+1))+t);
            v=CL(v/2, 0, 1);
            F r=S(v*PI)*.5f+.5f;
            F g=S(v*PI+PI/3)*.5f+.5f;
            F b=S(v*PI+PI)*.5f+.5f;
            d->AddQuadFilled({x,y},{x+ix,y},{x+ix,y+iy},{x,y+iy},0xff000000|CO(b,16)|CO(g,8)|CO(r,0));
        }
}

@sugrob9000
Copy link
Contributor

sugrob9000 commented Nov 20, 2020

Guitar for strumming. Unfortunately, requires that ImGuiWindowFlags_NoMove be set for the window in the testbed to work correctly. Using InvisibleButton instead of Dummy also works.

#define V2 ImVec2
#define C1 0xA7A830FF
#define C2 0x775839FF
float amp[6], ml;
int pk;
void FX(ImDrawList* d, V2 a, V2 b, V2 s, ImVec4 m, float t)
{
	if (m.z > -1)
		pk |= 2;
	m.y *= s.y; m.x *= s.x;
	m.y += a.y; m.x += a.x;
	float st = sin(10*t), th, y, w;
	d->AddRectFilledMultiColor(V2(a.x, a.y+40), V2(b.x, b.y-40), C1, C1, C2, C2);
	for (float i = a.x + 10, j = 20; i < b.x; i += (j += 10))
		d->AddRectFilled(V2(i, a.y+38), V2(i + 8, b.y-38), 0xFF888888, 8);
	for (int i = 0; i < 6; i++) {
		y = a.y + 48 + i * 16.6; th = 4-i*.5f; w = 1;
		int N = 10;
		for (int j = 0; j < N; j++) {
			float x = a.x + j * s.x / N, k = (w *= -1) * amp[i] * st;
			d->AddBezierCurve(V2(x,y+k),V2(x+10,y+k),V2(x+s.x/N-10,y-k),V2(x+s.x/N,y-k),-1u,th);
		}
		amp[i] *= 0.9;
		if (pk == 3) {
			float A=ml, B=m.y;
			if((A<=y&&B>y)||(A>=y&&B<y))amp[i]+=A-B;
		}
	}
	ml = m.y;
	if (pk >>= 1) d->AddTriangleFilled(V2(m.x, m.y), V2(m.x-15, m.y-15), V2(m.x+10, m.y-25), 0xFF0000FF);
}

guitar

@42yeah
Copy link

42yeah commented Nov 20, 2020

Complementary colors I guess? I have to optimize the hell out of it to get it under 1K, the code looks so ugly now :'( But it's quite fun!

#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define fract(x) (abs(x-floor(x)))
#define rand(x,se) (fract(sin(x)*se))
#define eps 1e-3
#define V2 ImVec2
#define C 10000.0f
float mix(float a,float b,float v) {return a+(b-a)*v;}float ss(float a,float b,float v) {return mix(a,b,3.0f*v*v-2.0f*v*v*v);}float perlin(float v,float se) {v=v*0.7f+eps;float f=floor(v);float s=fract(v);float a=rand(f,se);float b=rand(f+1.0f,se);return ss(a,b,s);}float perlin_d(float v,float se) {v *= 2.0f;float f=floor(v);float s=fract(v);float a=rand(f,se);float b=rand(f+1.0f,se);return ss(a,b,s);}void FX(ImDrawList* d,ImVec2 a,ImVec2 b,ImVec2 sz,ImVec4 mouse,float t) {t *= 0.3f;float sa[]={255.0f,0.0f};float sb[]={125.0f,130.0f};float sc[]={0.0f,255.0f};for(int i=0;i<2;i++) {for(int x=0;x<sz.x;x++) {float p=0.5f+rand(1.0f,(C-sa[i]));float bt=perlin(x/sz.x+t*p,C-sa[i])*sz.y;float tp=perlin(x/sz.x+t*p,C-sb[i])*sz.y;float h=tp-bt;d->AddRectFilled(V2(a.x+x,a.y+bt),V2(a.x+x+1,a.y+bt+h),IM_COL32(sa[i],sb[i],sc[i],200));}}}

result

@ocornut
Copy link
Owner Author

ocornut commented Nov 20, 2020

Unfortunately, requires that ImGuiWindowFlags_NoMove be set for the window in the testbed to work correctly.

I updated the test bed today (to 0.22) to use InvisibleButton() instead of Dummy() for the canvas, so it catches inputs.

Beautiful submissions everyone!

@kudaba
Copy link
Contributor

kudaba commented Nov 20, 2020

Snake Game (781 bytes)

#define v2 ImVec2
#define px(v,c) d->AddRectFilled(a+v*2,a+v*2+v2(2,2),c);
#define fr(v,x) for(int v=0;v<x;++v)
#define eq(l,r) l.x==r.x&l.y==r.y
#define kd(k) ImGui::IsKeyDown(ImGui::GetKeyIndex(k))
v2 sn[160*90]={{20,20}};
int ln=0,tg=4;
float lf;
v2 dr(1,0);
v2 fd(99,45);
void FX(ImDrawList* d, v2 a, v2 b, v2 sz, v2, float t)
{
	if (t-lf>0.033f){
		lf=t;
		if (ln<tg){ln++;sn[ln]=sn[ln-1];}
		else fr(x,ln)sn[x]=sn[x+1];
		sn[ln]+=dr;
		bool e=sn[ln].x<0|sn[ln].x>159|sn[ln].y<0|sn[ln].y>89;
		fr(x,ln-1)e|=eq(sn[x],sn[ln]);
		if(e)ln=0,tg=4,sn[0]={20,20};
		if(eq(sn[ln],fd))tg+=4,fd={rand()%150+5.f,rand()%80+5.f};
		if(kd(1))dr={-1,0};
		if(kd(2))dr={1,0};
		if(kd(3))dr={0,-1};
		if(kd(4))dr={0,1};
	}

	fr(x,ln+1)px(sn[x],-1);
	px(fd,-256);
}

imgui_snake

@kudaba
Copy link
Contributor

kudaba commented Nov 20, 2020

Mosaic. It wasn't what I was trying to do, but ended up in a neat place.

#define v2 ImVec2
#define wh(a) ImColor(1.f,1.f,1.f,a)
#define px(v,c) d->AddRectFilled(a+v*2,a+v*2+v2(2,2),c);
#define fr(v,x) for(int v=0;v<x;++v)
#define frc(x) ((x)-int(x))
#define hash(x) (srand(x),ImLerp(rand()/32767.f,rand()/32767.f,0.5f))
#define noise(x) ImLerp(hash(x),hash(x+1),frc(x))
void FX(ImDrawList* d, v2 a, v2 b, v2 sz, v2 mm, float t)
{
	fr(x,160)fr(y,90){
		auto rx=x-80;
		auto ry=y-45;
		auto an=ImAtan2(rx,ry);an=an<0?M_PI*2+an:an;
		auto len=(rx*rx+ry*ry+0.1f)+t*4;
		auto n0 = noise(an);
		auto n1 = noise(len);
		auto al= n0+n1;
		px(v2(x,y),wh(al));
	}
}

imgui_noise

@r-lyeh
Copy link

r-lyeh commented Nov 20, 2020

Hershey vectorial font! 3.8 KiB. I have not stripped the ASCII chars in the font to make the code fit under 1KiB, bc I wanted to make something useful as well. Sorry for breaking the rules! :D

void Hershey(ImDrawList* d, ImVec2 pos, ImVec2 sca, ImVec2 old, char *s) {
 static const char *fnt[] = {
 "AQ","IKFVFH@@FCEBFAGBFC","FQEVEO@@MVMO","LVLZE:@@RZK:@@EMSM@@DGRG","[UIZI=@@MZ"
 "M=@@RSPUMVIVFUDSDQEOFNHMNKPJQIRGRDPBMAIAFBDD","`YVVDA@@IVKTKRJPHOFODQDSEUGVIVK"
 "UNTQTTUVV@@RHPGOEOCQASAUBVDVFTHRH","c[XMXNWOVOUNTLRGPDNBLAHAFBECDEDGEIFJMNNOOQ"
 "OSNULVJUISIQJNLKQDSBUAWAXBXC","HKFTEUFVGUGSFQEP","KOLZJXHUFQELEHFCH?J<L:","KOD"
 "ZFXHUJQKLKHJCH?F<D:","IQIVIJ@@DSNM@@NSDM","F[NSNA@@EJWJ","IKGBFAEBFCGBG@F>E=",\
 "C[EJWJ","FKFCEBFAGBFC","CWUZC:","RUJVGUERDMDJEEGBJALAOBQERJRMQROULVJV","EUGRIS"
 "LVLA","OUEQERFTGUIVMVOUPTQRQPPNNKDARA","PUFVQVKNNNPMQLRIRGQDOBLAIAFBECDE","GUN"
 "VDHSH@@NVNA","RUPVFVEMFNIOLOONQLRIRGQDOBLAIAFBECDE","XUQSPUMVKVHUFREMEHFDHBKAL"
 "AOBQDRGRHQKOMLNKNHMFKEH","FURVHA@@DVRV","^UIVFUESEQFOHNLMOLQJRHREQCPBMAIAFBECD"
 "EDHEJGLJMNNPOQQQSPUMVIV","XUQOPLNJKIJIGJELDODPESGUJVKVNUPSQOQJPENBKAIAFBED","L"
 "KFOENFMGNFO@@FCEBFAGBFC","OKFOENFMGNFO@@GBFAEBFCGBG@F>E=","DYUSEJUA","F[EMWM@@"
 "EGWG","DYESUJEA","USDQDRETFUHVLVNUOTPRPPONNMJKJH@@JCIBJAKBJC","x\\SNRPPQMQKPJO"
 "ILIIJGLFOFQGRI@@MQKOJLJIKGLF@@SQRIRGTFVFXHYKYMXPWRUTSUPVMVJUHTFREPDMDJEGFEHCJB"
 "MAPASBUCVD@@TQSISGTF","ISJVBA@@JVRA@@EHOH","XVEVEA@@EVNVQURTSRSPRNQMNL@@ELNLQK"
 "RJSHSERCQBNAEA","SVSQRSPUNVJVHUFSEQDNDIEFFDHBJANAPBRDSF","PVEVEA@@EVLVOUQSRQSN"
 "SIRFQDOBLAEA","LTEVEA@@EVRV@@ELML@@EARA","ISEVEA@@EVRV@@ELML","WVSQRSPUNVJVHUF"
 "SEQDNDIEFFDHBJANAPBRDSFSI@@NISI","IWEVEA@@SVSA@@ELSL","CIEVEA","KQMVMFLCKBIAGA"
 "EBDCCFCH","IVEVEA@@SVEH@@JMSA","FREVEA@@EAQA","LYEVEA@@EVMA@@UVMA@@UVUA","IWEV"
 "EA@@EVSA@@SVSA","VWJVHUFSEQDNDIEFFDHBJANAPBRDSFTITNSQRSPUNVJV","NVEVEA@@EVNVQU"
 "RTSRSORMQLNKEK","YWJVHUFSEQDNDIEFFDHBJANAPBRDSFTITNSQRSPUNVJV@@MES?","QVEVEA@@"
 "EVNVQURTSRSPRNQMNLEL@@LLSA","UURSPUMVIVFUDSDQEOFNHMNKPJQIRGRDPBMAIAFBDD","FQIV"
 "IA@@BVPV","KWEVEGFDHBKAMAPBRDSGSV","FSBVJA@@RVJA","LYCVHA@@MVHA@@MVRA@@WVRA",""
 "FUDVRA@@RVDA","GSBVJLJA@@RVJL","IURVDA@@DVRV@@DARA","LOEZE:@@FZF:@@EZLZ@@E:L:",
 "COAVO>","LOJZJ:@@KZK:@@DZKZ@@D:K:","KQGPISKP@@DMIRNM@@IRIA","CQA?Q?","HKGVFUES"
 "EQFPGQFR","RTPOPA@@PLNNLOIOGNELDIDGEDGBIALANBPD","RTEVEA@@ELGNIOLONNPLQIQGPDNB"
 "LAIAGBED","OSPLNNLOIOGNELDIDGEDGBIALANBPD","RTPVPA@@PLNNLOIOGNELDIDGEDGBIALANB"
 "PD","RSDIPIPKOMNNLOIOGNELDIDGEDGBIALANBPD","IMKVIVGUFRFA@@COJO","WTPOP?O<N;L:I"
 ":G;@@PLNNLOIOGNELDIDGEDGBIALANBPD","KTEVEA@@EKHNJOMOONPKPA","IIDVEUFVEWDV@@EOE"
 "A","LKFVGUHVGWFV@@GOG>F;D:B:","IREVEA@@OOEE@@IIPA","CIEVEA","S_EOEA@@EKHNJOMOO"
 "NPKPA@@PKSNUOXOZN[K[A","KTEOEA@@EKHNJOMOONPKPA","RTIOGNELDIDGEDGBIALANBPDQGQIP"
 "LNNLOIO","RTEOE:@@ELGNIOLONNPLQIQGPDNBLAIAGBED","RTPOP:@@PLNNLOIOGNELDIDGEDGBI"
 "ALANBPD","INEOEA@@EIFLHNJOMO","RROLNNKOHOENDLEJGILHNGOEODNBKAHAEBDD","IMFVFEGB"
 "IAKA@@COJO","KTEOEEFBHAKAMBPE@@POPA","FQCOIA@@OOIA","LWDOHA@@LOHA@@LOPA@@TOPA",
 "FRDOOA@@OODA","JQCOIA@@OOIAG=E;C:B:","IROODA@@DOOO@@DAOA","hOJZHYGXFVFTGRHQIOI"
 "MGK@@HYGWGUHSIRJPJNILEJIHJFJDIBHAG?G=H;@@GIIGIEHCGBF@F>G<H;J:","CIEZE:","hOFZH"
 "YIXJVJTIRHQGOGMIK@@HYIWIUHSGRFPFNGLKJGHFFFDGBHAI?I=H;@@IIGGGEHCIBJ@J>I<H;F:",""
 "XYDGDIELGMIMKLOIQHSHUIVK@@DIEKGLILKKOHQGSGUHVKVM" };
 for( char c, *glyph; (c = *s++, glyph = (char*)fnt[c - 32], c > 0 && c < 127); ) {
  if( c != '\n' && c != '\r' ) {
   if( c > 32 ) for( int pen = 0, i = 0; i < (glyph[0] - 65); i++ ) {
    int x = glyph[2 + i*2 + 0] - 65, y = glyph[2 + i*2 + 1] - 65;
    if( x == -1 && y == -1 ) pen = 0; else {
     ImVec2 next = ImVec2(pos.x+sca.x*x, pos.y-sca.y*y);
     if( !pen ) pen = 1; else d->AddLine(old, next, 0.9*(ImU32)-1);
     old = next;
    }
   }
   pos.x += sca.x * (glyph[1] - 65);
  }
 }
}
void FX(ImDrawList* d, ImVec2 a, ImVec2 b, ImVec2 sz, ImVec4 mouse, float t) {
 ImVec2 pos(a.x,((a+b)/2).y), sca(1,sin(t*5)+1+0.5f);
 char str[128]; sprintf(str, "Hello imgui! %5.2fs", t);
 Hershey(d, pos, sca, ImVec2(), str);
}

GIF 11-20-2020 10-58-19 PM

@scemino
Copy link

scemino commented Nov 20, 2020

Ugly Doom Fire
doomfire

#define V2 ImVec2
#define W 64
#define H 48
#define S 0x07
#define T 0x1F
#define U 0x0F
#define I int
#define F float
I w=0,P[]={S,S,S,T,S,S,0x2F,U,S,0x47,U,S,0x57,0x17,S,0x67,T,S,0x77,T,S,0x8F,0x27,S,0x9F,0x2F,S,0xAF,0x3F,S,0xBF,0x47,S,0xC7,0x47,S,0xDF,0x4F,S,0xDF,0x57,S,0xDF,0x57,S,0xD7,0x5F,S,0xD7,0x5F,S,0xD7,0x67,U,0xCF,0x6F,U,0xCF,0x77,U,0xCF,0x7F,U,0xCF,0x87,0x17,0xC7,0x87,0x17,0xC7,0x8F,0x17,0xC7,0x97,T,0xBF,0x9F,T,0xBF,0x9F,T,0xFF,0xFF,0xFF};
char i[W*H];
void FX(ImDrawList *d,V2 a,V2 b,V2 sz,ImVec4,F t){if(!w){memset(i,0,W*H);memset(i+(H-1)*W,27,W);w=1;}for(I x=0;x<W;x++){for(I y=1;y<H;y++){I j=y*W+x,p=i[j];if(!p)i[j-W]=0;else{I r=I(3.f*rand()/RAND_MAX),d=j-r+1;i[d-W]=p-(r&1);}}};I j=0;F sx=1.f/W,sy=1.f/H,k=0.45f,ty=0;for(I y=0;y<H;y++,ty+=sy){F tx=0;for(I x=0;x<W;x++,tx+=sx){V2 c((tx+.5f*sx),(ty+.5f*sy));I *z=P+i[j++]*3;d->AddRectFilled(V2(a.x+(c.x-k*sx)*sz.x,a.y+(c.y-k*sy)*sz.y),V2(a.x+(c.x+k*sx)*sz.x,a.y+(c.y+k*sy)*sz.y),IM_COL32(z[0],z[1],z[2],255));}}}

@scemino
Copy link

scemino commented Nov 21, 2020

This one (The Business Card Raytracer from Paul Heckbert) is too big 1 510 bytes 😢 but still fun
aek

#define V2 ImVec2
#define op operator
#define rt return
typedef int i;typedef float f;struct v{f x,y,z;v op+(v r){rt v(x+r.x,y+r.y,z+r.z);}v op*(f r){rt v(x*r,y*r,z*r);}f op%(v r){rt x*r.x+y*r.y+z*r.z;}v(){}v op^(v r){rt v(y*r.z-z*r.y,z*r.x-x*r.z,x*r.y-y*r.x);}v(f a,f b,f c){x=a;y=b;z=c;}v op!(){rt*this*(1/sqrt(*this%*this));}};i G[]={247570,280596,280600,249748,18578,18577,231184,16,16};f R(){rt(f)rand()/RAND_MAX;}i T(v o,v d,f&t,v&n){t=1e9;i m=0;f p=-o.z/d.z;if(.01<p)t=p,n=v(0,0,1),m=1;for(i k=19;k--;)for(i j=9;j--;)if(G[j]&1<<k){v p=o+v(-k,0,-j-4);f b=p%d,c=p%p-1,q=b*b-c;if(q>0){f s=-b-sqrt(q);if(s<t&&s>.01)t=s,n=!(p+d*t),m=2;}}rt m;}v S(v o,v d){f t;v n;i m=T(o,d,t,n);if(!m)rt v(.7,.6,1)*pow(1-d.z,4);v h=o+d*t,l=!(v(9+R(),9+R(),16)+h*-1),r=d+n*(n%d*-2);f b=l%n;if(b<0||T(h,l,t,n))b=0;f p=pow(l%r*(b>0),99);if(m&1){h=h*.2;rt((i)(ceil(h.x)+ceil(h.y))&1?v(3,1,1):v(3,3,3))*(b*.2+.1);}rt v(p,p,p)+S(h,r)*.5;}
v img[512*512];i y=512;void FX(ImDrawList*d,V2 z,V2,V2 sz,ImVec4,f){v g=!v(-6,-16,0),a=!(v(0,0,1)^g)*.002,b=!(g^a)*.002,c=(a+b)*-256+g;f sx=1.f/512.f;f sy=1.f/512.f;if(y){y--;for(i x=512;x--;){v p(13,13,13);for(i r=64;r--;){v t=a*(R()-.5)*99+b*(R()-.5)*99;p=S(v(17,16,8)+t,!(t*-1+(a*(R()+x)+b*(y+R())+c)*16))*3.5+p;}img[y*512+x]=p;}}v*img2=img;f k=0.45f;for(f ty=1.0f;ty;ty-=sy)for(f tx=1.0f;tx;tx-=sx){V2 u((tx+0.5f*sx),(ty+0.5f*sy));v q=*img2++;d->AddRectFilled(V2(z.x+(u.x-k*sx)*sz.x,z.y+(u.y-k*sy)*sz.y),V2(z.x+(u.x+k*sx)*sz.x,z.y+(u.y+k*sy)*sz.y),IM_COL32((i)q.x,(i)q.y,(i)q.z,255));}}

@CedricGuillemet
Copy link
Contributor

tribute to https://tixy.land/ 473 bytes
ezgif com-gif-maker

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
   int i =0;
   for (int y = 0;y <= sz.y *0.2;y++)
   {
      for (int x = 0;x<=sz.x * 0.2;x++, i++)
      {
         //float v = cos(t * cos(i * 2)) * cos(i * cos(x * 2));
         float v = tan(t * cos(i * 2))* sin(i * cos(x * 2));
         v = ImClamp(v, -1.f, 1.f);
         d->AddCircleFilled(V2(x * 10 + a.x,y * 10 + a.x), 5 * fabsf(v), (v>0.f)?0xFFFFFFFF:0xFF0000FF, 12);
      }
   }
}

@CedricGuillemet
Copy link
Contributor

Yet another entry because it's a lot of fun!
I tried to emulate DOF with alpha and bigger disks.
ezgif com-gif-maker (1)

800 bytes

#define V2 ImVec2
#define F float
F k;
int i{};
F r() { return F(rand() / 32768.f) * 2.f - 1.f; };
struct P {F x,y,z,a,b,c;void A(){x+=a*k;y+=b*k;z+=c*k;
F ng{0.008f};z-=5.f;F xp=x*cosf(ng)-z*sinf(ng);F zp=x*sinf(ng)+z*cosf(ng);
x=xp;z=zp+5.f;a-=x*k+r()*k;b-=y*k+r()*k;c-=(z-5.0f)*k+r()*k;}};
P p[64];
void FX(ImDrawList* d, V2 o, V2 b, V2 sz, ImVec4, F t)
{int j{};
if (!i) {i=1;for (P&a:p){a={r(),r(),r()+5.f,r(),r(),r() };}}
for (P&a:p){
if (a.z<0.001) continue;
V2 s((a.x/a.z)*sz.x*2.f+sz.x*0.5f+o.x,(a.y/a.z)*sz.y*2.f+sz.y*0.5f+o.y);
int x=(j++)%16;
k=cosf((j/64.f)*3.14592f)*0.002f+0.002f;
F dist=fabsf(a.z-5.f)/2.5f,sc=(10.f+dist*100.f)/a.z;
int tr=int(ImMin(dist*128.f,128.f)+127)<<24;
ImColor col=ImColor::HSV(k*9.f+0.06f,0.8f,1.f,1.f-sqrtf(dist));
d->AddCircleFilled(s,sc,col,12);a.A();
}}

@heretique
Copy link

heretique commented Nov 21, 2020

A Breakout/Arkanoid type of game implementation in 1014 bytes. (Control paddle with mouse, use right-click to reset)

ImDrawList_Party_Breakout

#define V2 ImVec2
#define I int
#define F float
#define B bool
#define T static
#define W 320
#define H 180
#define FR(i,m) for(I i=0;i<m;++i)
#define C 0xffffffff
struct B2{V2 l,h;B a=1;B in(V2 p){return(p.x>l.x&&p.x<h.x)&&(p.y>l.y&&p.y<h.y);}};
void FX(ImDrawList* d,V2 a,V2 b,V2 s,ImVec4 m,float t)
{T B re=1;T F cx,cy,r,vx,vy;T F lt=t;T F dt=0;T F bw=W/10;T F bh=H/12;T B2 br[60];T B2 p{{0,b.y-5},{0,b.y}};if(re){cx=a.x+W/2;cy=a.y+H-8;r=3;vx=-1;vy=-3;FR(i,6)FR(j,10){B2& b=br[j+i*10];b.a=1;b.l={a.x+j*bw,a.y+i*bh};b.h={a.x+(j+1)*bw,a.y+(i+1)*bh};}re=0;}FR(i,60){B2& b=br[i];if(!b.a)continue;if(!b.in({cx,cy}))continue;b.a=0;F ol=cx-b.l.x;F or=b.h.x-cx;F ot=cy-b.l.y;F ob=b.h.y-cy;F ox=min(ol,or);F oy=min(ot,ob);B lo=ol<ob;B to=ot<ob;ox<oy?vx=-vx:vy=-vy;}dt=t-lt;lt=t;p.l.x=a.x+m.x*s.x-20;p.h.x=p.l.x+40;if(p.in({cx,cy}))vy=-vy;FR(i,60){if(br[i].a)d->AddRect(br[i].l,br[i].h,C);}d->AddRect(p.l,p.h,C);d->AddCircle({cx,cy},r,C);cx+=vx*dt*30;cy+=vy*dt*30;if(cx<a.x||cx>b.x)vx=-vx;if(cy<a.y)vy=-vy;if (!m.w)re=1;}

Update:
@ocornut 's suggestion on Twitter made we want to push it a little further and here it is in 1024 bytes with colors

ImDrawList_Party_Breakout2

using V=ImVec2;using I=int;using F=float;using B=bool;
#define T static
#define W 320
#define H 180
#define FR(i,m) for(I i=0;i<m;++i)
#define A d->AddRectFilled
struct B2{V l,h;B a=1;I c=~0;B in(V p){return(p.x>l.x&&p.x<h.x)&&(p.y>l.y&&p.y<h.y);}};
void FX(ImDrawList* d,V a,V b,V s,ImVec4 m,float t){T B re=1;T F cx,cy,r,vx,vy;T F lt=t;T F dt=0;T F bw=W/10;T F bh=H/12;T B2 br[60];T B2 p{{0,b.y-5},{0,b.y}};if(re){cx=a.x+W/2;cy=a.y+H-8;r=3;vx=-1;vy=-3;FR(i,6)FR(j,10){B2& b=br[j+i*10];b.a=1;b.l={a.x+j*bw,a.y+i*bh};b.h={a.x+(j+1)*bw,a.y+(i+1)*bh};b.c=255<<24|rand();}re=0;}FR(i,60){B2& b=br[i];if(!b.a)continue;if(!b.in({cx,cy}))continue;b.a=0;F ol=cx-b.l.x;F or=b.h.x-cx;F ot=cy-b.l.y;F ob=b.h.y-cy;F ox=min(ol,or);F oy=min(ot,ob);B lo=ol<ob;B to=ot<ob;ox<oy?vx=-vx:vy=-vy;}dt=t-lt;lt=t;p.l.x=a.x+m.x*s.x-20;p.h.x=p.l.x+40;if(p.in({cx,cy}))vy=-vy;FR(i,60){B2& b=br[i];if(b.a)A(b.l,b.h,b.c);}A(p.l,p.h,~0);d->AddCircleFilled({cx,cy},r,~0);cx+=vx*dt*30;cy+=vy*dt*30;if(cx<a.x||cx>b.x)vx=-vx;if(cy<a.y)vy=-vy;if (!m.w)re=1;}

@PossiblyAShrub
Copy link

Came across this by accident. I think it looks quite cool.

imdrawlist-party-1

521 bytes

#define V ImVec2
#define CF d->AddCircleFilled
#define RAND(a) (float)rand()/(float)(RAND_MAX/a)
void FX(ImDrawList*d,V a,V b,V s,ImVec4 m,float t) {
 static bool o = true;
 static V bs[1000];
 if(o){
  o=false;
  for(int i=0;i<1000;++i){
   float g=RAND(IM_PI/2)+(IM_PI/4);
   float r=RAND(50)+5;
   bs[i]=V(g,r);
  }
 }
 for(int i=0;i<1000;++i){
  float
   g=bs[i].x,
   r=bs[i].y;
  r+=sin(t+i)*100;
  CF(V(r*cos(g),r*sin(g))+(s/2+a)+V(r*cos(t),0),i%2+1,IM_COL32(r+100,50,fabs(r)+100,200));
 }
}

@Organic-Code
Copy link
Contributor

Organic-Code commented Nov 21, 2020

I did a poor man’s tetris
I’d like top put some more features (like, detection for when the game is lost, for example [mostly done]), but I’m at 1021 994 1024 bytes, so I can’t really add more

By the way, I also took the liberty to change from mouse_data.y = (io.MousePos.y - p1.y) / size.y; to mouse_data.y = (io.MousePos.y - p0.y) / size.y; in the gist, so that it corresponds to the specs on the OP

In case anyone wonders about the controls : the piece follows the mouse’s y coordinate, mouse left click rotates it, and right click accelerates it.

tetris
disclaimer: colors were modified to squeeze some space for end-game detection

source code (1024 bytes)
#define F(a,b)for(I a=b;a--;)
#define S(a,b)s(c[a],c[b]);
#define I int
#define V ImVec2
#define L(w,z) d->AddLine(a+V(p,y)*8,a+V(p+w,y+z)*8,g-1^~0);
#define P(x,y) a+V(x,y)*8,a+V(x+1,y+1)*8
#define R(x,y,c) d->AddRectFilled(P(x,y),c);
I g=1;I pc[][9]={{1,1,1},{1,1,0,1,1},{1,1,1,0,1},{1,1,1,1},{1,1,1,0,0,1},{1,1,0,0,1,1},{0,1,1,1,1}};I*c=0;I p=0;I f=0;I T[41][21];void s(I&a,I&b){I d=a;a=b;b=d;}void FX(ImDrawList * d,V a,V,V,ImVec4 m,float t){F(i,21)T[40][i]=1;if(!p)F(i,40){c=pc[(I)t%7];I s=-21;F(j,21)s+=T[i][j];if(!s){F(j,i)F(k,21)T[j+1][k]=T[j][k];++i;}}if(!m.z){S(0,6)S(1,5)S(2,8)S(3,7)S(3,5)S(0,8)}I y=m.y*23-1.;if(y<0){if(!(c[0]|c[1]|c[2]))F(i,3){c[i]=c[i+3];c[i+3]=c[i+6];c[i+6]=0;}y=0;}if(y>18){if(!(c[6]|c[7]|c[8]))F(i,3){c[i+6]=c[i+3];c[i+3]=c[i];c[i]=0;}y=18;}p+=m.w>0|!(++f%8);F(i,3)F(j,3)if(c[j*3+i]&T[p+i+1][y+j]){F(k,3)F(l,3)T[p+k][y+l]|=g&c[l*3+k];p=0;}F(i,21)g&=!T[0][i];F(i,40)F(j,21)if(T[i][j])R(i,j,g?~0xFDA:~0)if(g)F(i,3)F(j,3)if(c[j*3+i])R(i+p,j+y,~0xFF14)L(3,0)L(0,3)p+=3;y+=3;L(0,-3)L(-3,0)p-=3;}
expanded source code (3409 bytes)
#include <algorithm>
#include <numeric>

static int board[41][21];
static int pieces_list[][9] = {
		{1, 1, 1,
		 0, 0, 0,
		 0, 0, 0},
		{0, 1, 1,
		 0, 1, 1,
		 0, 0, 0},
		{1, 1, 1,
		 0, 1, 0,
		 0, 0, 0},
		{1, 1, 1,
		 1, 0, 0,
		 0, 0, 0},
		{1, 1, 1,
		 0, 0, 1,
		 0, 0, 0},
		{1, 1, 0,
		 0, 1, 1,
		 0, 0, 0},
		{0, 1, 1,
		 1, 1, 0,
		 0, 0, 0}};

static int * current_piece = nullptr;
static int piece_pos = 0;
static int frame_count = 0;
static int game_ongoing = 1;

void FX(ImDrawList * d, ImVec2 a, ImVec2, ImVec2, ImVec4 mouse, float t) {
	++frame_count;

	std::fill_n(board[40], 21, 1);// could be done only once

	if (piece_pos == 0) {
		for (int i = 39; i >= 0; --i) {
			current_piece = pieces_list[static_cast<int>(t) % 7];// selecting new piece (such randomness)

			if (std::accumulate(board[i], board[i] + 21, 0) == 21) {// checking for full line
				for (int j = i; j > 0; --j) {
					for (int k = 0; k < 21; ++k) {
						board[j + 1][k] = board[j][k];
					}
				}
				++i;// rollback
			}
		}
	}

	if (mouse.z == 0.f) {// rotating piece
		int copy[9]{};
		std::copy(current_piece, current_piece + 9, copy);
		current_piece[0] = copy[2];
		current_piece[1] = copy[5];
		current_piece[2] = copy[8];
		current_piece[3] = copy[1];
		current_piece[5] = copy[7];
		current_piece[6] = copy[0];
		current_piece[7] = copy[3];
		current_piece[8] = copy[6];
	}

	int y = mouse.y * 23 - 1.;// piece y coord
	if (y < 0) {
		if (!current_piece[0] && !current_piece[1] && !current_piece[2]) {
			for (int i = 0; i < 3; ++i) {
				current_piece[i] = current_piece[i + 3];
				current_piece[i + 3] = current_piece[i + 6];
				current_piece[i + 6] = 0;
			}
		}
		y = 0;

	} else if (y > 18) {
		if (!current_piece[6] && !current_piece[7] && !current_piece[8]) {
			for (int i = 0; i < 3; ++i) {
				current_piece[i + 6] = current_piece[i + 3];
				current_piece[i + 3] = current_piece[i];
				current_piece[i] = 0;
			}
		}
		y = 18;
	}

	if (mouse.w > 0 || frame_count % 8 == 0) {
		++piece_pos;
	}

	bool collided = false;
	for (int i = 0; i < 3; ++i) {
		for (int j = 0; j < 3; ++j) {

			if (current_piece[j * 3 + i] && board[piece_pos + i + 1][y + j]) {
				collided = true;
			}
		}
	}

	if (collided) {
		for (int i = 0; i < 3; ++i) {
			for (int j = 0; j < 3; ++j) {
				if (game_ongoing && current_piece[j * 3 + i]) {
					board[piece_pos + i][y + j] = 1;
				}
			}
		}
		piece_pos = 0;
	}

	if (std::accumulate(board[0], board[0] + 21, 0) != 0) {
		// game lost
		game_ongoing = 0;
	}


	for (int i = 0; i < 40; ++i) {
		for (int j = 0; j < 21; ++j) {
			if (board[i][j]) {
				d->AddRectFilled(a + ImVec2(i, j) * 8, a + ImVec2(i + 1, j + 1) * 8, game_ongoing ? IM_COL32(37,240,255,255) : IM_COL32_WHITE);
			}
		}
	}

	if (game_ongoing) {
		for (int i = 0; i < 3; ++i) {
			for (int j = 0; j < 3; ++j) {
				if (current_piece[j * 3 + i]) {
					d->AddRectFilled(a + ImVec2(i + piece_pos, j + y) * 8, a + ImVec2(i + piece_pos + 1, j + y + 1) * 8, IM_COL32(235,0,255,255));
				}
			}
		}

		d->AddLine(a + ImVec2(piece_pos, y) * 8, a + ImVec2(piece_pos + 3, y) * 8, IM_COL32_WHITE);
		d->AddLine(a + ImVec2(piece_pos, y) * 8, a + ImVec2(piece_pos, y + 3) * 8, IM_COL32_WHITE);
		d->AddLine(a + ImVec2(piece_pos + 3, y + 3) * 8, a + ImVec2(piece_pos + 3, y) * 8, IM_COL32_WHITE);
		d->AddLine(a + ImVec2(piece_pos + 3, y + 3) * 8, a + ImVec2(piece_pos, y + 3) * 8, IM_COL32_WHITE);
	}
}

@pinam45
Copy link

pinam45 commented Nov 21, 2020

I made a Mandelbrot set visualization with mouse-centered zoom/de-zoom:

Mandelbrot

I also took the liberty to change from mouse_data.y = (io.MousePos.y - p1.y) / size.y; to mouse_data.y = (io.MousePos.y - p0.y) / size.y; in the gist, so that it corresponds to the specs on the OP

Source code (1024 bytes)
#include <complex>

ImVec2 shift(-2.12,-0.9);
float scale = 0.01;
float zoom_factor = 0.9;
size_t max_iter = 32;

void FX(ImDrawList* d, ImVec2 a, ImVec2, ImVec2 sz, ImVec4 m, float)
{
	if((m.x >= 0 && m.x <= 1 && m.y >= 0 && m.y <= 1) && (m.z > 0 || m.w > 0))
	{
		float zf = m.z > 0 ? zoom_factor : 1 / zoom_factor;
		shift.x -= (m.x * sz.x * scale * (zf - 1));
		shift.y -= (m.y * sz.y * scale * (zf - 1));
		scale *= zf;
	}

	for(size_t x = 0; x < sz.x; ++x)
	{
		for (size_t y = 0; y < sz.y; ++y)
		{
			std::complex<double> c(shift.x + x /(sz.x-1.0)*(sz.x * scale), shift.y + y /(sz.y-1.0)*(sz.y * scale)), z;

			size_t iter;
			for (iter = 0; iter < max_iter && std::abs(z) < 2.0; ++iter)
				z = z * z + c;

			double v = std::log(iter) / std::log(max_iter - 1);
			if(iter < max_iter)
				d->AddRectFilled(ImVec2(a.x+ x,a.y+ y), ImVec2(a.x+ x +1,a.y+ y +1), IM_COL32((v*255), 255-(v*255), 255, 255));
			else
				d->AddRectFilled(ImVec2(a.x+ x,a.y+ y), ImVec2(a.x+ x +1,a.y+ y +1), IM_COL32(0, 0,0, 255));
		}
	}
}

@CedricGuillemet
Copy link
Contributor

Mandatory tunnel 971 bytes

#define V2 ImVec2
#define F float
V2 conv(V2 v, F z, V2 sz, V2 o){return V2((v.x/z)*sz.x*5.f+sz.x*0.5f,(v.y/z)*sz.y*5.f+sz.y*0.5f)+o;}
V2 R(V2 v, F ng){ng*=0.1f;return V2(v.x*cosf(ng)-v.y*sinf(ng),v.x*sinf(ng)+v.y*cosf(ng));}
void FX(ImDrawList* d, V2 o, V2 b, V2 sz, ImVec4, F t){d->AddRectFilled(o,b,0xFF000000,0);t*=4;
for (int i = 0; i < 20; i++){
F z=21.-i-(t-floorf(t))*2.,ng=-t*2.1+z,ot0=-t+z*0.2,ot1=-t+(z+1.)*0.2,os=0.3;
V2 s[]={V2(cosf((t+z)*0.1)*0.2+1.,sinf((t+z)*0.1)*0.2+1.),V2(cosf((t+z+1.)*0.1)*0.2+1.,sinf((t+z+1.)*0.1)*0.2+1.)};
V2 of[]={V2(cosf(ot0)*os,sinf(ot0)*os),V2(cosf(ot1)*os,sinf(ot1)*os)};
V2 p[]={V2(-1,-1),V2(1,-1),V2(1,1),V2(-1,1)};
ImVec2 pts[8];int j;
for (j=0;j<8;j++){int n = (j/4);pts[j]=conv(R(p[j%4]*s[n]+of[n],ng+n),(z+n)*2.,sz,o);}
for (j=0;j<4;j++){V2 q[4]={pts[j],pts[(j+1)%4],pts[((j+1)%4)+4],pts[j+4]};
F it=(((i&1)?0.5:0.6)+j*0.05)*((21.-z)/21.);
d->AddConvexPolyFilled(q,4,ImColor::HSV(0.6+sinf(t*0.03)*0.5,1,sqrtf(it)));
}}}

ezgif com-gif-maker (2)

@Fahien
Copy link

Fahien commented Nov 22, 2020

Awesome stuff so far.

I started by looking at some of the first entries, and decided to play with circles. So I went on googling for something to find some inspiration, and I though it would be cool to replicate this: Black and White Minimal Circles
by Colin Saunders
.

Anyway, while playing with the drawing algorithm something went wrong and I ended up with an out of control Death Star laser-shooting randomly onto the galaxy!

Death Star - 926 bytes

#define V2 ImVec2
#define CR(o,r,c) d->AddCircle(o,r,c)
#define LN(a,b,c) d->AddLine(a,b,c)
#define FORI(n) for(int i=0;i<n;++i)
void FX(ImDrawList*d,V2 a,V2 b,V2 sz,ImVec4,float t){
	static float pr{t}, tm{};
	static auto st=[](){ImVector<V2> v; v.resize(512); FORI(512) v[i]=V2(rand()%480,rand()%270); return v;}();
	V2 hsz{sz/2}, o{a+hsz}, dir{sinf(tm),cosf(tm)}, c, sf;
	float dt{}, rad{hsz.y*0.7}, r;
	int cnt{rad/2}, sh{!(int(t)%2)}, inc;
	FORI(512) CR(st[i],1,0xFF333333);
	if(!sh) dt=t-pr,tm+=dt;
	pr=t;
	ImU32 BL{0xFF000000}, WH{0xFFFFFFFF}, G{0xFF00FF00};
	FORI(cnt){r=rad-i,inc=i; c={o.x+inc*dir.x,o.y+inc*dir.y}; CR(c,r,WH);}
	V2 la{o.x-rad,o.y}, lb{o.x+rad,o.y};
	LN(la,lb,BL);
	FORI(cnt){r=rad-(cnt+i), inc=(cnt-i); c={o.x+inc*dir.x,o.y+inc*dir.y}; CR(c,r,WH);}
	if(sh){la=o+dir*rad/8; lb=o+dir*hsz.x*2; sf={3*sinf(t*1024),3*cosf(t*1024)}; LN(la,lb,G); LN(la+sf,lb+sf,G); LN(la-sf,lb-sf,G);}
}

death-star

@pinam45
Copy link

pinam45 commented Nov 22, 2020

Following the Mandelbrot set visualization, this time I made a Julia sets visualization:

Julia

Inspired by this Wikipedia gif, the Julia sets represented are generated by

z^{2} + 0.7885 e^{ia}

where a ranges from 0 to 2π.

Source code (1024 bytes)
#include <complex>
#define C(r,g,b) IM_COL32(255*(r), 255*(g), 255*(b), 255)
size_t max_iter = 256;
float color_f = 48.0;
float speed_f = 2.0;

ImU32 to_color(float v)
{
	v = 1.f - std::log(v * color_f+1) / std::log(color_f+1);
	size_t p = v * 5.0;
	double g = (v * 5.0 - p);
	ImU32 colors[] = {C(1, 0, 1-g),C(1, g, 0),C(1-g, 1, 0),C(0, 1, g),C(0, 1-g, 1),C(0, 0, 1),};
	return colors[p];
}
void FX(ImDrawList* d, ImVec2 a, ImVec2, ImVec2 sz, ImVec4, float t)
{
	for (size_t x = 0; x < sz.x; ++x)
		for (size_t y = 0; y < sz.y; ++y)
		{
			std::complex<double> z(-2.1+x/(sz.x-1.0)*(sz.x*0.013), -1.15+y/(sz.y-1.0)*(sz.y*0.013));
			std::complex<double> c(0.7885*std::cos(t/speed_f),0.7885*std::sin(t/speed_f));

			size_t iter;
			for (iter = 0; iter < max_iter && std::abs(z) < 2.0; ++iter)
				z=z*z+c;

			if(iter < max_iter)
				d->AddRectFilled(ImVec2(a.x+x,a.y+y), ImVec2(a.x+x+1,a.y+y+1), to_color((float)iter / max_iter));
			else
				d->AddRectFilled(ImVec2(a.x+x,a.y+y), ImVec2(a.x+x+1,a.y+y+1), 0XFF000000);
		}
}

@badlydrawnrod
Copy link

A little driving game. Use the mouse buttons to move left and right.

drive

#define V2 ImVec2
#define R d->AddRectFilled
#define RED 0xff0000ff

void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4 m, float t)
{
    static float mx = a.x + 160;
    float dy = 36, dt = 8;
    int i = fmodf(dt * t, 2) < 1 ? 1 : 0;
    auto v = fmodf(dt * t, 1), y = a.y - dy + v * dy;
    for (int s = 1 + sz.y / dy; s > 0; --s, y += dy) {
        float c = sinf(t + v / dy - s / dy) * 40;
        V2 tl = { c + a.x + sz.x / 2 - 64, y };
        V2 br = { c + a.x + sz.x / 2 + 64, y + dy };
        R(tl, br, (++i & 1) ? 0xffffffff : RED);
        tl.x += 8;
        br.x -= 8;
        R(tl, br, 0xff3f3f3f);
    }
    if (m.z >= 0) mx--; if (m.w >= 0) mx++;
    R({ mx - 8, b.y - sz.y / 4 - 15 }, { mx + 8, b.y - sz.y / 4 + 15 }, 0xff00ff00, 4);
    R({ mx - 7, b.y - sz.y / 4 - 8 }, { mx + 7, b.y - sz.y / 4 + 12 }, 0xff007f00, 4);
    R({ mx - 6, b.y - sz.y / 4 + 12 }, { mx - 2, b.y - sz.y / 4 + 14 }, RED);
    R({ mx + 2, b.y - sz.y / 4 + 12 }, { mx + 6, b.y - sz.y / 4 + 14 }, RED);
}

@jv42
Copy link

jv42 commented Nov 22, 2020

Inspired by this party, my entry is a Game of Life pulsar oscillator (see Wikipedia)

GoL

Uses left mouse button clicks to process next generation.

My algorithm is probably not efficient, and I need quite a big data input, so had to make the code ugly to get to 994 bytes:

#define V2 ImVec2
#define S 17
#define L 16
#define I int
#define F float

I h[S][S],g[S][S]={{0},{0},{0,0,0,0,1,1,1,0,0,0,1,1,1},{0},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,0,0,1,1,1,0,0,0,1,1,1},{0},{0,0,0,0,1,1,1,0,0,0,1,1,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0,0,1,0,0,0,0,1,0,1,0,0,0,0,1},{0},{0,0,0,0,1,1,1,0,0,0,1,1,1}};

void FX(ImDrawList* d,V2 a,V2 b,V2 sz,ImVec4 m,F t)
{
if (!m.z)
{
for(I i=1;i<L;i++)
for(I j=1;j<L;j++)
{
I c=g[i-1][j-1]+g[i-1][j]+g[i-1][j+1]+g[i][j-1]+g[i][j+1]+g[i+1][j-1]+g[i+1][j]+g[i+1][j+1];
h[i][j]=(g[i][j]&&c==2)||c==3;
}
for(I i=1;i<L;i++)
for(I j=1;j<L;j++)
g[i][j]=h[i][j];
}
F s=1.f/S; I i=0,j=0;
for(F y=0.f;y<1.f;y+=s,j++,i=0)
for(F x=0.f;x<1.f;x+=s,i++)
{
V2 c((x+.5f*s),(y+.5f*s));
F k = .45f;
d->AddRectFilled(
V2(a.x+(c.x-k*s)*sz.x,a.y+(c.y-k*s)*sz.y),
V2(a.x+(c.x+k*s)*sz.x,a.y+(c.y+k*s)*sz.y),
g[i][j]*0xFFFF0000);
}
}

@Organic-Code
Copy link
Contributor

Organic-Code commented Nov 22, 2020

Non competing (I mean it’s not really my idea ; and truthfully it’s not really an effect), inspired by the previous comment, Conway’s Game of Life
conways
conways2

Use left click to place/remove a cell, and right click to start/stop.

Source code (1024 bytes)
#define V ImVec2
#define R(c)d->AddRectFilled(a+V(1,1)+V(i-1,j-1)*8, a-V(1,1)+V(i,j)*8,c)
int board[42][24]{};
int r = 0;
int f = 0;
void FX(ImDrawList * d,V a,V,V,ImVec4 m, float t) {
	if (r && ++f%10==1) {
		int n[42][22] = {};
		for (int i = 41; --i;) {
			for (int j = 23; --j;) {
				int s = -board[i][j];
				for (int k = 3; k--;) {
					for (int l = 3; l--;) {
						s += board[i + k - 1][j + l - 1];
					}
				}
				if (s == 3)
					n[i][j] = board[i][j]?1:2;
				if (s == 2)
					n[i][j] = board[i][j];
			}
		}
		for (int i = 41; --i;)
			for (int j = 23; --j;)
				board[i][j] = n[i][j];
	}
	int x = int(m.x * 40);
	int y = int(m.y * 22.5f);
	if (m.z == 0.f && !r)
		if (x >= 0 && x < 41 && y >= 0 && y < 23)
			board[x+1][y+1] = !board[x+1][y+1];

	if (m.w == 0.f)
		r = !r;

	for (int i = 41; --i;)
		for (int j = 23; --j;) {
			if (board[i][j] == 2) {
				board[i][j] = 1+!!(f%10);
				R(0xFF55AAAA);
			}
			if (board[i][j] == 1)
				R(0xFFFF8855);
		}

	d->AddRect(a + V(x,y) * 8, a + V(x+1,y+1) * 8, ~0);
}

@pmalin
Copy link

pmalin commented Nov 29, 2020

Once again I find a hack just after I posted that improves things. Sorry for the double post.

ImguiLandscapeBetter

https://gist.github.com/pmalin/5e2906acc4983bdcbf9a7349997fe824
(1021 bytes)

@bdero
Copy link
Contributor

bdero commented Nov 29, 2020

@pmalin I love that that the compression of the gif paints in an extra mountain range on the right side. Extra scenic!

@bdero
Copy link
Contributor

bdero commented Nov 29, 2020

Second entry: Sail boat!

b2

Based on a small game jam entry I made a few years back.

Source is 1019 bytes -- thanks to @andwn for brainstorming additional ideas to shed off characters:

#define C cos
#define W(I){F R=H(I)*62,X=a.x+s.x/8*((I%11)-1)+C(R+t)*10,Y=a.y+s.y/8*(I/11)+40+sin(R+t)*10,E=1-exp(-(I/11)/3.);\
d->AddTriangleFilled(V(X,Y),V(X+300,Y+90),V(X-300,Y+90),ImColor(.94f-.17f*E,.61-.25*E,.36+.38*E));}
using F=float;using V=ImVec2;
ImU32 c[7]={0xff00a4fb,0xff00a4fb,(ImU32)-1,(ImU32)-1,0xff262aa2,0xff01007d,0xff64c9fd};
F M=FLT_MAX;V N=V(M,M);F H(F x){F y=C(x)*42;return y-floor(y);}
void FX(auto *d,V a,V b,V s,auto m,F t){d->AddRectFilled(a,b,c[6]);int i=0,j=0,k=0;
for(;i<33;i++)W(i)
F x=C(t*1.3)*2+a.x+s.x*.5,y=15+C(t*1.4)*2.5+C(t*2)*3+a.y+s.y*.5,r=C(t)/10+C(t*1.33)/12,
f[98]={-11,-3.5,4,-24,1.5,-3.5,M,M,5.5,-2,3,-24,11,-2,M,M,2.8,-24,4,-24,4,-2,2.8,-2,M,M,-11,-4.4,4,-4.4,4,-3.5,-11,-3.5,M,M,-12,-2,12,-2,12,0,-12,0,M};
V *v=(V*)f;v[48]=N;
for(i=25;i--;){F d=.1308*i;v[i+23]=V(C(d)*11,sin(d)*8);};
for(;i<49;i++)
if(v[i].x==M){d->AddConvexPolyFilled(&v[j],i-j,c[k]);j=i+1;k++;}
else{v[i]=V(x+(C(r)*v[i].x-sin(r)*v[i].y)*3.5,y+(sin(r)*v[i].x+C(r)*v[i].y)*3.5);}
for(i=33;i<88;i++)W(i)}

@andrewwillmott
Copy link
Contributor

Got an hour to remove the STL dependency from my entry (particularly as I see there are some cool ports above) and polish it a bit.

spirals4

Calling it "spirals" -- source is now down to 1010 bytes, with some formatting retained :)

typedef float F;
struct G{F v0,v1; int mc,w; F ms,ma; int c; F v,d,a;};

F x(G& g){
g.c++;
if (g.c > g.mc){
g.a = (drand48()-0.5)*2*g.ma;
g.c = 0;
}
g.d += g.a;
g.d = fmin(g.ms, fmax(-g.ms, g.d));
g.v += g.d;
if (g.w)
g.v = g.v0 + fmod(g.v-g.v0, g.v1-g.v0);
else
g.v = fmin(g.v1, fmax(g.v0, g.v));
return g.v;
}

int mx=999;
G rc={-15,15, 150,0,0.05,0.005,mx};
G ac={0,360,120,1,1,0.03,mx};
G da={0,360,80,1,0.1,0.01,mx};
G rm={64,255,95,0,10,1.3,mx};
G gm={64,255,40,0,10,1.3,mx};

struct E{F r;F a;F da;F cr;F cg;};
E ne(){return{x(rc),x(ac),x(da),x(rm),x(gm)};}

int ei=0,en=400;
E es[400];

void FX(ImDrawList* d,V2 a,V2 b,V2 sz,ImVec4,F){
ei++;ei%=en;
es[ei]=ne();

V2 o=a+sz*0.5;
d->AddRectFilled(a,b,~0);

for (int i=en;i;){
E& e = es[(i-- + ei)% en];
F ar = e.a*M_PI/180;
V2 p(sin(ar),cos(ar));
p.x += sin(e.da*e.a/3600)*.5;
p *= sz.y*e.r/42;
F cr = sz.y/20 * (1+fabs(e.r/15));
d->AddCircleFilled(o+p, cr, IM_COL32(e.cr, e.cg, (255-e.cr*e.cg/255), 60));
d->AddCircle(o+p, cr, 30<<24);
e.a += e.da/4;
}}

@StephaneMenardais
Copy link

StephaneMenardais commented Nov 29, 2020

ImGuiFx4c

A little shot'em up. Lots of features bypassed to make it fit in 1Ko (missile, gui, sort, planet background, level of difficulty etc.)
Did not anticipate how game logic increase complexity. If some1 is able to compress 10+bytes i could increase sphere display quality :)

edit: updated sphere visual (1022b).
nb: u must have mouse on windows before start (2sec delay)

#define Q 999
#define L(i,x)for(I i=0;i<x;i++)
#define D(a,b)sqrt(pow(a.p.x-b.p.x,2)+pow(a.p.y-b.p.y,2))
#define S(...)L(i,Q)if(!E[i].h){E[i]={__VA_ARGS__};i=Q;}
#define J (rand()&511)*.002
#define H(a)a.h--;z=!a.h&&a.i==8;L(i,6)S(a.p,V(cos(J*9),sin(J*9))*99,z?4:2,z?1:120,z*2)
using V=ImVec2;using I=int;struct T{V p,v;I i=9,h=0,s=2;};I z;T E[Q],C,&M=E[Q-1],&N=E[Q-2];void FX(ImDrawList*d,V a,V b,V sz,ImVec4 m,float t){C.p=a+sz/2;M.p=a+V(m.x,m.y)*sz;N.p=a+sz*V(.75,.5)+V(sin(t),cos(t*2))*40;if(t<2){M.h=N.h=99;M.s=1;}else{S(V(b.x,a.y+sz.y*J),V(-1-J,0)*50,1,40,0)L(i,Q)if(E[i].h){T&e=E[i];e.p+=e.v/50;t=e.i>8?e.s*10+J*(99-e.h)*.1:e.i;I j=64+7*e.i;L(k,(e.i>8?4:1))d->AddCircleFilled(e.p+(M.p-e.p)*k/50,t-k*t/4,((k&1)+2)*ImColor(e.s&2?j:e.h,e.s&1?j:e.h,e.s?0:e.h),32);if(e.i==2)e.h-=5;if(D(C,e)>200+e.i)e.h=0;L(j,Q){T&f=E[j];if(e.h*f.h&&e.s*f.s==2&&D(e,f)<f.i+e.i){H(e)H(f)}}}if(M.h*N.h){if(J<.1)S(N.p,M.p-N.p,4,2)if(J<.02)S(N.p,V(-50,0),8,2)if(m.z==0)L(j,4)S(M.p+V(0,(j&1)*(j-2)*4),V(500,j<3?(j-1)*250:0),4,1,1)}}}

@Horrowind
Copy link

Inspired by 'Symmetry in Chaos' from Michael Field and Martin Golubitsky. 997 bytes.

out

#define V ImVec2
#define f float
#define i int
i color(f h){h=fmod(h,3);i n=192,o=n*h;i c=0xFF404040;if(h<1){c+=n-o;c+=o<<8;}else if(h<2){o-=n;c+=(n-o)<<8;c+=o<<16;}else{o-=2*n;h-=2;c+=(n-o)<<16;c+=o;}return c;}
#define mul(a,b)V((a).x*(b).x-(a).y*(b).y,(a).x*(b).y+(a).y*(b).x)
void FX(ImDrawList* d,V a,V b,V s,ImVec4 m,f t){
i c = color(t);
f ps[5][7]={{-1.860,2,0,1,.1,4,90},{-2.08,1,-.1,0.167,0,7,60},{-1.816,1.791,0,1,0,5,90},{1.52,-1.21,-.091,-0.8005,0,3,60},{2.404,-2.505,0,.9,0,13,90}};
static f*qs=ps[0];i k=(i)(m.y*5);k=k<0?-1:k>=5?-1:k;
for(i j=0;j<5;j++)d->AddRectFilled(a+V(0,s.y*j/5+3),a+V(s.x*.2,s.y*(j+1)/5-3),k==j&&0<m.x&&m.x<0.2?c:c&0xEFFFFFF,2);
k=k==-1?0:k;
if(m.x<0.2&&m.z==0)qs=ps[k];
f l1=qs[0]+m.x*.01;
f l2=qs[1]+m.y*.01;
V z=V(.1,.1);
for(i j=0;j<1<<16;j++){
V p=z,q(1,0),e= V(z.x,-z.y);
for(i j=1;j<qs[5];j++){p = mul(p,z); q=mul(q,e);}
z=z*(l1+l2*(z.x*z.x+z.y*z.y)+qs[2]*p.x)+q*qs[3]+V(-z.y*qs[4],z.x*qs[4]);
d->AddCircleFilled(z*qs[6]+(a+b)/2,1.0,c&0x08FFFFFF,4);
}}

@Organic-Code
Copy link
Contributor

Organic-Code commented Nov 29, 2020

@StephaneMenardais

There you go, 15 bytes removed
#define Q 999
#define L(i,x)for(I i=0;i<x;i++)
#define D(a,b)pow(pow(a.p.x-b.p.x,2)+pow(a.p.y-b.p.y,2),.5)
#define S(...)L(i,Q)if(!E[i].i){E[i]={__VA_ARGS__};i=Q;}
#define J (rand()&511)*.002
#define H(a)a.h--;L(i,8)S(a.p,V(cos(J*9),sin(J*9))*99,2,120,0)
using V=ImVec2;using I=int;struct T{V p,v;I i=0,h=99,s=2;};T E[Q],C,&M=E[Q-1],&N=E[Q-2];void FX(ImDrawList*d,V a,V b,V sz,ImVec4 m,float t){C.p=a+sz/2;M.p=a+V(m.x,m.y)*sz;N.p=a+sz*V(.75,.5)+V(sin(t),cos(t*2))*40;if(t<2){M.i=N.i=9;M.s=1;}else{S(V(b.x,a.y+sz.y*J),V(-50-J*50,0),1,40,0)L(i,Q)if(E[i].i){T&e=E[i];e.p+=e.v/50;I j=50+16*e.i;d->AddCircleFilled(e.p,e.i>8?e.s*10+J*(99-e.h)*.1:e.i,ImColor(e.s&2?j:e.h,e.s&1?j:e.h,e.s?0:e.h)*2,32);if(D(C,e)>200+e.i)e.h=0;L(j,Q){T&f=E[j];if(e.h*f.h&&e.s*f.s==2&&D(e,f)<(f.i+e.i)){H(e);H(f);}}if(!e.h){if(e.i==8)L(i,16)S(e.p,V(cos(J*7),sin(J*7))*99,4,1)e.i=0;}if(e.i==2)e.h-=5;}if(M.h*N.h){if(J<.1)S(N.p,M.p-N.p,4,4)if(J<.01)S(N.p,V(-50,0),8,4)if(!m.z)L(j,4)S(M.p+V(0,(j&1)*(j-2)*4),V(500,j<3?(j-1)*250:0),4,1,1)}}}

changes :

  • replaced if(m.z==0) by if(!m.z)
  • removed an extraneous ; (S(e.p,V(cos(J*7),sin(J*7))*99,4,1);)
  • moved M and N declarations (from T E[Q],C;//...//T&M=E[Q-1];T&N=E[Q-2]; to T E[Q],C,&M=E[Q-1],&N=E[Q-2];//...//

edit: nvm I can’t count, that’s not 15 at all, that’s only 5 my bad

@StephaneMenardais
Copy link

StephaneMenardais commented Nov 29, 2020

!m.z do not work on my visual since it is the mouse (a float)
thx for the others. your eyes are definitely better than mine ^^

edit: finally i saved 16bytes (thx @Organic-Code) :), i'll try tonight to improve the gfx quality of the spheres
edit2: omg i reduced to 980bytes with a factorisation between explosion particles and bomb explosion (/me dancing!)

@Organic-Code
Copy link
Contributor

That’s peculiar, I am building it using MVSC (not visual studio itself though)

@Seyedof
Copy link

Seyedof commented Nov 29, 2020

imguiWolf

#define V2 ImVec2
#define fl float
#define in int
#define S 1000
V2 p(S/2,S/2);
fl r=0;
#define c cos
#define s sin
#define re return
in m[S][S];
in g=1;
V2 ro(V2 v){re V2(v.x*s(r)-v.y*c(r),v.x*c(r)+v.y*s(r));}
V2 ro(V2 v,fl b){re V2(v.x*s(b)-v.y*c(b),v.x*c(b)+v.y*s(b));}
fl dot(V2 v1,V2 v2){re v1.x*v2.x+v1.y*v2.y;}
void gm() 
{
	if(!g)re;
	for(in j=0;j<S;j++)for(in i=0;i<S;i++)m[j][i]=rand()>20000;
	m[(in)p.y][(in)p.x]=0;g=0;
}
void FX(ImDrawList*dl,V2 a,V2 b,V2 sz,ImVec4 ms,fl)
{
	gm();
	fl d=sz.x/2/tan(IM_PI/4);
	fl adv=ms.z>=0?ms.z:0;adv=ms.w>=0?-ms.w:adv;
	r=(ms.x-.5)*IM_PI*2;
	V2 f=ro(V2(adv,0));p+=f;
	for(fl x=-sz.x/2;x<sz.x/2;x++){
		V2 ray=V2(x,d)/sqrt(x*x+d*d);ray=ro(ray,r+IM_PI/2);
		V2 q=p;fl s;
		for(s=0;s<S;s+=.01){
			if(m[(in)(q.y)][(in)(q.x)])break;
			q=ray*s+p;
		}
		fl z=dot(q-p,ro(V2(1,0)));
		fl h2=d/z/2;fl l=.15+1/s;in v=((in)q.x+(in)q.y)&1;
		dl->AddLine(V2(x+a.x+sz.x/2,sz.y/2-h2+a.y),V2(x+a.x+sz.x/2,sz.y/2+h2+a.y),ImColor(v*l,l/4,(1-v)*l));
	}
}

This is my entry, Wolf3D style sw rendering in imgui, called imguiWolf.
Mouse.x = yaw
Mouse.LButton = move forward
Mouse.RButton = move backward

@tcantenot
Copy link

Fluid paint

BapO2ZEUVZ
1024 bytes

#define U using
#define L for(I
#define M L y=Y;y--;)L x=X;x--;){
#define R return
#define Z [x][y]
enum{X=160,Y=90};U I=int;U F=float;U A=ImVec2;U B=ImVec4;U C=ImColor;U D=A[X][Y];U E=B[X][Y];A operator+(A a,A b){R{a.x+b.x, a.y+b.y};}A operator*(A v,F f){R{f*v.x,f*v.y};}A G(A v){R{v.x-I(v.x),v.y-I(v.y)};}A J(A p){R A(p.x*-.5+p.y*.87,-p.x*.87-p.y*.5);}F K(F a,F b){R a<b?a:b;}E c,d;D e,f,g,h,i;F j,k;void FX(ImDrawList*_,A a,A b,A,B m,F t){F s,z;M g Z=g Z*.9;d Z=c Z;f Z=e Z;}M A u((x+.5)/X,(y+.5)/Y),a=u*2,t(cos(a.x),sin(a.x)),v;s=.01;L l=4;l--;s*=3.7)L m=3;m--;t=J(t)){A q=t*s,r=u+q,p(cos(a.y),sin(a.y)),b,o,w;z=0;L i=3;i--;p=J(p)){b=p*s,w=G(r+b);I x=w.x*X,y=w.y*Y;o=f Z;z+=(o.x*b.y-o.y*b.x)/(b.x*b.x+b.y*b.y);}v=v+A(-q.y*.02,q.x*.03)*z*.33;}u=G(u+v);I i=u.x*X,m=u.y*Y;c Z=d[i][m];e Z=(f[i][m]+g Z*.08)*.99;}s=m.x,z=m.y;M F a=s*X-x,b=z*Y-y,d=1-K(sqrt(a*a+b*b)/12,1);d*=m.z>0;if(d)c Z=C::HSV(t-I(t),sin(t)*.3+.7,1);e Z=e Z+A((j-s)*16,(k-z)*9)*d*.5;}j=s,k=z;M s=a.x+x*2,z=a.y+y*2;_->AddLine({s,z},{s+1,z+2},C(c Z));}}

Mouse left-click + drag to paint.

Sorry for the heavily compressed code :-s!

Inspired by flockaroo's fluid dynamics (https://www.shadertoy.com/view/MdKXRy).

@pmalin
Copy link

pmalin commented Nov 29, 2020

Ok, here is another one. I thought the ImDrawList coding party needed a disco ball.

DiscoBallD

#define V ImVec2
#define F float
void R(F&x,F&y,F r){F s=sin(r),c=cos(r),t=c*x-s*y;y=s*x+c*y;x=t;}
F c,e,f,g,l,r,x,y,z;
int i,j,k,u,v,K=24,J=48;
F L(F a){l*=l>0;return sqrt(1-exp(-a*(l+.1)-l*l*l));}
void T(F u){R(x,z,c+6.28*u);}
V P(F t){t*=3.14/K;return V(sin(t),cos(t));}
void FX(ImDrawList*d,V a,V b,V S,ImVec4 I,F t){
V o[4],m=(a+b)/2;c=t/2;
k=sin(t*13)*24+24;j=-0xafefb0+k*0x101;d->AddRectFilledMultiColor(a,b,j,j+0x503010,j+0x4050,j+0x7040);
for(k=K;--k;){for(j=J;j--;){for(i=4;i--;){
u=j+(i%3>0);v=-(i/2);
V p=P(k+v);x=p.x;y=p.y;z=0;
T((F)u/J);e=x;f=y;z=S.y/(g=z+2.5);
o[i]=m+V(x,y)*z;}
V v1=P(k),v2=P(k-1);
x=v1.y-v2.y;y=v2.x-v1.x;z=0;
l=sqrt(x*x+y*y);x=x/l;y=y/l;T((j+.5)/J);
r=2*(x*e+y*f+z*g);
e-=r*x;f-=r*y;g-=r*z;
l=sqrt(e*e+f*f+g*g);
x=atan2(e,g);y=atan2(sqrt(e*e+g*g),f);
l=sin(x*5+sin(y*3+t))+sin(x*9+sin(y*5+t))+cos(y*4+sin(x*5+t));
l=l/4+.5;
I.x=l;I.y=l*.9*(.8+e/4);I.z=(.5-f/2)*l/2;I.w=1;
if(r>0)d->AddConvexPolyFilled(o,4,ImColor(I)),d->AddPolyline(o,4,0xff<<24,true,1);
}}}

(1022 bytes)

@ocornut
Copy link
Owner Author

ocornut commented Nov 30, 2020

Amazing work all! As per the undefined behavior of what constitute a deadline of "Nov 30", let's make it maximum-optimistic Pacific Time, aka about 19 extra hours from the time of this post.

What shall we do with this to provide some kind of climax?
Would an "everyone wins" statement constitute enough climax? :)
How about:

  • We assemble everything into a single thing that's somehow shippable (potentially the stub could also play it as a megademo)
  • Publish on the web via emscripten
  • Bonus: with a source / text editor display on the side using ImGuiColorTextEdit ?

@Seyedof
Copy link

Seyedof commented Nov 30, 2020

sir

#include <vector>
#define Z std::vector
#define V ImVec2
#define W ImVec4
#define F float
#define R return
ImDrawList*gd;V bl;W ey;W la;W z;W x;W y;
W operator*(W&l,F r){R W(l.x*r,l.y*r,l.z*r,l.w*r);}
F d(W v,W w){R v.x*w.x+v.y*w.y+v.z*w.z+v.w*w.w;}
W n(W&v){R v*(1./sqrt(d(v,v)));}
V j(W&v){v.w=1;W r(d(x,v),d(y,v),d(z,v),v.w);V p(r.x*277/r.z+160,-r.y*277/r.z+90);R p+bl;}
#define A(a,b,c) W p##c=(v[a]+v[b])*.5;
#define Q(a,b,c,e,f) P({p##a,p##b,p##c,p##e,p##f},r+1);
#define C(a) W p##a=v[a-10];
#define I ImColor
#define D(a,b,c,f,g,h) gd->AddTriangleFilled(j(v[a]),j(v[b]),j(v[c]),I((F)l*f/10,l*g/10,l*h/10,1.));
void P(Z<W>v,int r){if(r<5) A(0,1,1)A(0,2,2)A(0,3,3)A(0,4,4)A(1,2,5)A(1,3,6)A(2,4,7)A(3,4,8)A(1,4,9)C(10)C(11)C(12)C(13)C(14)Q(1,11,5,6,9)Q(2,5,12,4,7)Q(10,1,2,3,4)Q(3,6,9,13,8)Q(4,9,7,8,14)R;}	F l=2./(v[0].z+5);D(0,2,2,5,5,0)D(0,2,4,0,5,0)D(0,1,3,0,0,10)D(0,3,4,10,0,0)}
void FX(ImDrawList*dl,V a,V,V,W,F t)
{bl=a;gd=dl;ey=W(sin(t/2.)*7,3.,-9,0);la=W(0,1,0,1);z=n(la-ey);x=n(W(z.z,0,-z.x,0));y=W(z.y*x.z-z.z*x.y,z.z*x.x-z.x*x.z,z.x*x.y-z.y*x.x,0);x.w=-d(x,ey);y.w=-d(y,ey);z.w=-d(z,ey);Z<W>v={{0,5,0,1},{-5,0,5,1},{5,0,5,1},{-5,0,-5,1},{5,0,-5,1}};P(v,0);}

3D Sierpinksi Triangle
I tried to reduce to 1024 but did not succeed, if we had ImVec4 math operators in imgui, it could end up being under 1024, maybe worth to share anyway :)

@Daandelange
Copy link

Hello, here's my entry, mixing random terrain generation and some kind of simulation (pseudo random movement, boundary checking). Randomness strives to eat all vegetation; once that happens, everything starts all over.

imgui_contest

#define g using
g C=int;C f=10;g A=ImVec2;g B=float;bool E=1;B G;B U=IM_PI*2;B H=0;B R(A S){C X=S.x+S.y*57;X=(X<<13)^X;return .5+.5*(1.-((X*((X*X*15731)+789221)+1376312589)&0x7fffffff)/1073741824.);}B V(B Y,B Z,B X){B W=ImClamp<B>((X-Y)/(Z-Y),0,1);return W*W*(3-2*W);}C I(A S){return C(ImMin<C>(S.x,320-1)/f)+C(ImMin<C>(S.y,180-1)/f)*(320/f);}A K[50];B Q[576];void FX(ImDrawList*F,A D,A,A b,ImVec4,B T){B J=0;if(E)G=(H+1337e-8*(intptr_t)&E);for(C M=0;M<576;++M){A c=A(fmodf(M,320/f),M/(320/f));if(E){B X=R(ImFloor(c)+A(G*f,0));Q[M]=(X<.5?1:(X>.7?0:2))+(H>T-1)*1-fmodf(T+M,2.1);}C d,e=d=0;if(Q[M]<=1){e=255-20*V(-1,0,fmodf(Q[M],1));d=e*V(1,0,Q[M]);}A S=D+c*f;F->AddRectFilled(S,S+A(f,10),IM_COL32(d,e,d,255));J+=Q[M]*(Q[M]>0&&Q[M]<=1);}for(C L=0;L<50;++L){if(E)K[L]=A(R(A(T,L)),R(A(L,T)))*b;A S=K[L];B O=(R(ImFloor(S/f)*f+A(L,L))+(C(T*.17))+T*.27*(L%2?1:-1))*U;C a=I(S);B&N=Q[a];N-=.2*(N<=1);A P(cos(O),sin(O));K[L]=ImClamp(K[L]+P*(Q[I(S+P*4)]<=1),A(0,0),b);F->AddCircleFilled(D+S,4,0xFF003acc);}if(H<T-1){E=J<1;if(E)H=T;}}

1022Kb, my backend is limited to 60 FPS, I hope the simulation runs well on other configs.

Thanks for ImGui, thanks for all entries, this was a marvellous week !

@kiwidream
Copy link

Thought I'd do something with hexagons! 1024 bytes exactly.

NB4GSN3Bfa

#define V2 ImVec2
#define PI 3.1415926535
#define HP(p,s,c,o) V2(cosf(p * PI / 3 + o) * s + c.x, sinf(p * PI / 3 + o) * s + c.y)
#define SQ(t) sinf(t) + sinf(3*t)/3 + sinf(5*t)/5 + sinf(7*t)/7
#define max(x,y) ((x)>(y)?x:y)
#define min(x,y) ((x)<(y)?x:y)
#define CI(i) ((int)(sinf(i) * 128 + 128)) % 256
#define Z 35.0
// Hexagons! Better make it 1024.
void FX(ImDrawList* d, V2 a, float t) {
    for (int x=-2;x<=5;x++) {
        for (float y = 0; y <= 4; y++) {
            V2 o = V2(a.x + sqrt(3) * Z * (x + y/2), a.y + y * 3 * Z / 2 + max(50*((4+((int)y+x)%5)-(15-15/t)),0));
            for (int s = 0; s <= Z; s += 5) {
                float h = max(0, t < 2.5 ? 0 : SQ(t - 1.5 + x * min(t-2.5,1) + s * 10));
                int l = 0;
                for (int p = 1; p <= 6; p++) {
                    d->AddLine(HP(p % 6, s, o, h + PI / 6), HP(l % 6, s, o, h + PI / 6), IM_COL32(CI(h), CI(h + 2), CI(h + 3), 255));
                    l = p;
                }
            }
        }
    }
}

@ocornut ocornut added the gallery label Dec 1, 2020
@septag
Copy link
Contributor

septag commented Dec 1, 2020

I'm late to the party but here goes. seven segment timer (resizable).
I really had to cram everything together to fit it into 1015 bytes:

seven_segment

#define W 15
#define H 7.5
#define v ImVec2
#define fl float
#define dr(n,i)d->AddConvexPolyFilled(pp,6,(kd[n]>>(6-i))&1 ? 0xffffffff : 0xff222222)
char kd[]={0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,0x7F,0x7B};void digit(ImDrawList*d,int n,v e,v p){fl r[7][4]={{-1,-1,H,H},{1,-1,-H,H},{1,0,-H,-H},{-1,1,H,-W*1.5},{-1,0,H,-H},{-1,-1,H,H},{-1,0,H,-H},};for(int i=0;i<7;i++){v a,b;if(i%3==0){a=v(p.x+r[i][0]*e.x+r[i][2],p.y+r[i][1]*e.y+r[i][3]-H);b=v(a.x+e.x*2-W,a.y+W);}else{a=v(p.x+r[i][0]*e.x+r[i][2]-H,p.y+r[i][1]*e.y+r[i][3]);b=v(a.x+W,a.y+e.y-W);}v q=b-a;fl s=W*0.6,u=s-H;if(q.x>q.y){v pp[]={{a.x+u,a.y+q.y*.5f},{a.x+s,a.y},{b.x-s,a.y},{b.x-u,a.y+q.y*.5f},{b.x-s,b.y},{a.x+s,b.y}};dr(n,i);}else{v pp[]={{a.x+q.x*.5f,a.y+u},{b.x,a.y+s},{b.x,b.y-s},{b.x-q.x*.5f,b.y-u},{a.x,b.y-s},{a.x,a.y+s}};dr(n,i);}}}void FX(ImDrawList*d,v a,v b,v sz,ImVec4,fl t){int _t=int(t/60)*100+fmod(t,60);fl p=0.02*sz.x,s=sz.x/4-p,x=s*.5,y=sz.y*.5;for(int i=0;i<4;i++){int _d=_t%10;_t/=10;digit(d,_d,v(s*.5,y),v(b.x-x,a.y+y));x+=s+p;}}

@Organic-Code
Copy link
Contributor

#3606 (comment)
I’m up with that

Might be a headache to put into place though, not all code snippets assumes the same compiler parameters (I had to modify about half of those I tested)
Not that that I’m familiar with emscripten, but if you need some tasking hands let me know

@ocornut
Copy link
Owner Author

ocornut commented Aug 27, 2021

@mgood7123 you’ve posted ~15 messages on this repo and opened various issues today, please be kind to not treat this is a chat room and keep discussions focused and mindful that this is a shared space (people get notifications when you send a message)

@mgood7123
Copy link

@mgood7123 you’ve posted ~15 messages on this repo and opened various issues today, please be kind to not treat this is a chat room and keep discussions focused and mindful that this is a shared space (people get notifications when you send a message)

sorry

@mgood7123
Copy link

mgood7123 commented Aug 27, 2021

* We assemble everything into a single thing that's somehow shippable (potentially the stub could also play it as a megademo)

* Publish on the web via emscripten

* Bonus: with a source / text editor display on the side using ImGuiColorTextEdit ?

is this available somewhere? if so where can i find it?

@xcloudplatform
Copy link

Here are some examples I made to get you started:

Circles

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4 mouse, float t)
{
    for (int n = 0; n < (1.0f + sinf(t * 5.7f)) * 40.0f; n++)
        d->AddCircle(V2(a.x + sz.x * 0.5f, a.y + sz.y * 0.5f), sz.y * (0.01f + n * 0.03f), 
            IM_COL32(255, 140 - n * 4, n * 3, 255));
}

drawlist fx 03 drawlist fx 03

Squares

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
    float sx = 1.f / 16.f;
    float sy = 1.f / 9.f;
    for (float ty = 0.0f; ty < 1.0f; ty += sy)
        for (float tx = 0.0f; tx < 1.0f; tx += sx)
        {
            V2 c((tx + 0.5f * sx), (ty + 0.5f * sy));
            float k = 0.45f;
            d->AddRectFilled(
                V2(a.x + (c.x - k * sx) * sz.x, a.y + (c.y - k * sy) * sz.y),
                V2(a.x + (c.x + k * sx) * sz.x, a.y + (c.y + k * sy) * sz.y),
                IM_COL32(ty * 200, tx * 255, 100, 255));
        }
}

unknown

Curves

#define V2 ImVec2
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t0)
{
    for (float t = t0; t < t0 + 1.0f; t += 1.0f / 100.0f)
    {
        V2 cp0(a.x, b.y);
        V2 cp1(b);
        float ts = t - t0;
        cp0.x += (0.4f + sin(t) * 0.3f) * sz.x;
        cp0.y -= (0.5f + cos(ts * ts) * 0.4f) * sz.y;
        cp1.x -= (0.4f + cos(t) * 0.4f) * sz.x;
        cp1.y -= (0.5f + sin(ts * t) * 0.3f) * sz.y;
        d->AddBezierCurve(V2(a.x, b.y), cp0, cp1, b, IM_COL32(100 + ts*150, 255 - ts*150, 60, ts * 200), 5.0f);
    }
}

drawlist fx 04b drawlist fx 04b

Waves

#define V2 ImVec2
#define ARFM d->AddRectFilledMultiColor
#define ACF d->AddCircleFilled
#define CH s.SetCurrentChannel
void FX(ImDrawList* d, V2 a, V2 b, V2 sz, ImVec4, float t)
{
    ARFM(a, b, 0xFF1E1E1E, 0xFF1E281E, 0xFF1E1E5A, 0xFF321E78);
    ARFM(a, V2(b.x, a.y + sz.y*0.4f), 0x1EFFDCFF, 0x14FFFFDC, 0x001E1E5A, 0x00321E78);
    auto s = d->_Splitter;
    s.Split(d, 2);
    for (int n = 0; n < 256; n++)
    {
        V2 c(a.x + n / 256.f * sz.x, b.y + 20 - cos(t - 0.1f * n / 2) * 10 + cos(t) * 5);
        float r(40 + sin(t + n / 2) * 40);
        CH(d, 0);
        ACF(c, r + 1, 0x80FFFFFF);
        CH(d, 1);
        ACF(c, r, IM_COL32(255, n / 2, n / 8, 255));
    }
    s.Merge(d);
    d->AddRect(a, b, IM_COL32(128, 128, 128, 100));
}

drawlist fx 02 drawlist fx 02

how do you record the snippets and upload them on the GitHub? is there a imGui middle ware for there?

@mohamed-ghayyad
Copy link

mohamed-ghayyad commented Mar 31, 2024

The Matrix effect, slowly been shaving off spaces and making the code uglier and uglier

//v1.1
#define V2 ImVec2
void FX(ImDrawList*d,V2 a,V2,V2 sz,ImVec4,float t)
{
  static struct{int y,h,c; float t,s;} m[40]={0};
  static int S=0x1234;
  static float t0=t;
  float ZI=t*.07f,Z=ZI+1.f;
  for(int x=0;x<40;x++)
  {
    auto& M=m[x];
    int i=x>=15&&x<25;
    if(M.s==0.f||M.y>16)
    {
      M.h = (t<7.f||i)*((int)(2+t*.5f) + S%(int)(6+(t*0.3f)));
      M.y = (M.s==0.f)*-(S%15)-M.h;
      M.c += S;
      M.s = (5+(S%14))*(.01f-t*.001f);
      if(t>5.f&&i)
      {
        M.c = (340003872375972UL>>(x*5-75))&31;
        M.h = i?(x!=19):0;
      }
    }
    if((M.t-=t-t0)<0.f)
    {
      if(t<6.f||!i||M.y!=6)
        M.y++;
      M.t += M.s;
    }
    char c=64|M.c%42;
    for(int j=0; j<M.h; j++,c=64|(c^M.c+M.h^j)%42)
      for(int f=(j+1==M.h)?13:4+(M.c&1);f--;)
        d->AddText(0, 13*(i?Z:-Z), V2(a.x-(sz.x*.5f*ZI)+x*8*Z+sin(j+t*f), a.y-(sz.y*.5f*ZI)+(M.y+j)*13*Z+cos(x*f-t)), 0x3c68bb5b, &c, &c+1);
    S|=((S&1)^((S&8)>>2))<<16;
    S>>=1;
  }
  t0 = t;
}

fx matrix 2 fx matrix 2

This is very nice, and it's exactly what I am looking for but I tried to figure out how to replace the text at the end and it is the char c = 64 if you change the value then it will randomize another ASCII chars but could you please explain a little bit from that code maybe to change to 0 1 0 or maybe to display 'Thanks'
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests