Add tile editing features (copy/paste, flip, nudge), boat

This commit also has a colour-remapping experiment but it appears to be too
costly to do in real-time; will probably back it out and rethink
This commit is contained in:
Jeremy Penner 2019-09-19 21:52:24 -04:00
parent fc310582c2
commit 70785c5cfa
12 changed files with 185 additions and 40 deletions

View file

@ -70,6 +70,7 @@ array frames
( 5: car lights ) 29 27 26 28 frame
( 6: jeanne stand ) 30 32 34 36 frame
( 7: jeanne walk ) 31 33 35 37 frame
( 8: boat w/ pete ) 42 41 40 39 frame
: sprindex ( dir frame ) 2 << frames + + b@ ;
: defstatic ( frame -- ) create b, does> b@ sprindex ;
@ -95,3 +96,10 @@ array frames
6 7 2 5 defanim {jeanne-walk}
18 defsingle {phone}
38 defsingle {fridge}
43 defsingle {boat}
8 defstatic {boat-pete}
: sprite-bob ( x y sprindex -- x y sprindex )
ticks 40 % 20 < if
dup 39 >= over 43 <= and if swap 1 + swap then
then ;

BIN
game.exe

Binary file not shown.

View file

@ -31,11 +31,15 @@ var player.prevdir
1 const MOVING
2 const DRIVING
4 const NOCLIP
8 const ISMARY
16 const ISJEANNE
4 const BOATING
8 const NOCLIP
16 const ISMARY
32 const ISJEANNE
: noclip player.state NOCLIP fnot! ;
: player.driving? player.state DRIVING f@ ;
: player.boating? player.state BOATING f@ ;
: :playerwalk create , , does>
player.state MOVING f@ not if cell + then @ execute ;
@ -46,15 +50,17 @@ var player.prevdir
: {player}
player.driving? if {car-drive}
else player.boating? if {boat-pete}
else
player.state ISMARY f@ if {pmary}
else player.state ISJEANNE f@ if {pjeanne}
else {ppete} then then
then ;
player.state ISMARY f@ if {pmary}
else player.state ISJEANNE f@ if {pjeanne}
else {ppete} then then
then then ;
: player.canmove? ( x y -- )
player.state NOCLIP f@ not if
player.driving? if DRIVABLE else WALKABLE then mapflag?
player.driving? if DRIVABLE else
player.boating? if BOATABLE else WALKABLE then then mapflag?
else drop drop 1 then ;
12 9 N ' {player} defentity player
@ -145,7 +151,7 @@ player :tick
: draw-entity
>r r@ entity.x @ r@ entity.y @
r@ entity.dir @ <r entity>sprite
draw-sprite ;
sprite-bob draw-sprite ;
var showmouse
1 showmouse !

BIN
game.prj

Binary file not shown.

View file

@ -50,6 +50,13 @@ var jiles-old-draw
45 const ^X
31 const ^S
20 const ^T
33 const ^F
46 const ^C
47 const ^V
73 const ^PgUp
81 const ^PgDn
var copysrc
: jiles-tick
mousepos 128 < swap 128 < and if
@ -67,6 +74,13 @@ var jiles-old-draw
^X key-pressed if mousexys getpixel rcolor color! then
^S key-pressed if s" SAVING " type gfxfilename dup type cr savegfx then
^T key-pressed if edittarget if 0 else 1 then edittarget! 0 +sprite! then
^C key-pressed if spriteindex @ copysrc ! then
^V key-pressed if copysrc @ spriteindex @ paste-tile refresh then
^F key-pressed if spriteindex @ flip-tile refresh then
^PgDn key-pressed if 5 +sprite! then
^PgUp key-pressed if -5 +sprite! then
^UP key-pressed if -1 spriteindex @ nudge-sprite refresh then
^DOWN key-pressed if 1 spriteindex @ nudge-sprite refresh then
^TAB key-pressed if
jiles-old-draw @ ' draw redefine
jiles-old-tick @ ' tick redefine

View file

