shithub: city

Download patch

ref: 32b89da7cd004d14f1641cbd6bd32f0ec6b97b20
parent: 063901a12ba4031e700716f193818a88a25439b2
author: qwx <qwx@sciops.net>
date: Sun Feb 21 18:19:02 EST 2021

basic input and drawing

--- a/city.c
+++ b/city.c
@@ -1,10 +1,16 @@
 #include <u.h>
 #include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include <mouse.h>
+#include <keyboard.h>
 #include "dat.h"
 #include "fns.h"
 
-int tdiv;
-vlong clock;
+static int tdiv;
+static Keyboardctl *kc;
+static Mousectl *mc;
+static Channel *tmc;
 
 void *
 emalloc(ulong n)
@@ -17,34 +23,68 @@
 	return p;
 }
 
-void
-input(void)
+static void
+timeproc(void *)
 {
-
+	tdiv = 1000 / AnimHz;
+	for(;;){
+		sleep(tdiv);
+		nbsendul(tmc, 0);
+	}
 }
 
 void
-main(int argc, char **argv)
+threadmain(int argc, char **argv)
 {
-	vlong t, t0, dt, Δtc;
+	Rune r;
+	Mouse mo;
 
 	ARGBEGIN{
 	}ARGEND
-	srand(time(nil));
 	init();
-	tdiv = Te9 / THz;
-	t0 = nsec();
+	initdrw();
+	if((kc = initkeyboard(nil)) == nil)
+		sysfatal("initkeyboard: %r");
+	if((mc = initmouse(nil, screen)) == nil)
+		sysfatal("initmouse: %r");
+	if((tmc = chancreate(sizeof(ulong), 0)) == nil)
+		sysfatal("chancreate: %r");
+	if(proccreate(timeproc, nil, 8192) < 0)
+		sysfatal("init: %r");
+	startsim();
+	enum{
+		Aresize,
+		Amouse,
+		Akbd,
+		Aanim,
+	};
+	Alt a[] = {
+		{mc->resizec, nil, CHANRCV},
+		{mc->c, &mc->Mouse, CHANRCV},
+		{kc->c, &r, CHANRCV},
+		{tmc, nil, CHANRCV},
+		{nil, nil, CHANEND}
+	};
 	for(;;){
-		input();
-		step();
-		clock++;
-		t = nsec();
-		Δtc = (t - t0) / tdiv;
-		if(Δtc <= 0)
-			Δtc = 1;
-		t0 += Δtc * tdiv;
-		dt = (t0 - t) / Te6;
-		if(dt > 0)
-			sleep(dt);
+		switch(alt(a)){
+		case Aresize:
+			if(getwindow(display, Refnone) < 0)
+				sysfatal("resize failed: %r");
+			mo = mc->Mouse;
+			resetdraw();
+			break;
+		case Amouse:
+			break;
+		case Akbd:
+			switch(r){
+			case Kdel:
+			case 'q': threadexitsall(nil);
+			case ' ': paused ^= 1; break;
+			}
+			break;
+		case Aanim:
+			updatedraw();
+			break;
+		}
 	}
 }
--- a/dat.h
+++ b/dat.h
@@ -107,6 +107,7 @@
 	vlong prodΔt;
 	vlong supplyΔt;
 	vlong pickupΔt;
+	int stale;
 };
 extern Tile *map;
 extern int mapwidth, mapheight;
@@ -114,8 +115,9 @@
 enum{
 	Te9 = 1000000000,
 	Te6 = 1000000,
-	THz = 5,
+	SimHz = 5,
+	AnimHz = 1,
 	Travelticks = 10,
 };
-extern int tdiv;
 extern vlong clock;
+extern int paused;
--- a/drw.c
+++ b/drw.c
@@ -1,4 +1,83 @@
 #include <u.h>
 #include <libc.h>
+#include <draw.h>
 #include "dat.h"
 #include "fns.h"
