aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/vfx/hit.pngbin0 -> 11597 bytes
-rw-r--r--assets/vfx/miss.pngbin0 -> 9040 bytes
-rw-r--r--bts.c67
-rw-r--r--dat.h39
-rw-r--r--fns.h16
-rw-r--r--mkfile2
6 files changed, 111 insertions, 13 deletions
diff --git a/assets/vfx/hit.png b/assets/vfx/hit.png
new file mode 100644
index 0000000..6a466ac
--- /dev/null
+++ b/assets/vfx/hit.png
Binary files differ
diff --git a/assets/vfx/miss.png b/assets/vfx/miss.png
new file mode 100644
index 0000000..215c165
--- /dev/null
+++ b/assets/vfx/miss.png
Binary files differ
diff --git a/bts.c b/bts.c
index 311ff76..9dec67c 100644
--- a/bts.c
+++ b/bts.c
@@ -135,6 +135,8 @@ char titlefontpath[] = "font/gunmetal/gunmetal.48.font";
Font *titlefont;
char winspec[32];
char uid[8+1], oid[8+1];
+Sprite *spritetab[NVFX];
+Vfx vfxqueue;
Channel *drawchan;
Channel *reconnc;
Channel *ingress, *egress;
@@ -277,12 +279,8 @@ resetgame(void)
Point
vstring(Image *dst, Point p, Image *src, Point sp, Font *f, char *s)
{
- char buf[2];
-
- buf[1] = 0;
while(*s){
- buf[0] = *s++;
- string(dst, p, src, sp, f, buf);
+ stringn(dst, p, src, sp, f, s++, 1);
p.y += font->height;
}
return p;
@@ -408,6 +406,9 @@ drawinfo(Image *dst)
snprint(aux, sizeof aux, "%s (%d)", shipname(curship-armada), curship->ncells);
p = Pt(SCRW/2 - stringwidth(font, aux)/2, SCRH-Boardmargin);
string(dst, p, pal[PCYellow], ZP, font, aux);
+ s = "MMB to rotate the ship";
+ p = Pt(SCRW/2 - stringwidth(font, s)/2, SCRH-Boardmargin+font->height);
+ string(dst, p, pal[PCYellow], ZP, font, s);
}else{
s = "done with the layout?";
p = Pt(SCRW/2 - stringwidth(font, s)/2, SCRH-Boardmargin);
@@ -452,6 +453,8 @@ drawconclusion(Image *dst)
void
redraw(void)
{
+ Vfx *vfx;
+
lockdisplay(display);
draw(screenb, screenb->r, pal[PCBlack], nil, ZP);
@@ -468,6 +471,8 @@ redraw(void)
drawinfo(screenb);
break;
}
+ for(vfx = vfxqueue.next; vfx != &vfxqueue; vfx = vfx->next)
+ vfx->draw(vfx, screenb);
drawconclusion(screenb);
draw(screen, screen->r, screenb, nil, ZP);
@@ -603,6 +608,18 @@ initarmada(void)
}
void
+initvfx(void)
+{
+ char aux[64];
+
+ snprint(aux, sizeof aux, "%s/%s", assetdir, "vfx/hit.png");
+ spritetab[VFXHit] = readpngsprite(aux, ZP, Rect(0, 0, 32, 32), 12, 100);
+ snprint(aux, sizeof aux, "%s/%s", assetdir, "vfx/miss.png");
+ spritetab[VFXMiss] = readpngsprite(aux, ZP, Rect(0, 0, 32, 32), 7, 150);
+ initvfxq(&vfxqueue);
+}
+
+void
initsfx(void)
{
struct {
@@ -763,11 +780,11 @@ mmb(Mousectl *mc)
if(!rectinrect(curship->bbox, localboard.bbox)){
switch(curship->orient){
case OH:
- curship->bbox.min.x -= curship->bbox.max.x-localboard.bbox.max.x;
+ curship->bbox.min.x -= curship->bbox.max.x - localboard.bbox.max.x;
curship->bbox.max.x = localboard.bbox.max.x;
break;
case OV:
- curship->bbox.min.y -= curship->bbox.max.y-localboard.bbox.max.y;
+ curship->bbox.min.y -= curship->bbox.max.y - localboard.bbox.max.y;
curship->bbox.max.y = localboard.bbox.max.y;
break;
}
@@ -878,7 +895,7 @@ celebrate(void)
void
keelhaul(void)
{
- static char s[] = "…YOU LOST";
+ static char s[] = "...YOU LOST";
conclusion.c = pal[PCRed];
conclusion.s = s;
@@ -1009,11 +1026,17 @@ processcmd(char *cmd)
idx = strtoul(cb->f[1], nil, 10);
cell = coords2cell(cb->f[2]);
settile(match.bl[idx^1], cell, Thit);
+ addvfx(&vfxqueue,
+ newvfx(spritetab[VFXHit]->clone(spritetab[VFXHit]),
+ addpt(fromboard(match.bl[idx^1], cell), Pt(TW/2, TH/2)), 1));
break;
case CMplayermiss:
idx = strtoul(cb->f[1], nil, 10);
cell = coords2cell(cb->f[2]);
settile(match.bl[idx^1], cell, Tmiss);
+ addvfx(&vfxqueue,
+ newvfx(spritetab[VFXMiss]->clone(spritetab[VFXMiss]),
+ addpt(fromboard(match.bl[idx^1], cell), Pt(TW/2, TH/2)), 1));
break;
case CMplayerplays:
idx = strtoul(cb->f[1], nil, 10);
@@ -1045,12 +1068,18 @@ processcmd(char *cmd)
break;
case CMwehit:
settile(&alienboard, lastshot, Thit);
+ addvfx(&vfxqueue,
+ newvfx(spritetab[VFXHit]->clone(spritetab[VFXHit]),
+ addpt(fromboard(&alienboard, lastshot), Pt(TW/2, TH/2)), 1));
break;
case CMwemiss:
if(!silent)
playaudio(playlist[SWATER]);
settile(&alienboard, lastshot, Tmiss);
+ addvfx(&vfxqueue,
+ newvfx(spritetab[VFXMiss]->clone(spritetab[VFXMiss]),
+ addpt(fromboard(&alienboard, lastshot), Pt(TW/2, TH/2)), 1));
break;
}
break;
@@ -1064,6 +1093,9 @@ processcmd(char *cmd)
cell = coords2cell(cb->f[1]);
for(i = 0; i < nelem(armada); i++)
if(ptinrect(fromboard(&localboard, cell), armada[i].bbox)){
+ addvfx(&vfxqueue,
+ newvfx(spritetab[VFXHit]->clone(spritetab[VFXHit]),
+ addpt(fromboard(&localboard, cell), Pt(TW/2, TH/2)), 1));
cell = subpt2(cell, armada[i].p);
armada[i].hit[(int)vec2len(cell)] = 1;
break;
@@ -1072,6 +1104,9 @@ processcmd(char *cmd)
case CMtheymiss:
cell = coords2cell(cb->f[1]);
settile(&localboard, cell, Tmiss);
+ addvfx(&vfxqueue,
+ newvfx(spritetab[VFXMiss]->clone(spritetab[VFXMiss]),
+ addpt(fromboard(&localboard, cell), Pt(TW/2, TH/2)), 1));
break;
}
break;
@@ -1101,7 +1136,9 @@ soundproc(void *)
void
timerproc(void *)
{
- uvlong t0, Δt, acc;
+ Vfx *vfx;
+ uvlong t0, Δt, φt, acc;
+ int refresh;
threadsetname("timer");
@@ -1109,15 +1146,24 @@ timerproc(void *)
acc = 0;
for(;;){
Δt = nsec() - t0;
+ φt = Δt/1000000ULL;
acc += Δt;
+ refresh = 0;
+ for(vfx = vfxqueue.next; vfx != &vfxqueue; vfx = vfx->next){
+ vfx->step(vfx, φt);
+ refresh = 1;
+ }
+ if(refresh)
+ nbsend(drawchan, nil);
+
if(gamestate == Waiting0 && acc >= 5*SEC){
chanprint(egress, "watch\n");
acc = 0;
}
t0 += Δt;
- sleep(HZ2MS(10));
+ sleep(HZ2MS(20));
}
}
@@ -1232,6 +1278,7 @@ threadmain(int argc, char *argv[])
initmainbtns();
initboards();
initarmada();
+ initvfx();
matches = newmenulist(14*font->height, "ongoing matches");
gamestate = Waiting0;
diff --git a/dat.h b/dat.h
index c7b7cee..d645d6f 100644
--- a/dat.h
+++ b/dat.h
@@ -7,7 +7,7 @@ enum {
Tmiss,
NTILES,
- TBITS = 2, /* ceil(log(NTILES)/log(2)) */
+ TBITS = 2, /* ceil(log(NTILES)/log(2)) */
TMASK = (1<<TBITS) - 1,
Scarrier = 0,
@@ -17,8 +17,12 @@ enum {
Sdestroyer,
NSHIPS,
- OH, /* horizontal */
- OV, /* vertical */
+ VFXHit = 0,
+ VFXMiss,
+ NVFX,
+
+ OH = 0, /* horizontal */
+ OV, /* vertical */
GMPvP = 0,
GMPvAI,
@@ -180,6 +184,35 @@ struct Button
void (*handler)(Button*);
};
+typedef struct Sprite Sprite;
+typedef struct Vfx Vfx;
+
+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);
+ Sprite *(*clone)(Sprite*);
+};
+
+struct Vfx
+{
+ Sprite *a; /* animation */
+ Point p;
+ int times; /* to repeat. -1 loops forever */
+ Vfx *prev, *next;
+
+ void (*step)(Vfx*, ulong);
+ void (*draw)(Vfx*, Image*);
+};
+
typedef struct Mentry Mentry;
typedef struct Mlist Mlist;
typedef struct Menulist Menulist;
diff --git a/fns.h b/fns.h
index 38aa481..c8f8fde 100644
--- a/fns.h
+++ b/fns.h
@@ -36,6 +36,22 @@ Menulist *newmenulist(int, char*);
void delmenulist(Menulist*);
/*
+ * sprite
+ */
+Sprite *newsprite(Image*, Point, Rectangle, int, ulong);
+Sprite *readsprite(char*, Point, Rectangle, int, ulong);
+Sprite *readpngsprite(char*, Point, Rectangle, int, ulong);
+void delsprite(Sprite*);
+
+/*
+ * vfx
+ */
+Vfx *newvfx(Sprite*, Point, int);
+void delvfx(Vfx*);
+void addvfx(Vfx*, Vfx*);
+void initvfxq(Vfx*);
+
+/*
* parse
*/
Cmdbuf *parsecmd(char*, int);
diff --git a/mkfile b/mkfile
index 40d51d5..74098db 100644
--- a/mkfile
+++ b/mkfile
@@ -13,6 +13,8 @@ OFILES=\
andy.$O\
menulist.$O\
mixer.$O\
+ sprite.$O\
+ vfx.$O\
HFILES=\
dat.h\