From 52bf13367fe28cb171c7bdd391f6f1d3bdbf2346 Mon Sep 17 00:00:00 2001 From: toasterbabe <rollerorbital@gmail.com> Date: Thu, 16 Jun 2016 00:59:54 +0100 Subject: [PATCH] New rotation functionality. * NAMEcL refers to a frame which is seen for the entirety of an object's left side. * NAMEcR refers to a name which is seen for the entirety of an object's right side. * NAMEcLcR does both sides. * Having just a NAMEcL requires you to fill in the opposite side either with NAMEcn where n is 1 and 5 to 8 OR fill in with a NAMEcR * Switches down the centerline of the object instead of at the ANGLE_202h interval for normal sprites. * Characters were selected for 1) ease of use and 2) not getting in the way of adding support for zdoom's totally bananas 16-way sprite system at a later date if we so choose --- src/hardware/hw_main.c | 11 ++++++-- src/r_defs.h | 6 +++++ src/r_things.c | 57 ++++++++++++++++++++++++++++++++++-------- src/r_things.h | 9 +++++++ 4 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 35a01ffd1..aba89bdcd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5095,8 +5095,15 @@ static void HWR_ProjectSprite(mobj_t *thing) if (sprframe->rotate) { // choose a different rotation based on player view - ang = R_PointToAngle(thing->x, thing->y); // uses viewx,viewy - rot = (ang-thing->angle+ANGLE_202h)>>29; + ang = R_PointToAngle (thing->x, thing->y) - thing->angle; + + if ((ang < ANGLE_180) && (sprframe->rotate & 4)) // See from right + rot = 6; // F7 slot + else if ((ang >= ANGLE_180) && (sprframe->rotate & 2)) // See from left + rot = 2; // F3 slot + else // Normal behaviour + rot = (ang+ANGLE_202h)>>29; + //Fab: lumpid is the index for spritewidth,spriteoffset... tables lumpoff = sprframe->lumpid[rot]; flip = sprframe->flip & (1<<rot); diff --git a/src/r_defs.h b/src/r_defs.h index 848708164..2ff2cacf9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -739,10 +739,16 @@ typedef struct // object and may have multiple rotations predrawn. // Horizontal flipping is used to save space, thus NNNNF2F5 defines a mirrored patch. // Some sprites will only have one picture used for all views: NNNNF0 +// Some sprites will take the entirety of the left side: NNNNFL +// Or the right side: NNNNFR +// Or both, mirrored: NNNNFLFR // typedef struct { // If false use 0 for any position. + // If L is present, (rotate & 2) == 2. + // If R is present, (rotate & 4) == 4. + // Otherwise, use 1. // Note: as eight entries are available, we might as well insert the same // name eight times. UINT8 rotate; diff --git a/src/r_things.c b/src/r_things.c index eaab53613..4f1faae97 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -100,7 +100,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch lumppat <<= 16; lumppat += lump; - if (frame >= 64 || rotation > 8) + if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) I_Error("R_InstallSpriteLump: Bad frame characters in lump %s", W_CheckNameForNum(lumppat)); if (maxframe ==(size_t)-1 || frame > maxframe) @@ -111,8 +111,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch // the lump should be used for all rotations if (sprtemp[frame].rotate == 0) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); - - if (sprtemp[frame].rotate == 1) + else // Let's complain for both 1-8 and L/R rotations. CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); sprtemp[frame].rotate = 0; @@ -121,15 +120,46 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch sprtemp[frame].lumppat[r] = lumppat; sprtemp[frame].lumpid[r] = lumpid; } - sprtemp[frame].flip = flipped ? UINT8_MAX : 0; + sprtemp[frame].flip = flipped ? UINT8_MAX : 0; // 11111111 in binary + return; + } + + if (rotation == ROT_L || rotation == ROT_R) + { + UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0); + + // the lump should be used for half of all rotations + if (sprtemp[frame].rotate == 0) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); + else if (sprtemp[frame].rotate == 1) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); + // Let's not complain about multiple L/R rotations. It's not worth the effort. + + sprtemp[frame].rotate |= ((rotation == ROT_R) ? 4 : 2); + for (r = 0; r < 4; r++) + { + if ((r != 0) || (sprtemp[frame].lumppat[rotation] == LUMPERROR)) // Only set front/back angles if they don't exist + { + sprtemp[frame].lumppat[r + rightfactor] = lumppat; + sprtemp[frame].lumpid[r + rightfactor] = lumpid; + } + } + sprtemp[frame].flip |= (flipped ? (0x0F << rightfactor) : 0); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R return; } // the lump is only used for one rotation if (sprtemp[frame].rotate == 0) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8 rotations and a rot = 0 lump\n", spritename, cn); + else if (sprtemp[frame].rotate != 1) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); - sprtemp[frame].rotate = 1; + if (rotation == 0 || rotation == 4) // Front or back... + sprtemp[frame].rotate = 1; // Prevent L and R changeover + else if (rotation > 3) // Right side + sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 2)); // Continue allowing L frame changeover + else // if (rotation <= 3) // Left side + sprtemp[frame].rotate = (1 | (sprtemp[frame].rotate & 4)); // Continue allowing R frame changeover // make 0 based rotation--; @@ -195,7 +225,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, frame = R_Char2Frame(lumpinfo[l].name[4]); rotation = (UINT8)(lumpinfo[l].name[5] - '0'); - if (frame >= 64 || rotation > 8) // Give an actual NAME error -_-... + if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) // Give an actual NAME error -_-... { CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); continue; @@ -287,7 +317,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, // only the first rotation is needed break; - case 1: + default: // must have all 8 frames for (rotation = 0; rotation < 8; rotation++) // we test the patch lump, or the id lump whatever @@ -1132,8 +1162,15 @@ static void R_ProjectSprite(mobj_t *thing) if (sprframe->rotate) { // choose a different rotation based on player view - ang = R_PointToAngle (thing->x, thing->y); - rot = (ang-thing->angle+ANGLE_202h)>>29; + ang = R_PointToAngle (thing->x, thing->y) - thing->angle; + + if ((ang < ANGLE_180) && (sprframe->rotate & 4)) // See from right + rot = 6; // F7 slot + else if ((ang >= ANGLE_180) && (sprframe->rotate & 2)) // See from left + rot = 2; // F3 slot + else // Normal behaviour + rot = (ang+ANGLE_202h)>>29; + //Fab: lumpid is the index for spritewidth,spriteoffset... tables lump = sprframe->lumpid[rot]; flip = sprframe->flip & (1<<rot); diff --git a/src/r_things.h b/src/r_things.h index 483db7e99..8aa799c44 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -17,6 +17,10 @@ #include "sounds.h" #include "r_plane.h" +// "Left" and "Right" character symbols for additional rotation functionality +#define ROT_L ('L' - '0') +#define ROT_R ('R' - '0') + // number of sprite lumps for spritewidth,offset,topoffset lookup tables // Fab: this is a hack : should allocate the lookup tables per sprite #define MAXVISSPRITES 2048 // added 2-2-98 was 128 @@ -230,4 +234,9 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn) #endif } +FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation) +{ + return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R)); +} + #endif //__R_THINGS__ -- GitLab