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.
--- /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);
+}