shithub: musw

Download patch

ref: 9942eb201a657640cf244b261008b850352a29f3
parent: d85705bf67be2a23e3d928f9670732be5484f958
author: rodri <rgl@antares-labs.eu>
date: Wed Jul 28 18:15:15 EDT 2021

brought the Sprite struct for future animations.
implemented per-party game state and dynamics.
now the state is broadcast after integration, not before.
fixed a bug in the broadcast procedure where it would keep referencing an already freed Party and its players.
implemented a proper Keymap the user will be able to configure.
added mkfile rules to manage installation and dependencies.
defined a ton of structs in dat.h for new game objects.
started work on a general vector model abstraction to define ship `skins'.
removed some debug clauses we no longer need. fixed some other ones.

diff: cannot open b/assets/mdl//null: file does not exist: 'b/assets/mdl//null' diff: cannot open b/assets//null: file does not exist: 'b/assets//null'
--- /dev/null
+++ b/assets/mdl/needle.vmdl
@@ -1,0 +1,14 @@
+# The Needle vector model
+
+v  10  0
+v   8 -4
+v -10 -6
+v -12  0
+v -10  6
+v   8  4
+
+l 1 2
+l 2 3
+c 3 4 5
+l 5 6
+l 6 1
--- a/dat.h
+++ b/dat.h
@@ -1,3 +1,28 @@
+typedef enum
+{
+	K↑,
+	K↺,
+	K↻,
+	Kfire,
+	Khyper,
+	Ksay,
+	Kquit,
+	NKEYOPS
+} KeyOp;
+
+typedef enum
+{
+	NEEDLE,
+	WEDGE
+} Kind;
+
+typedef struct Vector Vector;
+typedef struct VModel VModel;
+typedef struct Sprite Sprite;
+typedef struct Particle Particle;
+typedef struct Ship Ship;
+typedef struct Star Star;
+typedef struct Universe Universe;
 typedef struct GameState GameState;
 typedef struct Derivative Derivative;
 typedef struct Conn Conn;
@@ -5,8 +30,72 @@
 typedef struct Lobby Lobby;
 typedef struct Party Party;
 
+struct Vector
+{
+	double x, y;
+};
+
+/*
+ * Vector model - made out of lines and curves
+ */
+struct VModel
+{
+	Vector *pts;
+	ulong npts;
+	/* WIP
+	 * l(ine) → takes 2 points
+	 * c(urve) → takes 3 points
+	 */
+//	char *strokefmt;
+};
+
+struct Sprite
+{
+	Image *sheet;
+	Point sp;
+	Rectangle r;
+	int nframes;
+	int curframe;
+	ulong period;
+	ulong elapsed;
+
+	void (*step)(Sprite*, ulong);
+	void (*draw)(Sprite*, Image*, Point);
+};
+
+struct Particle
+{
+	Vector p, v;
+	double yaw;
+	double mass;
+};
+
+struct Ship
+{
+	Particle;
+	Kind kind;
+	uint ammo;
+	VModel *mdl;
+//	Matrix mdlxform;
+};
+
+struct Star
+{
+	Particle;
+	Sprite spr;
+};
+
+struct Universe
+{
+	Ship ships[2];
+	Star star;
+
+	int (*step)(Universe*);
+};
+
 struct GameState
 {
+	double t, timeacc;
 	double x, v;
 };
 
@@ -43,7 +132,12 @@
 struct Party
 {
 	Player players[2];	/* the needle and the wedge */
+	Universe *u;
 	Party *prev, *next;
+
+	/* testing */
+	GameState state;
 };
+
 
 extern Party theparty;
--- a/fns.h
+++ b/fns.h
@@ -30,7 +30,7 @@
 void dellobby(Lobby*);
 
 /*
- * lobby
+ * party
  */
 void inittheparty(void);
 Party *newparty(Player[2]);
--- a/lobby.c
+++ b/lobby.c
@@ -1,5 +1,6 @@
 #include <u.h>
 #include <libc.h>
+#include <draw.h> /* because of dat.h */
 #include "dat.h"
 #include "fns.h"
 
--- a/mkfile
+++ b/mkfile
@@ -1,5 +1,6 @@
 </$objtype/mkfile
 
+MAN=/sys/man/1
 BIN=/$objtype/bin/games
 TARG=\
 	musw\
@@ -17,4 +18,22 @@
 	dat.h\
 	fns.h\
 
+LIB=\
+	libgeometry/libgeometry.a$O\
+
 </sys/src/cmd/mkmany
+
+libgeometry/libgeometry.a$O: pulldeps
+	cd libgeometry
+	mk install
+
+pulldeps:V:
+	! test -d libgeometry && git/clone https://github.com/sametsisartenep/libgeometry || echo >/dev/null
+
+install:V: man
+
+uninstall:V:
+	for(i in $TARG){
+		rm -f $BIN/$i
+		rm -f $MAN/$i
+	}
--- a/musw.c
+++ b/musw.c
@@ -7,23 +7,24 @@
 #include "dat.h"
 #include "fns.h"
 
-enum {
-	K↑,
-	K←,
-	K→,
-	Kfire,
-	Khyper,
-	Kquit,
-	NKEYS
+typedef struct Keymap Keymap;
+struct Keymap
+{
+	Rune key;
+	KeyOp op;
 };
 
-Rune keys[NKEYS] = {
- [K↑]		Kup,
- [K←]		Kleft,
- [K→]		Kright,
- [Kfire]	' ',
- [Khyper]	'h',
- [Kquit]	'q'
+Keymap kmap[] = {
+	{.key = Kup,	.op = K↑},
+	{.key = Kleft,	.op = K↺},
+	{.key = Kright,	.op = K↻},
+	{.key = 'w',	.op = K↑},
+	{.key = 'a',	.op = K↺},
+	{.key = 'd',	.op = K↻},
+	{.key = ' ',	.op = Kfire},
+	{.key = 'h',	.op = Khyper},
+	{.key = 'y',	.op = Ksay},
+	{.key = 'q',	.op = Kquit}
 };
 ulong kup, kdown;
 
@@ -40,7 +41,8 @@
 void
 kbdproc(void *)
 {
-	Rune r, *k;
+	Rune r;
+	Keymap *k;
 	char buf[128], *s;
 	int fd, n;
 
@@ -74,9 +76,9 @@
 		kdown = 0;
 		while(*s){
 			s += chartorune(&r, s);
-			for(k = keys; k < keys+NKEYS; k++)
-				if(r == *k){
-					kdown |= 1 << k-keys;
+			for(k = kmap; k < kmap+nelem(kmap); k++)
+				if(r == k->key){
+					kdown |= 1 << k->op;
 					break;
 				}
 		}
@@ -83,7 +85,8 @@
 		kup = ~kdown;
 
 		if(debug)
-			fprint(2, "kup\t%lub\nkdown\t%lub\n", kup, kdown);
+			fprint(2, "kup   %.*lub\nkdown %.*lub\n",
+				sizeof(kup)*8, kup, sizeof(kdown)*8, kdown);
 	}
 }
 
--- a/muswd.c
+++ b/muswd.c
@@ -1,14 +1,12 @@
 #include <u.h>
 #include <libc.h>
 #include <thread.h>
+#include <draw.h> /* because of dat.h */
 #include "dat.h"
 #include "fns.h"
 
 int debug;
 
-GameState state;
-double t, Δt;
-
 Lobby *lobby;
 
 
@@ -68,28 +66,31 @@
 {
 	int i, n;
 	uchar buf[256];
-	Party *p;
+	Player *player;
+	Party *p, *np;
 
-	if(debug)
-		fprint(2, "state: x=%g v=%g\n", state.x, state.v);
+	for(p = theparty.next; p != &theparty; p = p->next){
+		n = pack(buf, sizeof buf, "dd", p->state.x, p->state.v);
 
-	for(p = theparty.next; p != &theparty; p = p->next)
 		for(i = 0; i < nelem(p->players); i++){
-			n = pack(buf, sizeof buf, "dd", state.x, state.v);
 			if(write(p->players[i].conn.data, buf, n) != n){
-				lobby->takeseat(lobby, p->players[i^1].conn.dir, p->players[i^1].conn.ctl, p->players[i^1].conn.data);
+				player = &p->players[i^1];
+				lobby->takeseat(lobby, player->conn.dir, player->conn.ctl, player->conn.data);
+				np = p->prev;
 				delparty(p);
+				p = np;
+				break;
 			}
 		}
+	}
 
 }
 
 void
-resetsim(void)
+resetsim(Party *p)
 {
-	t = 0;
-	memset(&state, 0, sizeof state);
-	state.x = 100;
+	memset(&p->state, 0, sizeof p->state);
+	p->state.x = 100;
 }
 
 void
@@ -96,50 +97,40 @@
 threadsim(void *)
 {
 	uvlong then, now;
-	double frametime, timeacc;
+	double frametime, Δt;
 	Ioproc *io;
 	Player couple[2];
+	Party *p;
 
 	Δt = 0.01;
 	then = nanosec();
-	timeacc = 0;
 	io = ioproc();
 
-	resetsim();
-
 	for(;;){
 		lobby->healthcheck(lobby);
 
-		if(debug){
-			Party *p;
-			ulong nparties = 0;
-
-			for(p = theparty.next; p != &theparty; p = p->next)
-				nparties++;
-
-			fprint(2, "lobby status: %lud conns at %lud cap\n",
-				lobby->nseats, lobby->cap);
-			fprint(2, "party status: %lud parties going on\n",
-				nparties);
+		if(lobby->getcouple(lobby, couple) != -1){
+			newparty(couple);
+			resetsim(theparty.prev); /* reset the new party */
 		}
 
-		if(lobby->getcouple(lobby, couple) != -1)
-			newparty(couple);
-
-		broadcaststate();
-
 		now = nanosec();
 		frametime = now - then;
 		then = now;
-		timeacc += frametime/1e9;
 
-		while(timeacc >= Δt){
-			integrate(&state, t, Δt);
-			timeacc -= Δt;
-			t += Δt;
+		for(p = theparty.next; p != &theparty; p = p->next){
+			p->state.timeacc += frametime/1e9;
+
+			while(p->state.timeacc >= Δt){
+				integrate(&p->state, p->state.t, Δt);
+				p->state.timeacc -= Δt;
+				p->state.t += Δt;
+			}
 		}
 
-		iosleep(io, FPS2MS(1));
+		broadcaststate();
+
+		iosleep(io, FPS2MS(70));
 	}
 }
 
@@ -146,8 +137,8 @@
 void
 fprintstats(int fd)
 {
-	Party *p;
 	ulong nparties = 0;
+	Party *p;
 
 	for(p = theparty.next; p != &theparty; p = p->next)
 		nparties++;
@@ -162,11 +153,14 @@
 }
 
 void
-fprintstate(int fd)
+fprintstates(int fd)
 {
-	fprint(fd, "x	%g\n"
-		   "v	%g\n",
-		state.x, state.v);
+	ulong i = 0;
+	Party *p;
+
+	for(p = theparty.next; p != &theparty; p = p->next, i++)
+		fprint(fd, "%lud [x %g	v %g]\n",
+			i, p->state.x, p->state.v);
 }
 
 
@@ -200,8 +194,8 @@
 			if(strcmp(cmdargs[0], "show") == 0){
 				if(strcmp(cmdargs[1], "stats") == 0)
 					fprintstats(pfd[1]);
-				else if(strcmp(cmdargs[1], "state") == 0)
-					fprintstate(pfd[1]);
+				else if(strcmp(cmdargs[1], "states") == 0)
+					fprintstates(pfd[1]);
 			}
 		}
 	}
@@ -221,7 +215,7 @@
 	int acfd;
 	char adir[40], *addr;
 
-	addr = "udp!*!112";
+	addr = "tcp!*!112"; /* for testing. will work out udp soon */
 	ARGBEGIN{
 	case 'a':
 		addr = EARGF(usage());
--- a/pack.c
+++ b/pack.c
@@ -1,5 +1,6 @@
 #include <u.h>
 #include <libc.h>
+#include <draw.h> /* because of dat.h */
 #include "dat.h"
 #include "fns.h"
 
--- a/party.c
+++ b/party.c
@@ -1,5 +1,6 @@
 #include <u.h>
 #include <libc.h>
+#include <draw.h> /* because of dat.h */
 #include "dat.h"
 #include "fns.h"
 
--- a/physics.c
+++ b/physics.c
@@ -1,24 +1,17 @@
 #include <u.h>
 #include <libc.h>
-#include <draw.h>
+#include <draw.h> /* because of dat.h */
 #include "dat.h"
 #include "fns.h"
 
-//enum { DYNTIME, RENTIME, NSTATS };
-//Stats simstats[NSTATS];
-
-
 /*
  *	Dynamics stepper
- *
- * 	Currently set to a basic spring-damper system.
  */
 static double
-accel(GameState *s, double t)
+accel(GameState *s, double)
 {
 	static double k = 15, b = 0.1;
 
-	USED(t);
 	return -k*s->x - b*s->v;
 }
 
--- /dev/null
+++ b/sprite.c
@@ -1,0 +1,72 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include "dat.h"
+#include "fns.h"
+
+static void
+sprite_step(Sprite *spr, ulong Δt)
+{
+	if(spr->nframes < 2)
+		return;
+
+	spr->elapsed += Δt;
+
+	if(spr->elapsed >= spr->period){
+		spr->elapsed -= spr->period;
+		spr->curframe = ++spr->curframe % spr->nframes;
+	}
+}
+
+static void
+sprite_draw(Sprite *spr, Image *dst, Point dp)
+{
+	Point sp = (Point){
+		spr->curframe * Dx(spr->r),
+		0
+	};
+	sp = addpt(spr->sp, sp);
+
+	draw(dst, rectaddpt(spr->r, dp), spr->sheet, nil, sp);
+}
+
+Sprite *
+newsprite(Image *sheet, Point sp, Rectangle r, int nframes, ulong period)
+{
+	Sprite *spr;
+
+	spr = emalloc(sizeof(Sprite));
+	spr->sheet = sheet;
+	spr->sp = sp;
+	spr->r = r;
+	spr->nframes = nframes;
+	spr->curframe = 0;
+	spr->period = period;
+	spr->elapsed = 0;
+	spr->step = sprite_step;
+	spr->draw = sprite_draw;
+
+	return spr;
+}
+
+Sprite *
+readsprite(char *sheetfile, Point sp, Rectangle r, int nframes, ulong period)
+{
+	Image *sheet;
+	int fd;
+
+	fd = open(sheetfile, OREAD);
+	if(fd < 0)
+		sysfatal("readsprite: %r");
+	sheet = readimage(display, fd, 1);
+	close(fd);
+
+	return newsprite(sheet, sp, r, nframes, period);
+}
+
+void
+delsprite(Sprite *spr)
+{
+	freeimage(spr->sheet);
+	free(spr);
+}