shithub: musw

Download patch

ref: b545537c9a6c7d32976b863cbb14792980d31e3d
parent: 941d146cea7d0c2ce872e599622a5c9e01d37fe2
author: rodri <rgl@antares-labs.eu>
date: Wed Mar 8 15:59:10 EST 2023

implemented states to represent game scene stages.

added an intro as well.

binary files /dev/null b/assets/spr/intro.pic differ
--- a/dat.h
+++ b/dat.h
@@ -58,7 +58,7 @@
 typedef struct VModel VModel;
 typedef struct Sprite Sprite;
 typedef struct Keymap Keymap;
-typedef struct Scene Scene;
+typedef struct State State;
 typedef struct Particle Particle;
 typedef struct Bullet Bullet;
 typedef struct Ship Ship;
@@ -107,14 +107,11 @@
 	KeyOp op;
 };
 
-struct Scene
+struct State
 {
-	char *title;
-	int state;
+	char *name;
 
-	Scene *(*δ)(Scene*);
-	void (*step)(Scene*);
-	void (*draw)(Scene*);
+	State *(*δ)(State*, void*); /* transition fn */
 };
 
 struct Particle
--- a/musw.c
+++ b/musw.c
@@ -12,6 +12,14 @@
 #include "dat.h"
 #include "fns.h"
 
+enum {
+	GSIntro,
+	GSConnecting,
+	GSMatching,
+	GSPlaying,
+	NGAMESTATES
+};
+
 Keymap kmap[] = {
 	{.key = Kup,	.op = K↑},
 	{.key = Kleft,	.op = K↺},
@@ -31,12 +39,15 @@
 VModel *needlemdl, *wedgemdl;
 Image *screenb;
 Image *skymap;
-Scene *curscene;
+Sprite *intro;
+State gamestates[NGAMESTATES];
+State *gamestate;
 Channel *ingress;
 Channel *egress;
 NetConn netconn;
 char deffont[] = "/lib/font/bit/pelm/unicode.9.font";
 char winspec[32];
+int weplaying;
 int doghosting;
 int debug;
 
@@ -365,6 +376,8 @@
 
 			switch(frame->type){
 			case NSsimstate:
+				weplaying = 1;
+
 				bufp = frame->data;
 				bufp += unpack(bufp, frame->len, "PdPdP",
 					&universe->ships[0].p, &universe->ships[0].θ,
@@ -385,6 +398,7 @@
 
 				break;
 			case NSbuhbye:
+				weplaying = 0;
 				netconn.state = NCSDisconnected;
 				break;
 			}
@@ -499,13 +513,20 @@
 	else
 		draw(screenb, screenb->r, skymap, nil, ZP);
 
-	if(netconn.state == NCSConnecting)
+	switch(gamestate-gamestates){
+	case GSIntro:
+		intro->draw(intro, screenb, subpt(divpt(screenb->r.max, 2), divpt(intro->r.max, 2)));
+		break;
+	case GSConnecting:
 		drawconnecting();
-
-	if(netconn.state == NCSConnected){
+		break;
+	case GSMatching:
+		break;
+	case GSPlaying:
 		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)));
+		break;
 	}
 
 	draw(screen, screen->r, screenb, nil, ZP);
@@ -541,6 +562,37 @@
 	redraw();
 }
 
+State *intro_δ(State *s, void *arg)
+{
+	double ∆t;
+	static ulong elapsed;
+
+	∆t = *(double*)arg;
+	elapsed += ∆t/1e6;
+	if(elapsed > 5000)
+		return &gamestates[GSConnecting];
+	return s;
+}
+
+State *connecting_δ(State *s, void*)
+{
+	if(netconn.state != NCSConnecting)
+		return &gamestates[GSMatching];
+	return s;
+}
+
+State *matching_δ(State *s, void*)
+{
+	if(netconn.state == NCSConnected && weplaying)
+		return &gamestates[GSPlaying];
+	return s;
+}
+
+State *playing_δ(State *s, void*)
+{
+	return s;
+}
+
 void
 usage(void)
 {
@@ -595,7 +647,6 @@
 
 	proccreate(kbdproc, nil, mainstacksize);
 
-	/* TODO: implement this properly with screens and iodial(2) */
 	fd = dial(server, nil, nil, nil);
 	if(fd < 0)
 		sysfatal("dial: %r");
@@ -611,6 +662,14 @@
 	universe->ships[1].mdl = wedgemdl;
 	universe->star.spr = readsprite("assets/spr/earth.pic", ZP, Rect(0,0,32,32), 5, 20e3);
 
+	intro = readsprite("assets/spr/intro.pic", ZP, Rect(0,0,640,480), 1, 0);
+
+	gamestates[GSIntro].δ = intro_δ;
+	gamestates[GSConnecting].δ = connecting_δ;
+	gamestates[GSMatching].δ = matching_δ;
+	gamestates[GSPlaying].δ = playing_δ;
+	gamestate = &gamestates[GSIntro];
+
 	ingress = chancreate(sizeof(Frame*), 8);
 	egress = chancreate(sizeof(Frame*), 8);
 	threadcreate(threadnetrecv, &fd, mainstacksize);
@@ -626,15 +685,18 @@
 		frametime = now - then;
 		then = now;
 
-		if(netconn.state != NCSConnected)
-			lastpktsent += frametime/1e6;
+		if(gamestate != &gamestates[GSIntro]){
+			if(netconn.state == NCSConnecting)
+				lastpktsent += frametime/1e6;
 
-		if(netconn.state == NCSDisconnected ||
-		  (netconn.state == NCSConnecting && lastpktsent >= 1000)){
-			initconn();
-			lastpktsent = 0;
+			if(netconn.state == NCSDisconnected ||
+			  (netconn.state == NCSConnecting && lastpktsent >= 1000)){
+				initconn();
+				lastpktsent = 0;
+			}
 		}
 
+		gamestate = gamestate->δ(gamestate, &frametime);
 		universe->star.spr->step(universe->star.spr, frametime/1e6);
 
 		redraw();
--- a/todo
+++ b/todo
@@ -7,11 +7,14 @@
 [ ] hyperjump
 	[ ] minskytron effect
 	[ ] engine damage on every jump
-[ ] different screens for each game state
-	[ ] intro
-	[ ] connecting to server
-	[ ] waiting for a player
-	[ ] main game
+[✓] different screens for each game state
+	[✓] intro
+	[✓] connecting to server
+	[✓] waiting for a player
+	[✓] main game
 [ ] reduce the amount of data sent on every NSsimstate packet
 [?] the client must try to connect continously
 	> there's an error in the udp stack that doesn't allow the client to receive packets if run before the server is up.
+[ ] more realistic DEC Type 30 CRT emulation
+	[ ] the right colors (fg: 0x3daaf7, fgblur: 0x0063eb, bg0: 0x79cc3e, bg1: 0x7eba1e)
+	[ ] the right decay function