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