From 7df9940505915a1e57fd4daba9602e6466626c50 Mon Sep 17 00:00:00 2001 From: rodri Date: Sun, 7 Jun 2020 21:14:05 +0000 Subject: new toy: chain. --- chain.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mkfile | 1 + readme.md | 9 +++ 3 files changed, 199 insertions(+) create mode 100644 chain.c create mode 100644 readme.md diff --git a/chain.c b/chain.c new file mode 100644 index 0000000..09c29ad --- /dev/null +++ b/chain.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include +#include +#include + +enum { + MAXMAGNITUDE = 40 +}; + +enum { + Cbg, + Cfg, + NCOLOR +}; + +typedef struct Strut Strut; + +struct Strut +{ + Point2 v; + Strut *next; +}; + +RFrame worldrf; +Image *pal[NCOLOR]; +Strut *struts; +Point2 origin; + +Strut* +newstrut(Point2 v) +{ + Strut *s; + + s = malloc(sizeof(Strut)); + if(s == nil) + sysfatal("malloc: %r"); + setmalloctag(s, getcallerpc(&v)); + s->v = v; + s->next = nil; + return s; +} + +Point +toscreen(Point2 p) +{ + p = invrframexform(p, worldrf); + return Pt(p.x,p.y); +} + +Point2 +fromscreen(Point p) +{ + return rframexform(Pt2(p.x,p.y,1), worldrf); +} + +void +initpalette(void) +{ + pal[Cbg] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000ff); + pal[Cfg] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xffffffff); +} + +void +redraw(void) +{ + Strut *s; + Point2 p0, p1; + + p0 = origin; + + lockdisplay(display); + draw(screen, screen->r, pal[Cbg], nil, ZP); + for(s = struts; s != nil; s = s->next){ + p1 = addpt2(p0, s->v); + line(screen, toscreen(p0), toscreen(p1), Endsquare, Endarrow, 0, pal[Cfg], ZP); + p0 = p1; + } + flushimage(display, 1); + unlockdisplay(display); +} + +void +resized(void) +{ + lockdisplay(display); + if(getwindow(display, Refnone) < 0) + sysfatal("resize failed"); + unlockdisplay(display); + worldrf.p = Pt2(screen->r.min.x,screen->r.max.y,1); + origin = Pt2(Dx(screen->r)/2,Dy(screen->r)/2,1); + redraw(); +} + +void +mouse(Mouse m) +{ + Strut *s; + Point2 mpos, v; + double θ; + + if((m.buttons & 1) != 0){ + mpos = subpt2(fromscreen(m.xy), origin); + θ = atan2(mpos.y, mpos.x); + //v = Vec2(cos(frand() * 2*PI),sin(frand() * 2*PI)); + v = Vec2(cos(θ),sin(θ)); + v = mulpt2(v, frand()*MAXMAGNITUDE); + s = newstrut(v); + if(struts == nil) + struts = s; + else{ + s->next = struts; + struts = s; + } + } +} + +void +key(Rune r) +{ + switch(r){ + case Kdel: + case 'q': + threadexitsall(nil); + } +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + Mousectl *mc; + Keyboardctl *kc; + Rune r; + + ARGBEGIN{ + default: usage(); + }ARGEND; + if(argc > 0) + usage(); + + if(initdraw(nil, nil, nil) < 0) + sysfatal("initdraw: %r"); + if((mc = initmouse(nil, screen)) == nil) + sysfatal("initmouse: %r"); + if((kc = initkeyboard(nil)) == nil) + sysfatal("initkeyboard: %r"); + initpalette(); + worldrf.p = Pt2(screen->r.min.x,screen->r.max.y,1); + worldrf.bx = Vec2(1, 0); + worldrf.by = Vec2(0,-1); + origin = Pt2(Dx(screen->r)/2,Dy(screen->r)/2,1); + + display->locking = 1; + unlockdisplay(display); + redraw(); + + for(;;){ + enum { MOUSE, RESIZE, KEYBOARD }; + Alt a[] = { + {mc->c, &mc->Mouse, CHANRCV}, + {mc->resizec, nil, CHANRCV}, + {kc->c, &r, CHANRCV}, + {nil, nil, CHANEND} + }; + + switch(alt(a)){ + case MOUSE: + mouse(mc->Mouse); + break; + case RESIZE: + resized(); + break; + case KEYBOARD: + key(r); + break; + } + + redraw(); + } +} diff --git a/mkfile b/mkfile index 7fc34f0..8c07918 100644 --- a/mkfile +++ b/mkfile @@ -8,6 +8,7 @@ TARG=\ grid\ isometric\ ptinline\ + chain\ HFILES=\ libgeometry/geometry.h\ diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..a2f5431 --- /dev/null +++ b/readme.md @@ -0,0 +1,9 @@ +# E-Toys + +A bunch of little computer programs for exploration and learning. + +## Notice + +The libgeometry used in these programs is not the stock one, but the +one i wrote (some of you probably noticed from the mkfile). Clone it +in the top dir and it will work. -- cgit v1.2.3