shithub: musw

Download patch

ref: 8975899ac8a3589d0d42f96dc4b7aa6ced8ee720
parent: 0f75049222798e1bfee7c5bff80bee6a0b7fdd2c
author: rodri <rgl@antares-labs.eu>
date: Sat Feb 25 05:21:02 EST 2023

implemented optional ghosting for the clients.

--- a/alloc.c
+++ b/alloc.c
@@ -32,13 +32,13 @@
 	return np;
 }
 
-//Image*
-//eallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong col)
-//{
-//	Image *i;
-//
-//	i = allocimage(d, r, chan, repl, col);
-//	if(i == nil)
-//		sysfatal("allocimage: %r");
-//	return i;
-//}
+Image*
+eallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong col)
+{
+	Image *i;
+
+	i = allocimage(d, r, chan, repl, col);
+	if(i == nil)
+		sysfatal("allocimage: %r");
+	return i;
+}
--- a/fns.h
+++ b/fns.h
@@ -5,7 +5,7 @@
  */
 void *emalloc(ulong);
 void *erealloc(void*, ulong);
-//Image *eallocimage(Display*, Rectangle, ulong, int, ulong);
+Image *eallocimage(Display*, Rectangle, ulong, int, ulong);
 
 /*
  * physics
--- a/musw.c
+++ b/musw.c
@@ -36,11 +36,13 @@
 RFrame screenrf;
 Universe *universe;
 VModel *needlemdl, *wedgemdl;
+Image *screenb;
 Image *skymap;
 Channel *ingress;
 Channel *egress;
 NetConn netconn;
 char winspec[32];
+int doghosting;
 int debug;
 
 
@@ -110,6 +112,46 @@
 	return mdl;
 }
 
+int
+blendimages(Image *i0, Image *i1, double f)
+{
+	static uchar *buf0, *buf1;
+	static char c0[10], c1[10];
+	static ulong n;
+	uchar *s0, *s1;
+
+	assert(i0->depth == i1->depth);
+	assert(Dx(i0->r) == Dx(i1->r) && Dy(i0->r) == Dy(i1->r));
+
+	f = fclamp(f, 0, 1);
+	if(buf0 == nil && buf1 == nil){
+		n = bytesperline(i0->r, i0->depth)*Dy(i0->r);
+		buf0 = emalloc(n);
+		buf1 = emalloc(n);
+
+		/* i1 won't ever change */
+		if(unloadimage(i1, i1->r, buf1, n) != n)
+			sysfatal("unloadimage: %r");
+
+		if(debug){
+			chantostr(c0, i0->chan);
+			chantostr(c1, i1->chan);
+			fprint(2, "i0 %s\ti1 %s\n", c0, c1);
+		}
+	}
+
+	if(unloadimage(i0, i0->r, buf0, n) != n)
+		sysfatal("unloadimage: %r");
+
+	for(s0 = buf0, s1 = buf1; s0 < buf0+n; s0++, s1++)
+		*s0 = flerp(*s0, *s1, f);
+
+	if(loadimage(i0, i0->r, buf0, n) != n)
+		sysfatal("loadimage: %r");
+
+	return 0;
+}
+
 void
 drawbullets(Ship *ship, Image *dst)
 {
@@ -444,12 +486,11 @@
 		t0 = nanosec();
 	}
 
-	draw(screen, screen->r, skymap, nil, ZP);
-	np = string(screen, addpt(screen->r.min, p), display->white, ZP, font, "connecting");
+	np = string(screenb, addpt(screenb->r.min, p), display->white, ZP, font, "connecting");
 
 	for(i = 1; i < 3+1; i++){
 		if(nanosec()-t0 > i*1e9)
-			np = string(screen, np, display->white, ZP, font, ".");
+			np = string(screenb, np, display->white, ZP, font, ".");
 	}
 }
 
