ref: 694039a3792bd62ac8e086ac710dddd553333bb6
parent: 13e4185989d42efd2d2dad6daddb67a61a55d94d
author: qwx <qwx@sciops.net>
date: Thu Feb 25 18:10:04 EST 2021
sv: decouple simulation from input and drawing the timeproc shit sucks, but not sure how to do this better. redrawing should occur immediately when input changes shit (like panning) even when simulation time is slow, but then it shouldn't redraw on every single mouse event, so instead just try to keep to some framerate as usual. seems sloppy somehow though.
--- a/dat.h
+++ b/dat.h
@@ -196,8 +196,14 @@
Tquit,
};
+enum{
+ Te9 = 1000000000,
+ Te6 = 1000000,
+ Te3 = 1000,
+
+ Tfast = 6,
+};
extern char *progname, *prefix, *dbname, *mapname;
-extern int clon;
extern vlong tc;
extern int pause, debugmap;
extern int debug;
--- a/drw.c
+++ b/drw.c
@@ -4,6 +4,8 @@
#include "dat.h"
#include "fns.h"
+extern QLock drawlock;
+
int scale = 1;
static Point p0, pan;
@@ -16,11 +18,11 @@
static Mobj **visbuf;
static int nvisbuf, nvis;
-void
-dopan(int dx, int dy)
+int
+dopan(Point p)
{
- pan.x -= dx;
- pan.y -= dy;
+ pan.x -= p.x;
+ pan.y -= p.y;
if(pan.x < 0)
pan.x = 0;
else if(pan.x > panmax.x)
@@ -29,36 +31,43 @@
pan.y = 0;
else if(pan.y > panmax.y)
pan.y = panmax.y;
+ return 1;
}
-void
-select(Point p, int b)
+int
+select(Point p)
{
int i;
+
+ if(!ptinrect(p, selr))
+ return 0;
+ p = divpt(subpt(p, selr.min), scale);
+ i = fbvis[p.y * fbw + p.x];
+ selected[0] = i == -1 ? nil : visbuf[i];
+ return 1;
+}
+
+int
+move(Point p)
+{
+ int i;
Point vp;
Mobj *mo;
- if(!ptinrect(p, selr))
- return;
- if(b & 1){
- p = divpt(subpt(p, selr.min), scale);
- i = fbvis[p.y * fbw + p.x];
- selected[0] = i == -1 ? nil : visbuf[i];
- }else if(b & 4){
- if(selected[0] == nil)
- return;
- vp = divpt(subpt(p, selr.min), scale);
- i = fbvis[vp.y * fbw + vp.x];
- mo = i == -1 ? nil : visbuf[i];
- if(mo == selected[0]){
- dprint("select: %#p not moving to itself\n", visbuf[i]);
- return;
- }
- p = divpt(addpt(subpt(p, selr.min), pan), scale);
- p.x /= Tlsubwidth;
- p.y /= Tlsubheight;
- moveone(p, selected[0], mo);
+ if(!ptinrect(p, selr) || selected[0] == nil)
+ return 0;
+ vp = divpt(subpt(p, selr.min), scale);
+ i = fbvis[vp.y * fbw + vp.x];
+ mo = i == -1 ? nil : visbuf[i];
+ if(mo == selected[0]){
+ dprint("select: %#p not moving to itself\n", visbuf[i]);
+ return 0;
}
+ p = divpt(addpt(subpt(p, selr.min), pan), scale);
+ p.x /= Tlsubwidth;
+ p.y /= Tlsubheight;
+ moveone(p, selected[0], mo);
+ return 1;
}
static void
@@ -371,6 +380,15 @@
if(debugmap)
drawmap(&mr);
drawhud();
+}
+
+void
+updatefb(void)
+{
+ qlock(&drawlock);
+ redraw();
+ qunlock(&drawlock);
+ drawfb();
}
void
--- a/fns.h
+++ b/fns.h
@@ -3,19 +3,23 @@
void linktomap(Mobj*);
int moveone(Point, Mobj*, Mobj*);
void stepsim(void);
-void initsv(void);
+void initsim(void);
+void initsv(int, char*);
void flushcl(void);
void packcl(char*, ...);
void stepnet(void);
void joinnet(char*);
void listennet(void);
-void dopan(int, int);
+int dopan(Point);
+int select(Point);
+int move(Point);
void compose(int, int, u32int);
void redraw(void);
+void updatefb(void);
void resetfb(void);
void drawfb(void);
void initimg(void);
-void init(void);
+void initfs(void);
void setgoal(Point*, Mobj*, Mobj*);
int isblocked(int, int, Obj*);
void markmobj(Mobj*, int);
--- a/fs.c
+++ b/fs.c
@@ -614,12 +614,11 @@
}
void
-init(void)
+initfs(void)
{
if(bind(".", prefix, MBEFORE|MCREATE) == -1 || chdir(prefix) < 0)
fprint(2, "init: %r\n");
loaddb(dbname);
loaddb(mapname);
- srand(time(nil));
initdb();
}
--- a/mkfile
+++ b/mkfile
@@ -12,6 +12,7 @@
sce.$O\
sim.$O\
snd.$O\
+ sv.$O\
util.$O\
HFILES=dat.h fns.h
--- a/sce.c
+++ b/sce.c
@@ -8,14 +8,15 @@
#include "dat.h"
#include "fns.h"
-void select(Point, int);
-
mainstacksize = 16*1024;
+enum{
+ Hz = 60,
+};
+
char *progname = "sce", *dbname, *prefix, *mapname = "map1.db";
-int clon;
-vlong tc;
int pause, debugmap;
+QLock drawlock;
typedef struct Kev Kev;
typedef struct Mev Mev;
@@ -25,19 +26,11 @@
};
struct Mev{
Point;
- int dx;
- int dy;
+ Point Δ;
int b;
};
-enum{
- Te9 = 1000000000,
- Te6 = 1000000,
- Tfast = 6,
-};
-static int tv = Tfast, tdiv;
-static vlong Δtc;
-static Channel *reszc, *kc, *mc;
+static Channel *reszc, *kc, *mc, *tmc;
static void
mproc(void *)
@@ -64,8 +57,8 @@
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;
+ m.Δ.x = m.x - om.x;
+ m.Δ.y = m.y - om.y;
if((m.b & 1) == 1 && (om.b & 1) == 0
|| (m.b & 4) == 4 && (om.b & 4) == 0
|| m.b & 2)
@@ -117,84 +110,49 @@
}
static void
-quit(void)
+timeproc(void *)
{
- packcl("u", Tquit);
- flushcl();
- threadexitsall(nil);
-}
+ int tdiv;
+ vlong t, t0, dt, Δtc;
-static void
-input(void)
-{
- Kev ke;
- Mev me;
-
- if(nbrecv(reszc, nil) != 0){
- if(getwindow(display, Refnone) < 0)
- sysfatal("resize failed: %r");
- resetfb();
+ tdiv = Te9 / Hz;
+ t0 = nsec();
+ for(;;){
+ nbsendul(tmc, 0);
+ t = nsec();
+ Δtc = (t - t0) / tdiv;
+ if(Δtc <= 0)
+ Δtc = 1;
+ t0 += Δtc * tdiv;
+ dt = (t0 - t) / Te6;
+ if(dt > 0)
+ sleep(dt);
}
- while(nbrecv(mc, &me) > 0){
- if(me.b & 5)
- select(me, me.b);
- if(me.b & 2)
- dopan(me.dx, me.dy);
- }
- while(nbrecv(kc, &ke) > 0){
- if(!ke.down)
- continue;
- switch(ke.r){
- case KF|1: debugmap ^= 1; pause ^= 1; break;
- case ' ': pause ^= 1; break;
- case Kdel: quit(); break;
- }
- }
}
static void
-stepcl(void)
-{
- if(!clon)
- return;
- input();
- flushcl();
- redraw();
- drawfb();
- stepsnd();
-}
-
-static void
initcl(void)
{
- clon = 1;
if(initdraw(nil, nil, progname) < 0)
sysfatal("initdraw: %r");
+ initsnd();
+ initimg();
+ resetfb();
if((reszc = chancreate(sizeof(int), 2)) == nil
|| (kc = chancreate(sizeof(Kev), 20)) == nil
- || (mc = chancreate(sizeof(Mev), 20)) == nil)
+ || (mc = chancreate(sizeof(Mev), 20)) == nil
+ || (tmc = chancreate(sizeof(ulong), 0)) == nil)
sysfatal("chancreate: %r");
if(proccreate(kproc, nil, 8192) < 0
- || proccreate(mproc, nil, 8192) < 0)
+ || proccreate(mproc, nil, 8192) < 0
+ || proccreate(timeproc, nil, 8192) < 0)
sysfatal("proccreate: %r");
- initsnd();
- initimg();
- resetfb();
}
static void
-step(void)
-{
- stepnet();
- stepcl();
- while(!pause && Δtc-- > 0)
- stepsim();
-}
-
-static void
usage(void)
{
- fprint(2, "usage: %s [-D] [-l port] [-m map] [-n name] [-s scale] [-t speed] [-x netmtpt] [sys]\n", argv0);
+ fprint(2, "usage: %s [-D] [-P port] [-m map] [-n name] [-s scale] [-t speed] [-x netmtpt] [sys]\n", argv0);
threadexits("usage");
}
@@ -201,11 +159,14 @@
void
threadmain(int argc, char **argv)
{
- vlong t, t0, dt;
+ int tv;
+ Kev ke;
+ Mev me;
+ tv = Tfast;
ARGBEGIN{
case 'D': debug = 1; break;
- case 'l': lport = strtol(EARGF(usage()), nil, 0); break;
+ case 'P': lport = strtol(EARGF(usage()), nil, 0); break;
case 'm': mapname = EARGF(usage()); break;
case 'n': progname = EARGF(usage()); break;
case 's':
@@ -230,23 +191,54 @@
dbname = smprint("%s.db", progname);
if(prefix == nil)
prefix = smprint("/sys/games/lib/%s", progname);
- init();
- initsv();
+ srand(time(nil));
+ initfs();
+ initsv(tv, *argv);
initcl();
- joinnet(*argv);
- tdiv = Te9 / (tv * 3);
- Δtc = 1;
- t0 = nsec();
+ enum{
+ Aresize,
+ Amouse,
+ Akbd,
+ Atic,
+ Aend,
+ };
+ Alt a[] = {
+ {reszc, nil, CHANRCV},
+ {mc, &me, CHANRCV},
+ {kc, &ke, CHANRCV},
+ {tmc, nil, CHANRCV},
+ {nil, nil, CHANEND}
+ };
for(;;){
- step();
- tc += 1;
- 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");
+ resetfb();
+ break;
+ case Amouse:
+ qlock(&drawlock); /* just for security */
+ if(me.b & 1)
+ select(me);
+ if(me.b & 2)
+ dopan(me.Δ);
+ if(me.b & 4)
+ move(me);
+ qunlock(&drawlock);
+ break;
+ case Akbd:
+ if(ke.r == Kdel)
+ threadexitsall(nil);
+ if(!ke.down)
+ continue;
+ switch(ke.r){
+ case KF|1: debugmap ^= 1; pause ^= 1; break;
+ case ' ': pause ^= 1; break;
+ }
+ break;
+ case Atic:
+ updatefb();
+ break;
+ }
}
}
--- a/sim.c
+++ b/sim.c
@@ -338,7 +338,7 @@
stepmove(oml->mo);
}
-static void
+void
initsim(void)
{
Team *t;
@@ -347,11 +347,4 @@
sysfatal("initgame: the only winning move is not to play");
for(t=team; t<=team+nteam; t++)
memcpy(t->r, initres, sizeof initres);
-}
-
-void
-initsv(void)
-{
- initsim();
- listennet();
}
--- /dev/null
+++ b/sv.c
@@ -1,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+extern QLock drawlock;
+
+vlong tc;
+
+static int tdiv;
+
+static void
+step(vlong tics)
+{
+ qlock(&drawlock);
+ while(!pause && tics-- > 0)
+ stepsim();
+ qunlock(&drawlock);
+}
+
+static void
+simproc(void *sys)
+{
+ vlong t, t0, dt, Δtc;
+
+ USED(sys);
+ initsim();
+ Δtc = 1;
+ t0 = nsec();
+ for(;;){
+ step(Δtc);
+ tc += 1;
+ t = nsec();
+ Δtc = (t - t0) / tdiv;
+ if(Δtc <= 0)
+ Δtc = 1;
+ t0 += Δtc * tdiv;
+ dt = (t0 - t) / Te6;
+ if(dt > 0)
+ sleep(dt);
+ }
+}
+
+void
+initsv(int tv, char *sys)
+{
+ tdiv = Te9 / (tv * 3);
+ if(proccreate(simproc, sys, 8192) < 0)
+ sysfatal("proccreate: %r");
+}