@ -7,11 +7,12 @@ var tileselect
1 const WALKABLE
2 const DRIVABLE
4 const BOATABLE
array tileflags
( grass ) WALKABLE b,
( dirt ) WALKABLE DRIVABLE | b,
( water ) 0 b,
( water ) BOATABLE b,
( pavement ) WALKABLE DRIVABLE | b,
( brick ) 0 b,
( forest ) 0 b,
@ -29,12 +30,11 @@ array tileflags
( house ) 0 b,
( fence ) 0 b,
( storefront ) 0 b,
( space ) 0 b,
here tileflags - 1 - const MAXTILE
: mapflag? ( x y flag -- b ) >rot tile b@ tileflags + b@ & ;
: walkable? ( x y -- b ) WALKABLE mapflag? ;
: drivable? ( x y -- b ) DRIVABLE mapflag? ;
: tick-mapedit
tileselect @

View file

@ -2,12 +2,18 @@
13 8 N ' {car} defentity car
32 5 W ' {horse} defentity e_chuck
17 10 W ' {boat} defentity boat
car :touch
move-player
1 player.state DRIVING f!
;entity
boat :touch
move-player
1 player.state BOATING f!
;entity
e_chuck :touch
pete say" It's good to have you\back, Chuck."
chuck say" * w h i n n y *\(I remember this place...)"
@ -16,6 +22,7 @@ e_chuck :touch
:noname
:| player.driving? not CHUCK-FOLLOW flag@ not and if car yield then
CHUCK-STOLEN flag@ if e_chuck yield then
player.boating? not if boat yield then
done |; ' entities redefine
:|

Binary file not shown.

View file