@@ -458,17 +499,22 @@
 {
 	lockdisplay(display);
 
-	draw(screen, screen->r, skymap, nil, ZP);
+	if(doghosting)
+		blendimages(screenb, skymap, 0.05);
+	else
+		draw(screenb, screenb->r, skymap, nil, ZP);
 
 	if(netconn.state == NCSConnecting)
 		drawconnecting();
 
 	if(netconn.state == NCSConnected){
-		drawship(&universe->ships[0], screen);
-		drawship(&universe->ships[1], screen);
-		universe->star.spr->draw(universe->star.spr, screen, subpt(toscreen(universe->star.p), Pt(16,16)));
+		drawship(&universe->ships[0], screenb);
+		drawship(&universe->ships[1], screenb);
+		universe->star.spr->draw(universe->star.spr, screenb, subpt(toscreen(universe->star.p), Pt(16,16)));
 	}
 
+	draw(screen, screen->r, screenb, nil, ZP);
+
 	flushimage(display, 1);
 	unlockdisplay(display);
 }
@@ -486,7 +532,7 @@
 		sysfatal("resize failed");
 	unlockdisplay(display);
 
-	screenrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.max.y-Dy(screen->r)/2,1);
+//	screenrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.max.y-Dy(screen->r)/2,1);
 
 	/* ignore move events */
 	if(Dx(screen->r) != SCRW || Dy(screen->r) != SCRH){
@@ -503,7 +549,7 @@
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-d] server\n", argv0);
+	fprint(2, "usage: %s [-dg] server\n", argv0);
 	threadexitsall("usage");
 }
 
@@ -524,6 +570,9 @@
 	case 'd':
 		debug++;
 		break;
+	case 'g':
+		doghosting++;
+		break;
 	default:
 		usage();
 	}ARGEND;
@@ -541,7 +590,11 @@
 	display->locking = 1;
 	unlockdisplay(display);
 
-	screenrf.p = Pt2(screen->r.min.x+Dx(screen->r)/2,screen->r.max.y-Dy(screen->r)/2,1);
+	initskymap();
+	screenb = eallocimage(display, rectsubpt(screen->r, screen->r.min), RGBA32, 0, DNofill);
+	draw(screenb, screenb->r, skymap, nil, ZP);
+
+	screenrf.p = Pt2(Dx(screenb->r)/2,Dy(screenb->r)/2,1);
 	screenrf.bx = Vec2(1, 0);
 	screenrf.by = Vec2(0,-1);
 
@@ -548,8 +601,6 @@
 	proccreate(kbdproc, nil, mainstacksize);
 
 	/* TODO: implement this properly with screens and iodial(2) */
-	drawconnecting();
-	flushimage(display, 1);
 	fd = dial(server, nil, nil, nil);
 	if(fd < 0)
 		sysfatal("dial: %r");
@@ -564,8 +615,6 @@
 	universe->ships[0].mdl = needlemdl;
 	universe->ships[1].mdl = wedgemdl;
 	universe->star.spr = readsprite("assets/spr/earth.pic", ZP, Rect(0,0,32,32), 5, 20e3);
-
-	initskymap();
 
 	ingress = chancreate(sizeof(Frame*), 8);
 	egress = chancreate(sizeof(Frame*), 8);
--- a/muswd.c
+++ b/muswd.c
@@ -342,7 +342,8 @@
 					ship->rotate(ship, 1, Δt);
 				if((player->kdown & 1<<K↻) != 0)
 					ship->rotate(ship, -1, Δt);
-				if((player->kdown & 1<<Khyper) != 0)
+				if(player->oldkdown != player->kdown &&
+				   (player->kdown & 1<<Khyper) != 0)
 					ship->hyperjump(ship);
 				if(player->oldkdown != player->kdown &&
 				   (player->kdown & 1<<Kfire) != 0)
--- a/physics.c
+++ b/physics.c
@@ -19,7 +19,6 @@
 {
 	double g, d;
 
-	/* TODO: take thrust into account, based on user input. */
 	d = vec2len(subpt2(u->star.p, p->p));
 	d *= 1e5; /* scale to the 100km/px range */
 	g = G*u->star.mass/(d*d);