+
+QLock drwlock;
+
+static char *fontname = "/lib/font/bit/fixed/unicode.6x10.font";
+
+static Rectangle fbr;
+static Image *fb;
+
+static 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
+drawtile(Tile *m)
+{
+	char *s;
+	Point p;
+
+	p.x = (m - map) % mapwidth * 16 * font->width;
+	p.y = (m - map) / mapwidth * 2 * font->height;
+	s = m->b != nil ? m->b->name : m->t->name;
+	string(fb, p, display->white, ZP, font, s);
+}
+
+void
+updatedraw(void)
+{
+	int bail;
+	Tile *m;
+
+	bail = 1;
+	qlock(&drwlock);
+	for(m=map; m<map+mapwidth*mapheight; m++)
+		if(m->stale){
+			bail = 0;
+			drawtile(m);
+			m->stale = 0;
+		}
+	qunlock(&drwlock);
+	if(bail)
+		return;
+	draw(screen, screen->r, fb, nil, ZP);
+	flushimage(display, 1);
+}
+
+void
+redraw(void)
+{
+	Tile *m;
+
+	draw(fb, fb->r, display->black, nil, ZP);
+	for(m=map; m<map+mapwidth*mapheight; m++)
+		m->stale = 1;
+	updatedraw();
+}
+
+void
+resetdraw(void)
+{
+	freeimage(fb);
+	fbr = rectsubpt(screen->r, screen->r.min);
+	fb = eallocimage(fbr, screen->chan, 0, DNofill);
+	redraw();
+}
+
+void
+initdrw(void)
+{
+	if(initdraw(nil, fontname, "city") < 0)
+		sysfatal("initdraw: %r");
+	resetdraw();
+}
--- a/fns.h
+++ b/fns.h
@@ -1,6 +1,9 @@
 void*	emalloc(ulong);
 void	init(void);
 void	initmap(void);
-void	step(void);
-void	input(void);
 int	mhdist(int, int, int, int);
+void	startsim(void);
+void	initdrw(void);
+void	resetdraw(void);
+void	redraw(void);
+void	updatedraw(void);
--- a/mkfile
+++ b/mkfile
@@ -4,6 +4,7 @@
 OFILES=\
 	city.$O\
 	defs.$O\
+	drw.$O\
 	map.$O\
 	sim.$O\
 
--- a/sim.c
+++ b/sim.c
@@ -1,8 +1,16 @@
 #include <u.h>
 #include <libc.h>
+#include <thread.h>
 #include "dat.h"
 #include "fns.h"
 
+extern QLock drwlock;
+
+int paused;
+vlong clock;
+
+static int tdiv;
+
 static Tile **objs, **objhead;
 static int maxobj;
 
@@ -179,14 +187,47 @@
 	}
 }
 
-void
+static void
 step(void)
 {
+	if(paused)
+		return;
+	qlock(&drwlock);
 	upkeep();
 	updateobj();
+	qunlock(&drwlock);
 }
 
 static void
+simproc(void *)
+{
+	int Δtc;
+	vlong t, t0, dt;
+
+	tdiv = Te9 / SimHz;
+	t0 = nsec();
+	for(;;){
+		step();
+		clock++;
+		t = nsec();
+		Δtc = (t - t0) / tdiv;
+		if(Δtc <= 0)
+			Δtc = 1;
+		t0 += Δtc * tdiv;
+		dt = (t0 - t) / Te6;
+		if(dt > 0)
+			sleep(dt);
+	}
+}
+
+void
+startsim(void)
+{
+	if(proccreate(simproc, nil, 8192) < 0)
+		sysfatal("init: %r");
+}
+
+static void
 calcdists(int n)
 {
 	int x, y, x´, y´;
@@ -208,6 +249,7 @@
 {
 	int i, n;
 
+	srand(time(nil));
 	initmap();
 	maxobj = mapwidth * mapheight;
 	objs = emalloc(maxobj * sizeof *objs);