@ -216,7 +216,7 @@ void f_keyIsDown() {
}
void f_drawSprite() { // ( x y sprite -- )
drawSprite(&sprites[TOP().i * SPRITE_STRIDE], ST2().i, ST1().i);
drawSprite(&sprites[TOP().i * SPRITE_STRIDE], ST2().i, ST1().i, NULL);
DROP(3);
}
@ -303,10 +303,10 @@ void f_glitch() {
y = screen.scrollY + (rand() % 232) - 16;
switch(rand()%2) {
case 0:
drawSprite(sprites + (rand() % (NUM_SPRITES * SPRITE_STRIDE)), x, y);
drawSprite(sprites + (rand() % (NUM_SPRITES * SPRITE_STRIDE)), x, y, NULL);
break;
case 1:
drawSprite(mem + (rand() % MEM_SIZE), x, y);
drawSprite(mem + (rand() % MEM_SIZE), x, y, NULL);
break;
}
}
@ -467,7 +467,72 @@ void f_spr2buf() {
unsigned int *buf = (unsigned int *)TOP().p;
unsigned int isprite = ST1().u;
DROP(2);
overlaySprite(buf, &sprites[isprite * SPRITE_STRIDE], 0, 0);
overlaySprite(buf, &sprites[isprite * SPRITE_STRIDE], 0, 0, NULL);
}
void f_remap_spr2buf() {
unsigned int *buf = (unsigned int *)TOP().p;
unsigned int isprite = ST1().u;
char *remap = (char*)ST2().p;
DROP(3);
overlaySprite(buf, &sprites[isprite * SPRITE_STRIDE], 0, 0, remap);
}
void f_pastetile() {
unsigned int far *src;
unsigned int far *dst;
unsigned int far *gfx = editTarget == ET_SPRITE ? sprites : tiles;
unsigned int stride = editTarget == ET_SPRITE ? SPRITE_STRIDE : TILE_STRIDE;
unsigned int i;
src = &gfx[ST1().i * stride];
dst = &gfx[TOP().i * stride];
DROP(2);
for (i = 0; i < stride; i ++) {
dst[i] = src[i];
}
}
void f_fliptile() {
unsigned int far *dst;
unsigned int far *gfx = editTarget == ET_SPRITE ? sprites : tiles;
unsigned int stride = editTarget == ET_SPRITE ? SPRITE_STRIDE : TILE_STRIDE;
unsigned int i;
unsigned int bit;
dst = &gfx[TOP().i * stride];
DROP(1);
for (i = 0; i < stride; i ++) {
unsigned int src = dst[i];
unsigned int result = 0;
for (bit = 0; bit < 16; bit ++) {
if (src & (1 << bit)) {
result |= (1 << (15 - bit));
}
}
dst[i] = result;
}
}
void f_nudgesprite() {
unsigned int far *dst = &sprites[TOP().i * SPRITE_STRIDE];
int direction = ST1().i < 0 ? -1 : 1;
int ystart = direction < 0 ? 0 : 15;
int ylim = direction < 0 ? 15 : 0;
int plane, y;
unsigned int itransparent = direction < 0 ? 64 : 79;
DROP(2);
if (dst[itransparent] != 0 || editTarget != ET_SPRITE) {
return;
}
for (plane = 0; plane < 5; plane ++) {
for (y = ystart; y != ylim; y -= direction) {
dst[y] = dst[y - direction];
}
dst[ylim] = 0;
dst += 16;
}
}
void f_paintbuf() {
@ -527,10 +592,14 @@ void game_f_init(char *exe, char *bootjor) {
CDEF("savegfx", f_savegfx);
CDEF("tile>buf", f_tile2buf);
CDEF("spr>buf", f_spr2buf);
CDEF("remap-spr>buf", f_remap_spr2buf);
CDEF("paintbuf", f_paintbuf);
CDEF("edittarget", f_getedittarget);
CDEF("edittarget!", f_setedittarget);
CDEF("reloadtiles", f_reloadtiles);
CDEF("paste-tile", f_pastetile);
CDEF("flip-tile", f_fliptile);
CDEF("nudge-sprite", f_nudgesprite);
f_loadjor(bootjor);

85
tiles.c
View file

@ -107,7 +107,7 @@ void writeTile(unsigned int *buf, unsigned int far *tile) {
}
}
void overlaySprite(unsigned int *buf, unsigned int far *sprite, int shift, int yStart) {
void overlaySprite(unsigned int *buf, unsigned int far *sprite, int shift, int yStart, char *remap) {
unsigned int far *mask;
unsigned int maskval;
int y, h, plane;
@ -120,24 +120,65 @@ void overlaySprite(unsigned int *buf, unsigned int far *sprite, int shift, int y
h = 16 - yStart;
}
mask = &sprite[BUF_WSTRIDE * 4];
if (shift < 0) {
shift = -shift;
for (plane = 0; plane < 4; plane ++) {
for (y = 0; y < h; y ++) {
maskval = mask[y] << shift;
buf[y] = (buf[y] & ~maskval) | ((sprite[y] << shift) & maskval);
if (!remap) {
if (shift < 0) {
shift = -shift;
for (plane = 0; plane < 4; plane ++) {
for (y = 0; y < h; y ++) {
maskval = mask[y] << shift;
buf[y] = (buf[y] & ~maskval) | ((sprite[y] << shift) & maskval);
}
sprite += BUF_WSTRIDE;
buf += BUF_WSTRIDE;
}
} else {
for (plane = 0; plane < 4; plane ++) {
for (y = 0; y < h; y ++) {
maskval = mask[y] >> shift;
buf[y] = (buf[y] & ~maskval) | ((sprite[y] >> shift) & maskval);
}
sprite += BUF_WSTRIDE;
buf += BUF_WSTRIDE;
}
sprite += BUF_WSTRIDE;
buf += BUF_WSTRIDE;
}
} else {
for (plane = 0; plane < 4; plane ++) {
for (y = 0; y < h; y ++) {
maskval = mask[y] >> shift;
buf[y] = (buf[y] & ~maskval) | ((sprite[y] >> shift) & maskval);
unsigned int b, bo, g, go, r, ro, i, io, bgri;
int bit;
if (shift < 0) {
shift = -shift;
#define SPLANE(b, y, p) b[y + (BUF_WSTRIDE * (p))]
#define DO_REMAP(ss, bitstart, bitlim) \
for (y = 0; y < h; y ++) { \
bo = go = ro = io = 0; \
b = SPLANE(sprite, y, 0); \
g = SPLANE(sprite, y, 1); \
r = SPLANE(sprite, y, 2); \
i = SPLANE(sprite, y, 3); \
for (bit = (bitstart); bit < (bitlim); bit ++) { \
int bshift = 1 << bit; \
bgri = ((b & bshift) ? 0x01 : 0x00) | \
((g & bshift) ? 0x02 : 0x00) | \
((r & bshift) ? 0x04 : 0x00) | \
((i & bshift) ? 0x08 : 0x00); \
bgri = remap[bgri]; \
if (bgri & 0x01) bo |= bshift; \
if (bgri & 0x02) go |= bshift; \
if (bgri & 0x04) ro |= bshift; \
if (bgri & 0x08) io |= bshift; \
} \
maskval = mask[y] ss shift; \
SPLANE(buf, y, 0) = (SPLANE(buf, y, 0) & ~maskval) | ((bo ss shift) & maskval); \
SPLANE(buf, y, 1) = (SPLANE(buf, y, 1) & ~maskval) | ((go ss shift) & maskval); \
SPLANE(buf, y, 2) = (SPLANE(buf, y, 2) & ~maskval) | ((ro ss shift) & maskval); \
SPLANE(buf, y, 3) = (SPLANE(buf, y, 3) & ~maskval) | ((io ss shift) & maskval); \
}
sprite += BUF_WSTRIDE;
buf += BUF_WSTRIDE;
DO_REMAP(<<, shift, 16)
} else {
DO_REMAP(>>, 0, 16 - shift)
#undef DO_REMAP
#undef SPLANE
}
}
}
@ -159,7 +200,7 @@ int prepareBuffer(int pageX, int pageY) {
return *dirty;
}
void drawSpriteToBuf(unsigned int far *sprite, int pageX, int pageY, int shift, int yStart) {
void drawSpriteToBuf(unsigned int far *sprite, int pageX, int pageY, int shift, int yStart, char *remap) {
unsigned int *buf;
if (pageX < 0 || pageY < 0 ||
@ -170,19 +211,19 @@ void drawSpriteToBuf(unsigned int far *sprite, int pageX, int pageY, int shift,
}
buf = screen.buffer[prepareBuffer(pageX, pageY)];
overlaySprite(buf, sprite, shift, yStart);
overlaySprite(buf, sprite, shift, yStart, remap);
}
void drawSprite(unsigned int far *sprite, int x, int y) {
void drawSprite(unsigned int far *sprite, int x, int y, char *remap) {
int pageX = (int)(x - (screen.scrollX & 0xfff0)) >> 4;
int pageY = (int)(y - (screen.scrollY & 0xfff0)) >> 4;
int pageOffsetX = x & 0x0f;
int pageOffsetY = y & 0x0f;
drawSpriteToBuf(sprite, pageX, pageY, pageOffsetX, pageOffsetY);
drawSpriteToBuf(sprite, pageX + 1, pageY, pageOffsetX - 16, pageOffsetY);
drawSpriteToBuf(sprite, pageX, pageY + 1, pageOffsetX, pageOffsetY - 16);
drawSpriteToBuf(sprite, pageX + 1, pageY + 1, pageOffsetX - 16, pageOffsetY - 16);
drawSpriteToBuf(sprite, pageX, pageY, pageOffsetX, pageOffsetY, remap);
drawSpriteToBuf(sprite, pageX + 1, pageY, pageOffsetX - 16, pageOffsetY, remap);
drawSpriteToBuf(sprite, pageX, pageY + 1, pageOffsetX, pageOffsetY - 16, remap);
drawSpriteToBuf(sprite, pageX + 1, pageY + 1, pageOffsetX - 16, pageOffsetY - 16, remap);
}
void scroll(int newX, int newY) {

BIN
tiles.gfx

Binary file not shown.

View file

@ -6,14 +6,14 @@ void tile_init();
void loadTiles(unsigned int tilesOffset, unsigned int far *memTiles);
void loadMap(unsigned char *map, unsigned int w, unsigned int h);
void drawSprite(unsigned int far *sprite, int x, int y);
void drawSprite(unsigned int far *sprite, int x, int y, char *remap);
void scroll(int newX, int newY);
void drawScreen();
void blit32x32(unsigned int offsetFrom, unsigned int offsetTo);
void writeTile(unsigned int *buf, unsigned int far *tile);
void overlaySprite(unsigned int *buf, unsigned int far *sprite, int shift, int yStart);
void overlaySprite(unsigned int *buf, unsigned int far *sprite, int shift, int yStart, char *remap);
void paintBuffer(unsigned int *buf, unsigned int vidOffset);
#define PAGE_TILES_W 21