shithub: etoys

Download patch

ref: 7df9940505915a1e57fd4daba9602e6466626c50
parent: 3bef1314a3ae1e5bdc3ffb771e32866e05072d48
author: rodri <rgl@antares-labs.eu>
date: Sun Jun 7 17:14:05 EDT 2020

new toy: chain.

--- /dev/null
+++ b/chain.c
@@ -1,0 +1,189 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
+#include <geometry.h>
+
+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();
+	}
+}
--- a/mkfile
+++ b/mkfile
@@ -8,6 +8,7 @@
 	grid\
 	isometric\
 	ptinline\
+	chain\
 
 HFILES=\
 	libgeometry/geometry.h\
--- /dev/null
+++ b/readme.md
@@ -1,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.