shithub: riscv

Download patch

ref: b622d928912018951b333d6f7e002fa83a71d3cd
parent: c135b5af7abfefe595e109a90becc0281892a9ba
author: aiju <[email protected]>
date: Fri Sep 16 09:32:48 EDT 2011

added games/mandel

--- /dev/null
+++ b/sys/src/games/mandel.c
@@ -1,0 +1,238 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <thread.h>
+#include <mouse.h>
+#include <cursor.h>
+
+enum { ncolors = 600 };
+
+double xmin = -2, xmax = 1;
+double ymin = -1, ymax = 1;
+Mousectl *mctl;
+Rendez rend;
+int stopdraw;
+uchar *imagedata;
+Image *image;
+extern Cursor reading;
+uchar colors[3 * (ncolors + 1)];
+
+double
+convx(Rectangle *r, int x)
+{
+	return (xmax - xmin) * (x - r->min.x) / (r->max.x - r->min.x) + xmin;
+}
+
+double
+convy(Rectangle *r, int y)
+{
+	return (ymax - ymin) * (r->max.y - y) / (r->max.y - r->min.y) + ymin;
+}
+
+void
+pixel(int x, int y)
+{
+	draw(screen, Rect(x, y, x + 1, y + 1), display->black, nil, ZP);
+}
+
+ulong
+iterate(double x, double y)
+{
+	int i;
+	double zx, zy, zx2, zy2, v;
+
+	zx = zy = zx2 = zy2 = 0;
+	for(i = 0; i < 100; i++){
+		zy = 2 * zx * zy + y;
+		zx = zx2 - zy2 + x;
+		zx2 = zx * zx;
+		zy2 = zy * zy;
+		if(zx2 + zy2 >= 4){
+			v = 2 + i - log(log(sqrt(zx2 + zy2)) / log(i + 2)) / 0.69314718;
+			return (int)(v * 1000) % ncolors;
+		}
+	}
+	return 0;
+}
+
+void
+redrawproc(void *)
+{
+	int x, y;
+	uchar *p, *q;
+
+	qlock(rend.l);
+	for(;;){
+		setcursor(mctl, &reading);
+		p = imagedata;
+		for(y = screen->r.min.y; y < screen->r.max.y; y++)
+			for(x = screen->r.min.x; x < screen->r.max.x; x++){
+				if(stopdraw)
+					goto check;
+				q = colors + 3 * iterate(convx(&screen->r, x), convy(&screen->r, y));
+				*p++ = *q++;
+				*p++ = *q++;
+				*p++ = *q;
+			}
+		if(stopdraw)
+			goto check;
+		lockdisplay(display);
+		loadimage(image, image->r, imagedata, Dx(image->r) * Dy(image->r) * 3);
+		draw(screen, screen->r, image, nil, screen->r.min);
+		flushimage(display, 1);
+		unlockdisplay(display);
+	check:
+		stopdraw = 0;
+		setcursor(mctl, nil);
+		rsleep(&rend);
+		stopdraw = 0;
+	}
+}
+
+void
+zoom(void)
+{
+	Rectangle r;
+	double xmin_, xmax_, ymin_, ymax_;
+
+	r = getrect(3, mctl);
+	if(r.min.x == 0 && r.min.y == 0 && r.max.x == 0 && r.max.y == 0)
+		return;
+	xmin_ = convx(&screen->r, r.min.x);
+	xmax_ = convx(&screen->r, r.max.x);
+	ymin_ = convy(&screen->r, r.max.y);
+	ymax_ = convy(&screen->r, r.min.y);
+	stopdraw = 1;
+	qlock(rend.l);
+	xmin = xmin_;
+	xmax = xmax_;
+	ymin = ymin_;
+	ymax = ymax_;
+	rwakeup(&rend);
+	qunlock(rend.l);
+}
+
+char *menus[] = {
+	"zoom in",
+	"reset",
+	"quit",
+	nil,
+};
+
+Menu menu = {
+	.item = menus
+};
+
+void
+resizethread(void *)
+{
+	ulong l;
+
+	for(;;){
+		if(recv(mctl->resizec, &l) < 1)
+			continue;
+		stopdraw = 1;
+		qlock(rend.l);
+		if(getwindow(display, Refnone) < 0)
+			sysfatal("getwindow: %r");
+		freeimage(image);
+		free(imagedata);
+		image = allocimage(display, screen->r, RGB24, 0, DBlack);
+		imagedata = malloc(3 * Dx(screen->r) * Dy(screen->r));
+		rwakeup(&rend);
+		qunlock(rend.l);
+	}
+}
+
+void
+initcolors(void)
+{
+	uchar *p;
+	int h, x;
+
+	for(p = colors + 3, h = 0; p < colors + nelem(colors); h++){
+		x = 0xFF - abs(h % (ncolors / 3) - ncolors / 6) * 0xFF / (ncolors / 6);
+		if(h < ncolors/6){
+			*p++ = 0xFF;
+			*p++ = x;
+			*p++ = 0;
+		}else if(h < ncolors/3){
+			*p++ = x;
+			*p++ = 0xFF;
+			*p++ = 0;
+		}else if(h < ncolors/2){
+			*p++ = 0;
+			*p++ = 0xFF;
+			*p++ = x;
+		}else if(h < 2*ncolors/3){
+			*p++ = 0;
+			*p++ = x;
+			*p++ = 0xFF;
+		}else if(h < 5*ncolors/6){
+			*p++ = x;
+			*p++ = 0;
+			*p++ = 0xFF;
+		}else{
+			*p++ = 0xFF;
+			*p++ = 0;
+			*p++ = x;
+		}
+	}
+}
+
+void
+threadmain()
+{
+	static QLock ql;
+	int rc;
+
+	if(initdraw(nil, nil, "mandelbrot") < 0)
+		sysfatal("initdraw: %r");
+	display->locking = 1;
+	unlockdisplay(display);
+	if((mctl = initmouse(nil, screen)) == nil)
+		sysfatal("initmouse: %r");
+	rend.l = &ql;
+	image = allocimage(display, screen->r, RGB24, 0, DBlack);
+	imagedata = malloc(3 * Dx(screen->r) * Dy(screen->r));
+	initcolors();
+	proccreate(redrawproc, nil, mainstacksize);
+	threadcreate(resizethread, nil, mainstacksize);
+	for(;;){
+		readmouse(mctl);
+		if(mctl->buttons & 4){
+			lockdisplay(display);
+			rc = menuhit(3, mctl, &menu, nil);
+			unlockdisplay(display);
+			switch(rc){
+			case 0:
+				zoom();
+				break;
+			case 1:
+				stopdraw = 1;
+				qlock(rend.l);
+				xmin = -2;
+				xmax = 1;
+				ymin = -1;
+				ymax = 1;
+				rwakeup(&rend);
+				qunlock(rend.l);
+				break;
+			case 2:
+				threadexitsall(nil);
+			}
+		}
+	}
+}
+
+Cursor reading = {
+	{-1, -1},
+	{0xff, 0x80, 0xff, 0x80, 0xff, 0x00, 0xfe, 0x00, 
+	 0xff, 0x00, 0xff, 0x80, 0xff, 0xc0, 0xef, 0xe0, 
+	 0xc7, 0xf0, 0x03, 0xf0, 0x01, 0xe0, 0x00, 0xc0, 
+	 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0xff, },
+	{0x00, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x7c, 0x00, 
+	 0x7e, 0x00, 0x7f, 0x00, 0x6f, 0x80, 0x47, 0xc0, 
+	 0x03, 0xe0, 0x01, 0xf0, 0x00, 0xe0, 0x00, 0x40, 
+	 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
+};
--- a/sys/src/games/mkfile
+++ b/sys/src/games/mkfile
@@ -11,6 +11,7 @@
 	mole\
 	glendy\
 	packet\
+	mandel\
 
 OFILES=
 HFILES=