shithub: dporg

Download patch

ref: f7927e23bd580bca048fb9eba61d59959722de44
parent: d720781005fff71800333afec5f574ccd770edea
author: qwx <qwx@sciops.net>
date: Tue May 11 08:46:56 EDT 2021

add intro sequence fsm

- fsm: basic common fsm system
- drw: add static canvas pic to manipulate image data into,
alloc maximum canvas size, but allow changing its "dimensions" at will
- fs: load and parse base.str

--- a/dat.h
+++ b/dat.h
@@ -3,10 +3,33 @@
 extern char *prefix;
 
 enum{
-	Vwidth = 320,
-	Vheight = 210,
+	Vw = 320,
+	Vfullh = 210,
+	Vdrwh = Vfullh - 60 - 2,	/* FIXME: ? */
+	Vh = Vdrwh + 40,
+	Vcenterx = Vw / 2,
+	Vcentery = Vh / 2,
+	Vfntw = 7,
+	Vfnth = 12,
+
+	Kfire = 0,
+	K↑,
+	K↓,
+	K←,
+	K→,
 };
 
+enum{
+	BScontinue = 114,
+	BSgameloaded,
+	BSmore,
+	BSintro1 = 256,
+	BSintro2,
+	BSintro3,
+	BSend = 270,
+};
+extern char **basestr;
+
 extern int npal;
 extern u32int *pal;
 
@@ -32,4 +55,16 @@
 	int w;
 	int h;
 };
-extern Pic pics[PCend];
+extern Pic pics[PCend], canvas;
+
+enum{
+	DShip = 0xbb0000ff,
+	DHud1 = 0x313131ff,
+	DHud2 = 0x808591ff,
+	DFace = 0x323232ff,
+	DAmmo = 0x828282ff,
+};
+
+extern void (*step)(void);
+extern void (*input)(Rune);
+extern vlong tc;
--- a/dporg.c
+++ b/dporg.c
@@ -9,14 +9,6 @@
 
 char *prefix = "/sys/games/lib/dporg";
 
-enum{
-	Kfire = 'x',
-	K↑ = Kup,
-	K↓ = Kdown,
-	K← = Kleft,
-	K→ = Kright,
-};
-
 static Keyboardctl *kc;
 static Mousectl *mc;
 
@@ -77,17 +69,19 @@
 		sysfatal("initkeyboard: %r");
 	if((mc = initmouse(nil, screen)) == nil)
 		sysfatal("initmouse: %r");
+	srand(time(nil));
 	initfsm();
 	enum{
 		Aresize,
 		Amouse,
 		Akbd,
+		Aend,
 	};
 	Alt a[] = {
-		{mc->resizec, nil, CHANRCV},
-		{mc->c, &mc->Mouse, CHANRCV},
-		{kc->c, &r, CHANRCV},
-		{nil, nil, CHANEND}
+		[Aresize] {mc->resizec, nil, CHANRCV},
+		[Amouse] {mc->c, &mc->Mouse, CHANRCV},
+		[Akbd] {kc->c, &r, CHANRCV},
+		[Aend] {nil, nil, CHANNOBLK},
 	};
 	for(;;){
 		switch(alt(a)){
@@ -105,13 +99,22 @@
 			switch(r){
 			case Kdel:
 			case 'q': threadexitsall(nil);
-			case Kfire: break;
-			case K↑: break;
-			case K↓: break;
-			case K←: break;
-			case K→: break;
+			case 'x': r = Kfire; break;
+			case Kup: r = K↑; break;
+			case Kdown: r = K↓; break;
+			case Kleft: r = K←; break;
+			case Kright: r = K→; break;
+			default: r = -1; break;
 			}
+			if(r != -1 && input != nil)
+				input(r);
 			break;
 		}
+		if(step != nil){
+			advclock();
+			step();
+		}
+		a[Aend].op = step == nil ? CHANEND : CHANNOBLK;
+		sleep(1);
 	}
 }
--- a/drw.c
+++ b/drw.c
@@ -4,17 +4,61 @@
 #include "dat.h"
 #include "fns.h"
 
-static u32int fb[Vwidth * Vheight];
-
 int npal;
 u32int *pal;
-Pic pics[PCend];
+Pic pics[PCend], canvas;
 
+static u32int fb[Vw * Vfullh];
+
 static int scale, fbsz;
 static Rectangle fbsr;
 static Image *fbs;
 static u32int *fbsbuf;
 
