ref: 9fba9b42bfc9df98b00fa01753cdfeb9bc214ca8
parent: f409e8573caf34c1fd9a963cc0afb612e8ebc525
author: qwx <qwx@sciops.net>
date: Mon Sep 28 19:26:08 EDT 2020
fs: add support for transparent floating sprites add gfx entries, which are sprite objects linked to a unit object's state. sprite objects are to be decorations drawn on top of a unit. such sprites use an alpha channel, in which case we save it. use of an alpha channel is specified in the db file.
--- a/dat.h
+++ b/dat.h
@@ -3,6 +3,7 @@
typedef struct Attack Attack;
typedef struct Pic Pic;
typedef struct Pics Pics;
+typedef struct OState OState;
typedef struct Obj Obj;
typedef struct Path Path;
typedef struct Mobj Mobj;
@@ -68,6 +69,8 @@
PFterrain = 1<<0,
PFidle = 1<<1,
PFmove = 1<<2,
+ PFfloat = 1<<13,
+ PFalpha = 1<<14,
PFshadow = 1<<15,
};
struct Pic{
@@ -90,10 +93,19 @@
Fair = 1<<2,
Fbuild = 1<<3,
};
+enum{
+ OSidle,
+ OSmove,
+ OSend
+};
+struct OState{
+ Pics pics;
+ Obj *gfx;
+ Mobj *mgfx;
+};
struct Obj{
char *name;
- Pics pidle;
- Pics pmove;
+ OState state[OSend];
int w;
int h;
int f;
--- a/drw.c
+++ b/drw.c
@@ -273,7 +273,7 @@
if(pp->pic != nil)
frm = tc % pp->nf;
else{
- pp = &mo->o->pmove;
+ pp = &mo->o->state[OSmove].pics;
frm = mo->freezefrm;
}
assert(pp->pic != nil && pp->shadow != nil);
--- a/fs.c
+++ b/fs.c
@@ -28,6 +28,7 @@
struct Picl{
int frm;
int type;
+ int teamcol;
char *name;
char iname[64];
int nr;
@@ -53,7 +54,7 @@
};
static void
-loadpic(char *name, Pic *pic)
+loadpic(char *name, Pic *pic, int alpha)
{
int fd, n, m, dx, dy;
Image *i;
@@ -65,8 +66,8 @@
if((i = readimage(display, fd, 0)) == nil)
sysfatal("readimage: %r");
close(fd);
- if(i->chan != RGB24)
- sysfatal("loadpic %s: non-RGB24 image", name);
+ if(alpha && i->chan != RGBA32 || !alpha && i->chan != RGB24)
+ sysfatal("loadpic %s: inappropriate image format", name);
dx = Dx(i->r);
dy = Dy(i->r);
n = dx * dy;
@@ -83,10 +84,12 @@
s = b;
while(n-- > 0){
v = s[2] << 16 | s[1] << 8 | s[0];
- if(v != bgcol)
+ if(alpha)
+ v |= s[3] << 24;
+ else if(v != bgcol)
v |= 0xff << 24;
*p++ = v;
- s += 3;
+ s += i->depth / 8;
}
free(b);
}
@@ -100,7 +103,7 @@
for(i=0; i<pl->nr; i++){
snprint(path, sizeof path, "%s.%02d.%02d.s.bit",
pl->name, pl->frm, rot17idx[i]);
- loadpic(path, pic++);
+ loadpic(path, pic++, 0);
}
}
@@ -115,7 +118,11 @@
for(i=0; i<pl->nr; i++){
snprint(path, sizeof path, "%s.%02d.%02d.bit",
pl->name, pl->frm, rot17idx[i]);
- loadpic(path, &pic0);
+ loadpic(path, &pic0, pl->type & PFalpha);
+ if(!pl->teamcol){
+ memcpy(pic, &pic0, sizeof *pic);
+ continue;
+ }
if(pic0.h % Nteam != 0)
sysfatal("loadobjpic: obj %s sprite sheet %d,%d: height not multiple of %d\n",
pl->name, pic0.w, pic0.h, Nteam);
@@ -140,7 +147,7 @@
if(tilesetpic.p == nil){
snprint(path, sizeof path, "%s.bit", tileset);
- loadpic(path, &tilesetpic);
+ loadpic(path, &tilesetpic, 0);
if(tilesetpic.h % tilesetpic.w != 0)
sysfatal("loadterpic: tiles not squares: tilepic %d,%d\n",
tilesetpic.w, tilesetpic.h);
@@ -197,8 +204,9 @@
if(nr != 17 && nr != 1)
sysfatal("pushpic %s: invalid number of rotations", iname);
n = nr;
- /* nteam isn't guaranteed to be set correctly by now */
- if((type & (PFshadow|PFterrain)) == 0)
+ /* nteam isn't guaranteed to be set correctly by now, so
+ * just set to max */
+ if(pl->teamcol = (type & (PFshadow|PFterrain|PFfloat)) == 0)
n *= Nteam;
pl->p = emalloc(n * sizeof *pl->p);
pl->l = pic->l;
@@ -281,7 +289,7 @@
if(*s == 0)
sysfatal("vunpack: empty obj");
for(o=obj; o<obj+nobj; o++)
- if(strcmp(s, o->name) == 0)
+ if(o->name != nil && strcmp(s, o->name) == 0)
break;
if(o == obj + nobj)
sysfatal("vunpack: no such obj %s", s);
@@ -387,6 +395,28 @@
}
static void
+readgfx(char **fld, int, Table *tab)
+{
+ int f;
+ Obj *fxo, *o;
+ OState *s;
+
+ if(obj == nil)
+ obj = emalloc(nobj * sizeof *obj);
+ fxo = obj + nobj - 1 - tab->row;
+ fxo->name = estrdup(*fld++);
+ unpack(fld, "od", &o, &f);
+ fxo->f = f;
+ s = nil;
+ switch(f){
+ case PFidle: s = o->state + OSidle; break;
+ case PFmove: s = o->state + OSmove; break;
+ default: sysfatal("readgfx: %s unknown flag", fxo->name);
+ }
+ s->gfx = fxo;
+}
+
+static void
readobj(char **fld, int, Table *tab)
{
Obj *o;
@@ -421,9 +451,9 @@
fld += 3;
n -= 3;
ps = nil;
- switch(type & 0x7e){
- case PFidle: ps = &o->pidle; break;
- case PFmove: ps = &o->pmove; break;
+ switch(type & 0xf){
+ case PFidle: ps = &o->state[OSidle].pics; break;
+ case PFmove: ps = &o->state[OSmove].pics; break;
default: sysfatal("readspr %s: invalid type %#02ux", o->name, type & 0x7e);
}
ppp = type & PFshadow ? &ps->shadow : &ps->pic;
@@ -441,15 +471,27 @@
}
}
+enum{
+ Tmapobj,
+ Tobj,
+ Tgfx,
+ Tattack,
+ Tresource,
+ Tspawn,
+ Ttileset,
+ Tmap,
+ Tspr,
+};
Table table[] = {
- {"mapobj", readmapobj, 4, &nobjp},
- {"obj", readobj, 17, &nobj},
- {"attack", readattack, 4, &nattack},
- {"resource", readresource, 2, &nresource},
- {"spawn", readspawn, -1, nil},
- {"tileset", readtileset, 1, nil},
- {"map", readmap, -1, &terheight},
- {"spr", readspr, -1, nil},
+ [Tmapobj] {"mapobj", readmapobj, 4, &nobjp},
+ [Tobj] {"obj", readobj, 17, &nobj},
+ [Tgfx] {"gfx", readgfx, 3, &nobj},
+ [Tattack] {"attack", readattack, 4, &nattack},
+ [Tresource] {"resource", readresource, 2, &nresource},
+ [Tspawn] {"spawn", readspawn, -1, nil},
+ [Ttileset] {"tileset", readtileset, 1, nil},
+ [Tmap] {"map", readmap, -1, &terheight},
+ [Tspr] {"spr", readspr, -1, nil},
};
static int
--- a/sce/sce.db
+++ b/sce/sce.db
@@ -6,18 +6,21 @@
attack,fusion cutter,5,1,15
attack,spines,5,1,22
# obj: name, flags, w, h, hp, def, vis, cost[3], time, attack[2], speed, accel, halt, turn
-obj,scv,3,4,4,60,0,7,1,50,0,20,fusion cutter,,4.97,67,12227,40
-obj,drone,1,4,4,40,0,7,1,50,0,20,spines,,4.97,67,12227,40
-obj,control,8,16,12,1500,1,1,10,400,0,1800,,,0,0,0,0
-obj,hatchery,8,16,12,1250,1,1,10,300,0,1800,,,0,0,0,0
+obj,scv,0x3,4,4,60,0,7,1,50,0,20,fusion cutter,,4.97,67,12227,40
+obj,drone,0x1,4,4,40,0,7,1,50,0,20,spines,,4.97,67,12227,40
+obj,control,0x8,16,12,1500,1,1,10,400,0,1800,,,0,0,0,0
+obj,hatchery,0x8,16,12,1250,1,1,10,300,0,1800,,,0,0,0,0
+# gfx: name, obj, flags (PF enum)
+gfx,tscglow,scv,0x4
# spawn: objname, [obj..]
spawn,control,scv
# spr: objname, flags (PF enum), rotations, [frame..]
-spr,scv,2,17,0
+spr,scv,0x2,17,0
spr,scv,0x8002,17,0
-spr,control,2,1,0
+spr,control,0x2,1,0
spr,control,0x8002,1,0
-spr,drone,4,17,0,1,2,3,4
+spr,drone,0x4,17,0,1,2,3,4
spr,drone,0x8004,17,0,1,2,3,4
spr,hatchery,2,1,0,1,2,3,3,2,1,0
spr,hatchery,0x8002,1,0,0,0,0,0,0,0,0
+spr,tscglow,0x6004,17,0,1,2,3
--- a/sim.c
+++ b/sim.c
@@ -90,7 +90,7 @@
mo->pathp = nil;
if(mo->pics->nf > 0)
mo->freezefrm = tc % mo->pics->nf;
- mo->pics = &mo->o->pidle;
+ mo->pics = &mo->o->state[OSidle].pics;
resetcoords(mo);
}
@@ -112,7 +112,8 @@
}
mo->movingp = linkmobj(moving, mo, mo->movingp);
mo->pathp = mo->paths;
- mo->pics = mo->o->pmove.pic != nil ? &mo->o->pmove : &mo->o->pidle;
+ mo->pics = mo->o->state[OSmove].pics.pic != nil
+ ? &mo->o->state[OSmove].pics : &mo->o->state[OSidle].pics;
nextmove(mo);
return 0;
}
@@ -141,7 +142,7 @@
if((mo = mapspawn(x, y, o)) == nil)
return -1;
mo->team = n;
- mo->pics = &mo->o->pidle;
+ mo->pics = &mo->o->state[OSidle].pics;
if(mo->f & Fbuild)
team[n].nbuild++;
else