shithub: 3d

Download patch

ref: 0c330bc0d2d56af57af2b40fc2e3765dd9d114ef
author: qwx <[email protected]>
date: Mon Feb 22 10:48:55 EST 2021

3d01: absolute basic 3d view of map and actor

--- /dev/null
+++ b/3d01.c
@@ -1,0 +1,125 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+enum{
+	Hz = 30,
+};
+char *progname = "3d01";
+
+int tdiv = Te3 / Hz;
+
+enum{
+	Cbg,
+	Cplayer,
+	Carrow,
+	Cwall,
+	Cend,
+};
+static Image *col[Cend];
+
+typedef struct Player Player;
+struct Player{
+	Foint;
+	double θ;
+};
+static Player player;
+static Rectangle wall;
+
+static void
+forward(void)
+{
+	player.x += cos(player.θ);
+	player.y += sin(player.θ);
+}
+
+static void
+backward(void)
+{
+	player.x -= cos(player.θ);
+	player.y -= sin(player.θ);
+}
+
+static void
+turnleft(void)
+{
+	player.θ -= 0.1;
+}
+
+static void
+turnright(void)
+{
+	player.θ += 0.1;
+}
+
+static void
+transleft(void)
+{
+	player.x += sin(player.θ);
+	player.y -= cos(player.θ);
+}
+
+static void
+transright(void)
+{
+	player.x -= sin(player.θ);
+	player.y += cos(player.θ);
+}
+
+Key keys[] = {
+	{'w', forward},
+	{'s', backward},
+	{'a', turnleft},
+	{'d', turnright},
+	{'q', transleft},
+	{'e', transright},
+};
+int nkeys = nelem(keys);
+
+static void
+stepsim(void)
+{
+	Key *k;
+
+	for(k=keys; k<keys+nkeys; k++)
+		if(k->down)
+			k->fn();
+}
+
+/* absolute map: global 2d topdown view */
+static void
+render(void)
+{
+	draw(fb, fb->r, col[Cbg], nil, ZP);
+	line(fb, wall.min, wall.max, 0, 0, 1, col[Cwall], ZP);
+	ellipse(fb, Pt(player.x, player.y), 2, 2, 0, col[Cplayer], ZP);
+	line(fb, Pt(player.x, player.y),
+		Pt(player.x + cos(player.θ) * 15, player.y + sin(player.θ) * 15),
+		0, 0, 0, col[Carrow], ZP);
+}
+
+static void
+initrender(void)
+{
+	col[Cbg] = display->black;
+	col[Cplayer] = display->white;
+	col[Carrow] = eallocimage(Rect(0,0,1,1), screen->chan, 1, 0x777777ff);
+	col[Cwall] = eallocimage(Rect(0,0,1,1), screen->chan, 1, DYellow);
+}
+
+static void
+initsim(void)
+{
+	wall = Rect(70, 20, 70, 70);
+	player = (Player){(Foint){50, 50}, 0};
+}
+
+void
+threadmain(int, char**)
+{
+	sysinit(initrender, initsim, render, stepsim);
+	sim();
+}
--- /dev/null
+++ b/dat.h
@@ -1,0 +1,29 @@
+typedef struct Key Key;
+typedef struct Foint Foint;
+
+enum{
+	Te9 = 1000000000,
+	Te6 = 1000000,
+	Te3 = 1000,
+};
+extern int tdiv;
+
+struct Key{
+	Rune r;
+	void (*fn)(void);
+	int down;
+};
+extern Key keys[];
+extern int nkeys;
+
+extern Image *fb;
+extern Rectangle fbr;
+
+struct Foint{
+	double x;
+	double y;
+};
+
+extern char *progname;
+extern void (*renderfn)(void);
+extern void (*stepsimfn)(void);
--- /dev/null
+++ b/drw.c
@@ -1,0 +1,44 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+Rectangle fbr;
+Image *fb;
+
+void (*renderfn)(void);
+
+Image *
+eallocimage(Rectangle r, ulong chan, int repl, ulong col)
+{
+	Image *i;
+
+	if((i = allocimage(display, r, chan, repl, col)) == nil)
+		sysfatal("allocimage: %r");
+	return i;
+}
+
+void
+updatedraw(void)
+{
+	renderfn();
+	draw(screen, screen->r, fb, nil, ZP);
+	flushimage(display, 1);
+}
+
+void
+redraw(void)
+{
+	updatedraw();
+}
+
+void
+resetdraw(void)
+{
+	freeimage(fb);
+	fbr = rectsubpt(screen->r, screen->r.min);
+	fb = eallocimage(fbr, screen->chan, 0, DNofill);
+	redraw();
+}
--- /dev/null
+++ b/fns.h
@@ -1,0 +1,7 @@
+void*	emalloc(ulong);
+void	sim(void);
+void	sysinit(void (*)(void), void (*)(void), void (*)(void), void (*)(void));
+Image*	eallocimage(Rectangle, ulong, int, ulong);
+void	updatedraw(void);
+void	redraw(void);
+void	resetdraw(void);
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,12 @@
+</$objtype/mkfile
+TARG=\
+	3d01\
+
+OFILES=\
+	drw.$O\
+	sys.$O\
+
+HFILES=dat.h fns.h
+</sys/src/cmd/mkmany
+BIN=$home/bin/$objtype
+HFILES=
--- /dev/null
+++ b/sys.c
@@ -1,0 +1,192 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <keyboard.h>
+#include <mouse.h>
+#include "dat.h"
+#include "fns.h"
+
+void (*stepsimfn)(void);
+
+typedef struct Kev Kev;
+typedef struct Mev Mev;
+struct Kev{
+	int down;
+	Rune r;
+};
+struct Mev{
+	Point;
+	int dx;
+	int dy;
+	int b;
+};
+static Channel *reszc, *kc, *mc, *tmc;
+
+void *
+emalloc(ulong n)
+{
+	void *p;
+
+	if((p = mallocz(n, 1)) == nil)
+		sysfatal("emalloc: %r");
+	setmalloctag(p, getcallerpc(&n));
+	return p;
+}
+
+static void
+mproc(void *)
+{
+	int n, fd, nerr;
+	char buf[1+5*12];
+	Mev m, om;
+
+	if((fd = open("/dev/mouse", OREAD)) < 0)
+		sysfatal("mproc: %r");
+	nerr = 0;
+	memset(&om, 0, sizeof om);
+	for(;;){
+		if((n = read(fd, buf, sizeof buf)) != 1+4*12){
+			if(n < 0 || ++nerr > 10)
+				break;
+			fprint(2, "mproc: bad count %d not 49: %r\n", n);
+			continue;
+		}
+		nerr = 0;
+		switch(buf[0]){
+		case 'r': send(reszc, nil); /* wet floor */
+		case 'm':
+			m.x = strtol(buf+1+12*0, nil, 10);
+			m.y = strtol(buf+1+12*1, nil, 10);
+			m.b = strtol(buf+1+12*2, nil, 10);
+			m.dx = m.x - om.x;
+			m.dy = m.y - om.y;
+			if((m.b & 1) == 1 && (om.b & 1) == 0
+			|| (m.b & 4) == 4 && (om.b & 4) == 0
+			|| m.b & 2)
+				send(mc, &m);
+			om = m;
+			break;
+		}
+	}
+}
+
+static void
+kproc(void *)
+{
+	int n, fd;
+	char buf[256], down[128], *s, *p;
+	Rune r;
+	Kev ke;
+
+	if((fd = open("/dev/kbd", OREAD)) < 0)
+		sysfatal("kproc: %r");
+	memset(buf, 0, sizeof buf);
+	for(;;){
+		if(buf[0] != 0){
+			n = strlen(buf)+1;
+			memmove(buf, buf+n, sizeof(buf)-n);
+		}
+		if(buf[0] == 0){
+			n = read(fd, buf, sizeof(buf)-1);
+			if(n <= 0)
+				break;
+			buf[n-1] = 0;
+			buf[n] = 0;
+		}
+		switch(buf[0]){
+		default: continue;
+		case 'k': s = buf+1; p = down+1; ke.down = 1; break;
+		case 'K': s = down+1; p = buf+1; ke.down = 0; break;
+		}
+		while(*s != 0){
+			s += chartorune(&r, s);
+			if(utfrune(p, r) == nil){
+				ke.r = r;
+				if(send(kc, &ke) < 0)
+					break;
+			}
+		}
+		strcpy(down, buf);
+	}
+}
+
+static void
+timeproc(void *)
+{
+	for(;;){
+		sleep(tdiv);
+		nbsendul(tmc, 0);
+	}
+}
+
+
+void
+sim(void)
+{
+	Kev ke;
+	Mev me;
+	Key *k;
+
+	enum{
+		Aresize,
+		Amouse,
+		Akbd,
+		Atic,
+	};
+	Alt a[] = {
+		{reszc, nil, CHANRCV},
+		{mc, &me, CHANRCV},
+		{kc, &ke, CHANRCV},
+		{tmc, nil, CHANRCV},
+		{nil, nil, CHANEND}
+	};
+	for(;;){
+		switch(alt(a)){
+		case Aresize:
+			if(getwindow(display, Refnone) < 0)
+				sysfatal("resize failed: %r");
+			resetdraw();
+			break;
+		case Amouse:
+			break;
+		case Akbd:
+			if(ke.r == Kdel)
+				threadexitsall(nil);
+			for(k=keys; k<keys+nkeys; k++)
+				if(ke.r == k->r){
+					k->down = ke.down;
+					break;
+				}
+			break;
+		case Atic:
+			stepsimfn();
+			updatedraw();
+			break;
+		}
+	}
+}
+
+void
+sysinit(void (*initrender)(void), void (*initsim)(void), void (*render)(void), void (*stepsim)(void))
+{
+	srand(time(nil));
+	if(initdraw(nil, nil, progname) < 0)
+		sysfatal("initdraw: %r");
+	if((reszc = chancreate(sizeof(int), 2)) == nil
+	|| (kc = chancreate(sizeof(Kev), 20)) == nil
+	|| (mc = chancreate(sizeof(Mev), 20)) == nil)
+		sysfatal("chancreate: %r");
+	if(proccreate(kproc, nil, 8192) < 0
+	|| proccreate(mproc, nil, 8192) < 0)
+		sysfatal("proccreate: %r");
+	if((tmc = chancreate(sizeof(ulong), 0)) == nil)
+		sysfatal("chancreate: %r");
+	if(proccreate(timeproc, nil, 8192) < 0)
+		sysfatal("init: %r");
+	initrender();
+	initsim();
+	renderfn = render;
+	stepsimfn = stepsim;
+	resetdraw();
+}