+void
+scrollpic(Pic *pp, int Δx)
+{
+	// FIXME: scroll pic into canvas
+	// scrollpic(&pics[PCspace], tc / scrollΔtc % pics[PCspace].w);
+	// instead we just pass tc / scrollΔtc and do MOD here with pp->w
+	USED(pp,Δx);
+}
+
+void
+drawstr(int x, int y, char *s)
+{
+	// FIXME
+	USED(x,y,s);
+}
+
+void
+drawsubstr(int x, int y, char *s, char *e)
+{
+	// FIXME
+	USED(x,y,s,e);
+}
+
+void
+drawline(int x, int y, int w, int h, u32int col)
+{
+	// FIXME
+	USED(x,y,w,h,col);
+}
+
+void
+drawpic(int x, int y, Pic *pp)
+{
+	// FIXME: draw pp at x,y
+	USED(x,y,pp);
+}
+
+void
+drawfill(u32int col)
+{
+	// FIXME: fill window/vis area/rect with color
+	USED(col);
+}
+
 static void
 drawscaled(void)
 {
@@ -55,7 +99,7 @@
 		r = fbsr;
 		while(r.min.y < fbsr.max.y){
 			r.max.y = r.min.y + scale;
-			p += loadimage(fbs, fbs->r, p, fbsz / Vheight);
+			p += loadimage(fbs, fbs->r, p, fbsz / Vfullh);
 			draw(screen, r, fbs, nil, ZP);
 			r.min.y = r.max.y;
 		}
@@ -68,17 +112,17 @@
 {
 	Point o, p;
 
-	scale = min(Dx(screen->r) / Vwidth, Dy(screen->r) / Vheight);
+	scale = min(Dx(screen->r) / Vw, Dy(screen->r) / Vfullh);
 	if(scale <= 0)
 		scale = 1;
 	else if(scale > 12)
 		scale = 12;
 	o = divpt(addpt(screen->r.min, screen->r.max), 2);
-	p = Pt(Vwidth / 2 * scale, Vheight / 2 * scale);
+	p = Pt(Vw / 2 * scale, Vfullh / 2 * scale);
 	fbsr = Rpt(subpt(o, p), addpt(o, p));
-	fbsz = Vwidth * Vheight * scale * sizeof *fbsbuf;
+	fbsz = Vw * Vfullh * scale * sizeof *fbsbuf;
 	freeimage(fbs);
-	if((fbs = allocimage(display, Rect(0,0,Vwidth*scale,scale==1? Vheight : 1),
+	if((fbs = allocimage(display, Rect(0,0,Vw*scale,scale==1? Vfullh : 1),
 		XRGB32, scale > 1, DBlack)) == nil)
 		sysfatal("allocimage: %r");
 	free(fbsbuf);
--- a/fns.h
+++ b/fns.h
@@ -1,4 +1,14 @@
+void	enterloadmap(void);
+void	enterintro(void);
+int	advclock(void);
+void	setfsm(void (*)(void), void (*)(Rune));
 void	initfsm(void);
+void	scrollpic(Pic*, int);
+void	drawsubstr(int, int, char*, char*);
+void	drawstr(int, int, char*);
+void	drawline(int, int, int, int, u32int);
+void	drawpic(int, int, Pic*);
+void	drawfill(u32int);
 void	drawfb(void);
 void	resetfb(int);
 void	initfb(void);
--- a/fs.c
+++ b/fs.c
@@ -6,6 +6,7 @@
 #include "fns.h"
 
 s32int sintab[256];
+char **basestr;
 
 static Biobuf *
 eopen(char *s, int mode)
@@ -80,6 +81,8 @@
 	dx = Dx(i->r);
 	dy = Dy(i->r);
 	n = dx * dy;
+	if(dx * dy > Vw * Vfullh)
+		sysfatal("loadpic %s: inappropriate image size", name);
 	p = emalloc(n * sizeof *p);
 	pic->p = p;
 	pic->w = dx;
@@ -113,6 +116,9 @@
 	loadpic("p.bit", pics + PCcur);
 	loadpic("q.bit", pics + PCscroll);
 	loadpic("r.bit", pics + PCgibs);
+	canvas.p = emalloc(Vw * Vfullh * sizeof *canvas.p);
+	canvas.w = Vw;
+	canvas.h = Vfullh;
 }
 
 static void
@@ -139,7 +145,42 @@
 	Bterm(bf);
 }
 
+static char **
+loadstr(char *name, int *nel)
+{
+	int n;
+	char **s, **p, **e, *q;
+	Biobuf *bf;
+
+	bf = eopen(name, OREAD);
+	n = get16(bf);
+	s = emalloc(n * sizeof *p);
+	e = s + n;
+	*nel = n;
+	for(p=s; p<e; p++){
+		n = get16(bf);
+		*p = emalloc(n + 1);
+		eread(bf, *p, n);
+		/* FIXME: not always? */
+		q = *p;
+		while((q = strchr(q, '|')) != nil)
+			*q = '\n';
+	}
+	Bterm(bf);
+	return s;
+}
+
 static void
+loadbasestr(void)
+{
+	int nel;
+
+	basestr = loadstr("base.str", &nel);
+	if(nel != BSend)
+		sysfatal("loadbasestr: inconsistent base.str file: entries %d not %d", nel, BSend);
+}
+
+static void
 loadsintab(void)
 {
 	Biobuf *bf;
@@ -159,6 +200,7 @@
 		fprint(2, "initfs: %r\n");
 	loadsintab();
 	loadpal();
+	loadbasestr();
 }
 
 // grids: 32/256/2048
--- a/fsm.c
+++ b/fsm.c
@@ -3,8 +3,44 @@
 #include "dat.h"
 #include "fns.h"
 
+void (*step)(void);
+void (*input)(Rune);
+
+vlong tc;
+static vlong t0;
+
+enum{
+	Te9 = 1000000000,
+	Te6 = 1000000,
+	Hz = 1000,
+	TΔ = Te9 / Hz,
+};
+
+int
+advclock(void)
+{
+	int Δtc;
+	vlong t;
+
+	t = nsec();
+	Δtc = (t - t0) / TΔ;
+	tc += Δtc;
+	t0 += Δtc * TΔ;
+	return Δtc;
+}
+
 void
+setfsm(void (*stepfn)(void), void (*inputfn)(Rune))
+{
+	step = stepfn;
+	input = inputfn;
+	t0 = nsec();
+	tc = 0;
+}
+
+void
 initfsm(void)
-{	
+{
 	srand(time(nil));
+	enterintro();
 }
--- /dev/null
+++ b/fsm.intro.c
@@ -1,0 +1,193 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "dat.h"
+#include "fns.h"
+
+enum{
+	Ttext = 25,
+	Tbg1scroll = 157,
+	Tbg2scroll = 457,
+	TshipΔx = 142,
+	TshipΔy = 333,
+	Tblink = 500,
+	Tshiptravel = 10000,
+};
+
+static char *curstr, *prompt;
+static int stri;
+static int steptc;
+static int canvmidx, canvmidy, promptΔx;
+static int scrollΔtc, scroll2Δtc, txtΔt;
+
+static void
+drawbg(void)
+{
+	scrollpic(&pics[PCspace], tc / scrollΔtc);
+	drawpic(canvmidx, canvmidy, &canvas);
+}
+
+static void
+drawprompt(void)
+{
+	Pic *pp;
+
+	pp = &pics[PCcur];
+	drawstr(canvmidx + canvas.w - 4 - strlen(prompt) * Vfntw,
+		canvmidy + canvas.h - Vfnth, prompt);
+	drawpic(Vcenterx + promptΔx - pp->w,
+		canvmidy + canvas.h - 2 - pp->h, pp);
+}
+
+static void
+drawtarget(void)
+{
+	int x, y;
+
+	x = Vcenterx + tc / TshipΔx;
+	y = Vcentery + 22 - tc / TshipΔy;
+	drawline(x, y - 1, 10, 1, DShip);
+	drawline(x + 4, canvmidy, 1, y - canvmidy - 1, DShip);
+	drawline(x, y + 9, 10, 1, DShip);
+	drawline(x + 4, y + 9, 1, canvmidy + canvas.h - y - 9, DShip);
+	if(x - 1 > canvmidx)
+		drawline(x - 1, y, 1, 10, DShip);
+	drawline(canvmidx, y + 4, x - 1 - canvmidx + canvas.w, 1, DShip);
+	drawline(x + 9, y, 1, 9, DShip);
+	drawline(x + 9, y + 4, canvmidx + canvas.w - x - 9, 1, DShip);
+}
+
+static void
+drawship(void)
+{
+	drawpic(Vcenterx + tc / TshipΔx, Vh / 2 + 22 - tc / TshipΔy, &pics[PCship]);
+}
+
+static void
+drawplanets(void)
+{
+	drawpic(canvmidx, canvmidy, &pics[PCplanets]);
+}
+
+static void
+drawgrid(void)
+{
+	scrollpic(&pics[PCgrid], tc / scroll2Δtc);
+	drawpic(canvmidx, canvmidy, &canvas);
+}
+
+static void
+drawintrostr(void)
+{
+	if(stri < strlen(curstr))
+		stri = tc / txtΔt;
+	drawsubstr(canvmidx, canvmidy, curstr, curstr+stri);
+}
+
+static void
+intro3step(void)
+{
+	int tc₁, tc₂;
+
+	if(tc > Tshiptravel){
+		input(Kfire);
+		return;
+	}
+	if(tc < steptc)
+		return;
+	drawbg();
+	drawgrid();
+	drawplanets();
+	drawship();
+	if((tc / Tblink & 1) == 0)
+		drawtarget();
+	drawfb();
+	tc₁ = (tc / scrollΔtc + 1) * scrollΔtc;
+	tc₂ = (tc / scroll2Δtc + 1) * scroll2Δtc;
+	tc₁ = min(tc₁, tc₂);
+	tc₂ = (tc / TshipΔx + 1) * TshipΔx;
+	tc₁ = min(tc₁, tc₂);
+	tc₂ = (tc / TshipΔy + 1) * TshipΔy;
+	tc₁ = min(tc₁, tc₂);
+	tc₂ = (tc / Tblink + 1) * Tblink;
+	steptc = min(tc₁, tc₂);
+}
+
+static void
+scrollstep(void)
+{
+	int tc₁, tc₂;
+
+	if(tc < steptc)
+		return;
+	drawbg();
+	drawintrostr();
+	drawprompt();
+	drawfb();
+	tc₁ = (tc / scrollΔtc + 1) * scrollΔtc;
+	tc₂ = stri < strlen(curstr) ? (tc / txtΔt + 1) * txtΔt : scrollΔtc;
+	steptc = min(tc₁, tc₂);
+}
+
+static void
+intro4step(void)
+{
+	scrollstep();
+}
+
+static void
+intro2step(void)
+{
+	scrollstep();
+}
+
+static void
+intro1step(void)
+{
+	scrollstep();
+}
+
+static void
+introkey(Rune k)
+{
+	if(k != Kfire)
+		return;
+	if(stri < strlen(curstr))
+		stri = strlen(curstr);
+	else if(step == intro1step){
+		setfsm(intro2step, introkey);
+		curstr = basestr[BSintro2];
+		stri = 0;
+		steptc = 0;
+	}else if(step == intro2step){
+		setfsm(intro3step, introkey);
+		scrollΔtc = Tbg2scroll;
+		scroll2Δtc = Tbg1scroll;
+		steptc = 0;
+	}else if(step == intro3step){
+		setfsm(intro4step, introkey);
+		curstr = basestr[BSintro3];
+		prompt = basestr[BScontinue];
+		promptΔx = 8 - 4;
+		scrollΔtc = Tbg1scroll;
+		stri = 0;
+		steptc = 0;
+	}else
+		enterloadmap();
+}
+
+void
+enterintro(void)
+{
+	canvas.w = pics[PCplanets].w;
+	canvas.h = pics[PCplanets].h;
+	canvmidx = Vcenterx - canvas.w / 2;
+	canvmidy = Vcentery - canvas.h / 2;
+	setfsm(intro1step, introkey);
+	curstr = basestr[BSintro1];
+	prompt = basestr[BSmore];
+	promptΔx = 36 - 30;
+	scrollΔtc = Tbg1scroll;
+	txtΔt = Ttext;
+	steptc = 0;
+}
--- /dev/null
+++ b/fsm.map.c
@@ -1,0 +1,9 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+void
+enterloadmap(void)
+{
+}
--- a/mkfile
+++ b/mkfile
@@ -6,6 +6,8 @@
 	dporg.$O\
 	drw.$O\
 	fsm.$O\
+	fsm.intro.$O\
+	fsm.map.$O\
 
 HFILES= dat.h fns.h
 </sys/src/cmd/mkone