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);