
|
|
Author |
Message |
BrotherTank
Forum Administrator

Joined: 01 Mar 2003
Last Visit: 13 Sep 2017
Topics: 153
Posts: 2255
Location: Ontario

|
Posted: Tue Mar 16, 2004 12:10 pm
Subject: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

 
|
|
Formatting is a little messed up but...
Directional 3D sprites
By Ripper
Hi and welcome to my first tutorial for Wolfenstein 3D ;D
I hope this will help you make some of your dreams come true
As you may already have noticed, this tutorial wants to teach you, how to include "directional 3D sprites" into your Wolfenstein 3D engine. But first of all: WHAT THE HELL ARE "directional 3D sprites" ???
To explain this remember those glass sprites in some TCs which were used to make a glass wall between two wall sides. When you looked perpendicularly at them, they looked all nice. But when you turned a bit around and looked at them again, you should have noticed, that they turned with you! Or another example: you probably remember some outdoor scenes with fences painted on walls. Or imagine a house/bunker with windows! With normal sprites this is impossible if you don't want the user to only run straight forward to the window *gg*
But before I start telling you how you can add it to your own TC or whatever, I want to reveal some negative points you'll have to remember when trying to add directional sprites:
- The first two (didn't tried just one yet) and the last column of a sprites image have to be empty or Wolfenstein 3D will crash when it tries to paint the sprites. Update: With DarkOne's sprite bug fix, you'll be able to use all 64 columns (keeping the next point in mind)!
- Due to the limitation to 4096 bytes per sprite it isn't possible yet to make a "wall" sprite as tall as a normal wall without using some tricks I won't mention here.
- This feature is rather powerful as there are many possiblities you can use it. With some individual code changes you can even create turning doors and many other things you can't even imagine *gg* But of course that's why it's "a little bit" complicated so at first you'll have to play around with it before you get used to it. This is mainly because of the limited map format which only allows simple object numbers and no individual data for a object at all (i.e. an integer to provide an angle). That's why we'd have to create a new object for every angle used inside a map (this version only supports two different angles, but you can implement more angles, of course). Not very nice, but currently the only way
- As you should know, playing around with the source code of Wolfenstein 3D causes many system crashes which are too often binded with data loss (i.e. I lost hundreds of MB because my whole system crashed many times during downloads... very funny... ). So you're the only one responsible for what happens if your Wolfenstein 3D engine doesn't do the things it should, say it crashes! But you should already be used to it
- In the following code there seems to be at least one "wolf only crash" causing bug which appears extremly rare when running through such sprites. So you can find the bug and kill it, prohibit running through directional 3d sprites or leave the bug doing what he wants to do. It's probably a division error...
- Although the sprites are sorted by distance it is possible that they are drawn in the wrong order when having differently positioned sprites next to each other:
- Probably some other things I can't remember right now
Now that this is said, let's start:
At first make sure your current version of Wolfenstein 3D is working without major problems, though it would be perfectly if it would run without any problems, but that's a rare situation, isn't it? Then make a backup of your current source code, so that you won't be unable to restore the working status.
Now open your WL_SCALE.C and append (add) the following code to the end of the file:
::: CODE :::
void Scale3DShaper (int x1,int x2,int shapenum,unsigned height1,unsigned height2,
fixed ny1,fixed ny2,fixed nx1,fixed nx2)
{
t_compshape _seg *shape;
t_compscale _seg *comptable;
unsigned scale1,scale2;
unsigned far *cmdptr;
int dx=x2-x1,len,i;
fixed height,dheight;
int xpos[65];
fixed dxx=(ny2-ny1)<<8,dzz=(nx2-nx1)<<8;
fixed dxa=0,dza=0;
if(!dx) return;
height=((fixed)height1)<<12+2048;
dheight=(((fixed)height2-(fixed)height1)<<12)/(fixed)dx;
// Get length/address of pixeldata
shape = PM_GetSpritePage (shapenum);
scale1 = height1>>3; // low three bits are fractional
scale2 = height2>>3; // low three bits are fractional
if (!scale1 && !scale2 || scale1>maxscale && scale2>maxscale)
return; // too close or far away*/
len=shape->rightpix-shape->leftpix;
if(!len) return;
dxx/=len,dzz/=len;
xpos[0]=(int)((ny1+(dxa>>8))*scale/(nx1+(dza>>8))+centerx);
for(i=1;i<=len;i++)
{
dxa+=dxx,dza+=dzz;
xpos[i]=(int)((ny1+(dxa>>8))*scale/(nx1+(dza>>8))+centerx);
if(xpos[i-1]>viewwidth) break;
}
len=i-1;
*(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape
cmdptr = &shape->dataofs[0];
slinewidth = 1;
i=0;
if(x2>viewwidth) x2=viewwidth;
for(i=0;i<len;i++)
{
for(slinex=xpos[i];slinex<xpos[i+1] && slinex<x2;slinex++)
{
height+=dheight;
if(slinex<0) continue;
scale1=(unsigned)(height>>15);
if(wallheight[slinex]<(height>>12) && scale1 && scale1<=maxscale)
{
comptable = scaledirectory[scale1];
*(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call
(unsigned)linecmds=cmdptr[i];
ScaleLine();
}
}
}
}
extern long playx,playy;
void Scale3DShape(statobj_t *ob)
{
fixed nx1,nx2,ny1,ny2;
int viewx1,viewx2;
long height1,height2;
fixed diradd;
//
// the following values for "diradd" aren't optimized yet
// if you have problems with sprites being visible through wall edges
// where they shouldn't, you can try to adjust these values and
// the -1024 and +2048 in both "if" blocks
//
if(ob->flags & FL_DIRFORWARD) diradd=0x7ff0+0x8000;
else if(ob->flags & FL_DIRBACKWARD) diradd=-0x7ff0+0x8000;
else diradd=0x8000;
if(ob->flags & FL_DIREAST)
{
fixed gx1,gx2,gy,gxt1,gxt2,gyt;
//
// translate point to view centered coordinates
//
gx1 = (((long)ob->tilex) << TILESHIFT)+0x8000-playx-0x8000L-1024;
gx2 = gx1+0x10000L+2048;
gy = (((long)ob->tiley) << TILESHIFT)+diradd-playy;
//
// calculate newx
//
gxt1 = FixedByFrac(gx1,viewcos);
gxt2 = FixedByFrac(gx2,viewcos);
gyt = FixedByFrac(gy,viewsin);
nx1 = gxt1-gyt-0x2000;
nx2 = gxt2-gyt-0x2000;
//
// calculate newy
//
gxt1 = FixedByFrac(gx1,viewsin);
gxt2 = FixedByFrac(gx2,viewsin);
gyt = FixedByFrac(gy,viewcos);
ny1 = gyt+gxt1;
ny2 = gyt+gxt2;
}
else
{
fixed gy1,gy2,gx,gyt1,gyt2,gxt;
//
// translate point to view centered coordinates
//
gy1 = (((long)ob->tiley) << TILESHIFT)+0x8000-playy-0x8000L-1024;
gy2 = gy1+0x10000L+2048;
gx = (((long)ob->tilex) << TILESHIFT)+diradd-playx;
//
// calculate newx
//
gxt = FixedByFrac(gx,viewcos);
gyt1 = FixedByFrac(gy1,viewsin);
gyt2 = FixedByFrac(gy2,viewsin);
nx1 = gxt-gyt1-0x2000;
nx2 = gxt-gyt2-0x2000;
//
// calculate newy
//
gxt = FixedByFrac(gx,viewsin);
gyt1 = FixedByFrac(gy1,viewcos);
gyt2 = FixedByFrac(gy2,viewcos);
ny1 = gyt1+gxt;
ny2 = gyt2+gxt;
}
//
// calculate perspective ratio
//
if(nx1>=0 && nx1<=1792) nx1=1792;
if(nx1<0 && nx1>=-1792) nx1=-1792;
if(nx2>=0 && nx2<=1792) nx2=1792;
if(nx2<0 && nx2>=-1792) nx2=-1792;
viewx1=(int)(centerx+ny1*scale/nx1);
viewx2=(int)(centerx+ny2*scale/nx2);
//
// calculate height (heightnumerator/(nx>>8)) (heightnumerator=0x36800)
//
asm mov ax,word ptr heightnumerator
asm mov dx,word ptr heightnumerator+2
asm idiv word ptr nx1+1 // nx1>>8
asm mov word ptr height1,ax
asm mov word ptr height1+2,dx
asm mov ax,word ptr heightnumerator
asm mov dx,word ptr heightnumerator+2
asm idiv word ptr nx2+1 // nx2>>8
asm mov word ptr height2,ax
asm mov word ptr height2+2,dx
if(viewx2 < viewx1)
Scale3DShaper(viewx2,viewx1,ob->shapenum,(unsigned)height2,
(unsigned)height1,ny2,ny1,nx2,nx1);
else
Scale3DShaper(viewx1,viewx2,ob->shapenum,(unsigned)height1,
(unsigned)height2,ny1,ny2,nx1,nx2);
}
Update: At this point I'll insert DarkOne's sprite bug fix, so that you'll be able to use full width sprites.
Replace the ScaleShape and SimpleScaleShape functions with the following functions:
::: CODE :::
void ScaleShape (int xcenter, int shapenum, unsigned height)
{
t_compshape _seg *shape;
t_compscale _seg *comptable;
unsigned scale,srcx,startx,stopx,next_x;
unsigned far *cmdptr;
boolean leftvis, rightvis;
shape=PM_GetSpritePage(shapenum);
scale=height>>3; // low three bits are fractional
if(!scale || scale>maxscale) return; // too close or far away
comptable=scaledirectory[scale];
*(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call
*(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape
next_x=slinex=xcenter-scale;
cmdptr=shape->dataofs;
startx=shape->leftpix;
stopx=shape->rightpix;
for(srcx=0; srcx<=stopx; srcx++, slinex=next_x)
{
if(slinex>=viewwidth) break; // off the screen
slinewidth=comptable->width[srcx];
next_x+=slinewidth; // next slinex
if(srcx<startx) continue; // before the shape
(unsigned)linecmds=*cmdptr++;
if(!slinewidth) continue;
if(slinewidth==1)
{
if(slinex<0 || slinex>=viewwidth) continue;
if(wallheight[slinex]>=height) continue; // obscured by closer wall
ScaleLine();
}
else
{
if(slinex<0)
{
if(slinewidth<=-slinex) continue; // still off the left edge
slinewidth-=slinex;
slinex=0;
}
else if(slinex+slinewidth>viewwidth)
slinewidth=viewwidth-slinex;
leftvis=(wallheight[slinex]<height);
rightvis=(wallheight[slinex+slinewidth-1]<height);
if(leftvis)
{
if(rightvis)
ScaleLine();
else
{
while(wallheight[slinex+slinewidth-1]>=height) slinewidth--;
ScaleLine();
break; // the rest of the shape is gone
}
}
else
{
if(rightvis)
{
while(wallheight[slinex]>=height)
{
slinex++;
slinewidth--;
}
ScaleLine ();
}
else
continue; // totally obscured
}
}
}
}
void SimpleScaleShape (int xcenter, int shapenum, unsigned height)
{
t_compshape _seg *shape;
t_compscale _seg *comptable;
unsigned scale,srcx,startx,stopx,next_x;
int t;
unsigned far *cmdptr;
boolean leftvis,rightvis;
shape = PM_GetSpritePage (shapenum);
scale = height>>1;
comptable = scaledirectory[scale];
*(((unsigned *)&linescale)+1)=(unsigned)comptable; // seg of far call
*(((unsigned *)&linecmds)+1)=(unsigned)shape; // seg of shape
next_x=slinex=xcenter-scale;
cmdptr=shape->dataofs;
startx=shape->leftpix;
stopx=shape->rightpix;
for(srcx=0; srcx<=stopx; srcx++, slinex=next_x)
{
if(slinex>=viewwidth) break; // off the screen
slinewidth=comptable->width[srcx];
next_x+=slinewidth; // next slinex
if(srcx<startx) continue; // before the shape
(unsigned)linecmds=*cmdptr++;
if(!slinewidth) continue;
if(slinewidth==1)
{
if(slinex<0 || slinex>=viewwidth) continue;
ScaleLine();
}
else
{
if(slinex<0)
{
if(slinewidth<=-slinex) continue; // still off the left edge
slinewidth-=slinex;
slinex=0;
}
else if(slinex+slinewidth>viewwidth)
slinewidth=viewwidth-slinex;
ScaleLine();
}
}
}
If you use the normal SetupScaling function, very near walls and sprites get pixelized upper and lower edges because they optimized the scalers to save some memory. For normal walls and sprites that's ok, but for directional 3D sprites you'll probably see the difference.
So IF you don't want very near sprites to look pixelized, you'll have to change the SetupScaling function at the very begining of WL_SCALE.C. There you have to comment out the following red marked lines by adding a "//" in front of them:
::: CODE :::
//
// free up old scalers
//
for (i=1;i<MAXSCALEHEIGHT;i++)
{
if (scaledirectory[i])
MM_FreePtr (&(memptr)scaledirectory[i]);
if (i>=stepbytwo)
i += 2;
}
memset (scaledirectory,0,sizeof(scaledirectory));
MM_SortMem ();
//
// build the compiled scalers
//
stepbytwo = viewheight/2; // save space by double stepping
MM_GetPtr (&(memptr)work,20000);
for (i=1;i<=maxscaleheight;i++)
{
BuildCompScale (i*2,&(memptr)scaledirectory[i]);
if (i>=stepbytwo)
i+= 2;
}
MM_FreePtr (&(memptr)work);
//
// compact memory and lock down scalers
//
MM_SortMem ();
for (i=1;i<=maxscaleheight;i++)
{
MM_SetLock (&(memptr)scaledirectory[i],true);
fullscalefarcall[i] = (unsigned)scaledirectory[i];
fullscalefarcall[i] <<=16;
fullscalefarcall[i] += scaledirectory[i]->codeofs[0];
if (i>=stepbytwo)
{
scaledirectory[i+1] = scaledirectory[i];
fullscalefarcall[i+1] = fullscalefarcall[i];
scaledirectory[i+2] = scaledirectory[i];
fullscalefarcall[i+2] = fullscalefarcall[i];
i+=2;
}
}
scaledirectory[0] = scaledirectory[1];
fullscalefarcall[0] = fullscalefarcall[1];
Now let's go the next file WL_DRAW.C:
First add the following line at the begining right under GLOBAL VARIABLES
::: CODE :::
long playx,playy;
Then go to the DrawScaleds function and add the following blue marked lines:
::: CODE :::
#define MAXVISABLE 50
typedef struct
{
int viewx,
viewheight,
shapenum;
statobj_t *transsprite;
} visobj_t;
visobj_t vislist[MAXVISABLE],*visptr,*visstep,*farthest;
void Scale3DShape(statobj_t *ob);
void DrawScaleds (void)
{
int i,j,least,numvisable,height;
[...]
if (!visptr->viewheight)
continue; // to close to the object
if(statptr->flags & (FL_DIRSOUTH | FL_DIREAST))
visptr->transsprite=statptr;
else
visptr->transsprite=NULL;
if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
visptr++;
[...]
if (obj->state->rotate)
visptr->shapenum += CalcRotate (obj);
if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
{
visptr->transsprite=NULL;
visptr++;
}
obj->flags |= FL_VISABLE;
[...]
//
// draw farthest
//
if(farthest->transsprite)
Scale3DShape(farthest->transsprite);
else
ScaleShape(farthest->viewx,farthest->shapenum,farthest->viewheight);
farthest->viewheight = 32000;
}
The last change in this file is in the ThreeDRefresh function:
::: CODE :::
//
// draw all the scaled images
//
playy=(player->y+FixedByFrac(0x7300,viewsin));
playx=(player->x-FixedByFrac(0x7300,viewcos));
DrawScaleds(); // draw scaled stuff
DrawPlayerWeapon (); // draw player's hands
[/quote]
Your next victim (file to edit) is WL_DEF.H some pages under GLOBAL CONSTANTS
[quote="code"]// object flag values
#define FL_SHOOTABLE 1
#define FL_BONUS 2
#define FL_NEVERMARK 4
#define FL_VISABLE 8
#define FL_ATTACKMODE 16
#define FL_FIRSTATTACK 32
#define FL_AMBUSH 64
#define FL_NONMARK 128
#define FL_DIRSOUTH 16
#define FL_DIREAST 32
#define FL_DIRFORWARD 64
#define FL_DIRBACKWARD 128
Then go to GLOBAL TYPES and add these blue lines:
::: CODE :::
bo_machinegun,
bo_chaingun,
bo_food,
bo_fullheal,
bo_25clip,
bo_spear, // add a comma to the end of bo_spear as shown
dir_south,
dir_south_fw,
dir_south_bw,
dir_east,
dir_east_fw,
dir_east_bw,
bl_dir_south,
bl_dir_south_fw,
bl_dir_south_bw,
bl_dir_east,
bl_dir_east_fw,
bl_dir_east_bw
Now let's change WL_ACT1.C! When you're already here, you can also add two example directional sprites. For that go to the end of the object list and add the blue lines:
::: CODE :::
//
// NEW PAGE
//
#ifdef SPEAR
{SPR_STAT_48,block}, // marble pillar
{SPR_STAT_49,bo_25clip}, // bonus 25 clip
{SPR_STAT_50,block}, // truck
{SPR_STAT_51,bo_spear}, // SPEAR OF DESTINY!
#endif
{SPR_STAT_26,bo_clip2}, // Clip "
{SPR_STAT_47,dir_south},
{SPR_STAT_47,bl_dir_east},
{-1} // terminator
};
In the SpawnStatic function you have to add this(in blue again):
::: CODE :::
case bo_alpo:
case bo_gibs:
case bo_spear:
laststatobj->flags = FL_BONUS;
laststatobj->itemnumber = statinfo[type].type;
break;
case bl_dir_south:
case bl_dir_south_fw:
case bl_dir_south_bw:
(unsigned)actorat[tilex][tiley] = 1; // consider it a blocking tile
case dir_south:
case dir_south_fw:
case dir_south_bw:
laststatobj->flags=FL_DIRSOUTH;
break;
case bl_dir_east:
case bl_dir_east_fw:
case bl_dir_east_bw:
(unsigned)actorat[tilex][tiley] = 1; // consider it a blocking tile
case dir_east:
case dir_east_fw:
case dir_east_bw:
laststatobj->flags=FL_DIREAST;
break;
}
switch(statinfo[type].type)
{
case dir_south_fw:
case bl_dir_south_fw:
case dir_east_fw:
case bl_dir_east_fw:
laststatobj->flags|=FL_DIRFORWARD;
break;
case dir_south_bw:
case bl_dir_south_bw:
case dir_east_bw:
case bl_dir_east_bw:
laststatobj->flags|=FL_DIRBACKWARD;
break;
}
laststatobj++;
if (laststatobj == &statobjlist[MAXSTATS])
Quit ("Too many static objects!\n");
}
Update: While updating this tutorial, I noticed, that I forgot to mention a source code change in the WL_GAME.C to make the example work...
You've got to add the following blue lines in the ScanInfoPlane function:
::: CODE :::
case 70:
#ifdef SPEAR
case 71:
case 72:
case 73: // TRUCK AND SPEAR!
case 74:
#endif
case 72:
case 73:
SpawnStatic(x,y,tile-23);
break;
That were all source code changes for now ;D
So all what's left is to include some directional 3D sprites into your map! I'll only explain this for FloEdit, because it's the only editor I have and use (I know it's crashing a little bit too much, but I'm not responsible for making maps )
After you have connected to your Wolfenstein 3D files you'll be using for this engine, go into the Professional mode dialog under "Extra". There click on Add new record and enter the following values:
- New ID: 72
- Description: Vines N/S
- Kind: Object
- Database position: 10000
Then once again Add new record:
- New ID: 73
- Description: Vines W/E
- Kind: Object
- Database position: 10001
Now you'll just have to add those objects (as many times as you wish (more or less )), save your changes, compile your wolf3d engine and watch the results ;D
If everything works, you can add more directional 3D sprites using your own graphics and individual sprite states (I'll explain just in a minute).
If it doesn't work, then I have no idea right now (while I'm writing this text ). Read through the tutorial carefully and see if you forgot something.
This tutorial was tested with Borland C++ 3.1 and Borland C++ 4.02 so it should really work, if you started with a working standard wolf engine. Of course there could be problems with non standard engines i.e. when trying to add this feature to an already modified engine. In that case you'll have to find a way to fix it. Perhaps add this feature here to a working standard wolf engine and add your individual features to this engine step by step. Then you should be able to find the point where it stops working.
If it still won't work, wait one day and try again
If it just can't be helped, try to contact me. But FIRST try to help yourself !!!
You may have noticed, that we added a small amount of different directional 3D sprites:
- dir_south, dir_south_fw, dir_south_bw
- dir_east, dir_east_fw, dir_east_bw
- bl_dir_south, bl_dir_south_fw, bl_dir_south_bw
- bl_dir_east, bl_dir_east_fw, bl_dir_east_bw
First a sprite can have one of two different directions which the sprite runs along: south and east (or north and west, what ever you want). These directions correspond to the directions when looking at your map in an editor.
Then a sprite can be blocking so that you can't walk through it, though enemies can see you through them even if you can't. This is marked by a bl.
The last option you have is the position inside a map tile. The sprite can be in the middle or on one of two edges depending on whether fw (forward) or bw (backward) is used and of course which direction.
I hope you got an idea of those states, but you'll probably just have play around a bit with them
So here's a quick reference, what you have to do to add a new directional sprite:
- Add a new sprite constant to WL_DEF.H (for own sprite images only)
- Add a new object with the correct sprite constant and state to the statinfo array in WL_ACT1.C
- Add a new "case" line with the correct object number inside the ScanInfoPlane function in WL_GAME.C
(the object number of the first object after the "bo_clip2" clip is 72)
- Add your new sprite image to the VSWAP.WL6 using your Wolf3D editor (for own sprite images only)
- Add the new object with the object number from above to your Wolf3D editor
- Add the new object to your maps
Just remember when adding own sprite images that you'll have to leave the edges on the left and on the right empty, if you don't like your Wolf3D to crash *gg*
Also you should make sure, that your project doesn't contain WOLFHACK.C and WHACK_A.ASM, because the first file eats up 1622 bytes of your DATA segment and the second uses 8192 additional bytes of your main memory. But neither file is needed or used at all! Without these files you will have 1705 free bytes in your DATA segment instead of 83 bytes... Small difference, he?
With this amount of free memory you should be able to add enough objects, sounds or whatever you need to make your TC become perfect without any annoying "Abnormal programm termination" messages
So have a lot of fun with this feature, keep developing it and give us some credits if you use it ;D
Thanks for reading this and cu later
Ripper |
|
|
 |
JackaL
DieHard SS


Joined: 25 Jun 2004
Last Visit: 04 Apr 2011
Topics: 30
Posts: 335
Location: Rotorua, New Zealand

|
Posted: Fri Aug 19, 2005 1:58 am
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
I got this problem ages ago but forgot to post for help, now that I've got back into my TC I suppose I'll ask.
My code had textured flats and shading in it, (as well as heaps more but these were the major ones) I tried to add the directional sprites code and when I went to compile it all up I got error messages, I believe it was a conflict with the shading (SHADE_A.ASM) I think...
- Should I restart the code but instead add direction sprites THEN shading?
- Or should I retry the directional sprites tutorial in case I missed something?
Thanks |
|
|
 |
WLHack
DieHard Wolfer


Joined: 10 Jul 2005
Last Visit: 18 Jan 2018
Topics: 66
Posts: 1241
Location: Loppi - Finland

|
Posted: Wed Aug 31, 2005 6:54 am
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
I think I know why you got this problem. I suppose you deleted MapMask declaration
in the end of SimpleScaleShape function. |
|
|
 |
WLHack
DieHard Wolfer


Joined: 10 Jul 2005
Last Visit: 18 Jan 2018
Topics: 66
Posts: 1241
Location: Loppi - Finland

|
Posted: Fri Sep 09, 2005 11:41 am
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
Can anyone tell how to get this strange "bug".
When I come near the directional sprites, they don't rotate
anymore (what is good) but instead move left and right or backward
and forward, depending on which direction the sprite is facing.
I would be pleased if anyone could help. |
|
|
 |
lwmxynedtodth
DieHard Officer


Joined: 28 May 2006
Last Visit: 24 Aug 2017
Topics: 38
Posts: 570
Location: Neverland

|
Posted: Mon Oct 16, 2006 11:58 am
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
Hey,
I just got a question out of curiosity. I just applied this tutorial (already for the fourth time, but who cares).
Drawed a new sprite, an archway, and placed it on the chunk of the green barrel and the other one on the table chunk.
I compiled as usual, sure everything works fine. I tested my level with these new static objects. From the front it looked fine,
a nice archway combined with a ceiling tile to look real. I walked under it, to see it from the other side.
But huh, the sprite actually swapped sides. It was weird mirrored, I checked again and I was right.
After a lot of messing around with my code and chunks I figured that it works fine on other chunks, but not on the first
and the second. So I did put it on another and now I'm set. But how could it happen? Why did it mirrored itself, but works fine on another chunk? Really weird, isn't it.
- lwmxynedtodth
EDIT: it seems that what I said was wrong. It actually solved nothing, gonna mess with my code again. |
_________________ lwmxynedtodth (portfolio, blog and more)
Killer-suit: Masterminds
On a MMORPG trip.
|
|
 |
lwmxynedtodth
DieHard Officer


Joined: 28 May 2006
Last Visit: 24 Aug 2017
Topics: 38
Posts: 570
Location: Neverland

|
Posted: Mon Oct 16, 2006 11:51 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
Well, I don't know what is causing this weird bug now. I thought I'd solved it, but it was not.
This is as I said the fourth time I implemented this tutorial in a code, and this never occured.
So this is the problem: when I view from side one (say facing north), the sprite is drawn correctly.
When I'm facing south then, the sprite is actually mirrored. It occurs at all sprite states, and all sprite chunks.
I used build all, not only compile and make. Any help would be greatly appreciated.
- lwmxynedtodth |
_________________ lwmxynedtodth (portfolio, blog and more)
Killer-suit: Masterminds
On a MMORPG trip.
|
|
 |
the_fish
Bring 'em On

Joined: 18 Nov 2006
Last Visit: 07 Nov 2008
Topics: 12
Posts: 133
Location: England

|
Posted: Sat Dec 16, 2006 12:00 pm
Subject: Update for Wolf4GW
[ IP : Logged ]
|

  
|
|
@lwmxynedtodth: (man, that's hard to remember. What's it stand for/mean?) Don't know whether you've given up on that bug yet, from what I can gather from the code it should always occur as the sprite is always drawn from left to right regardless of which way you view it.
I guess no-one's pointed this out before because most directional sprites will be windows/fences etc, which are generally symmetric (that's certainly the case in my TC, so I wouldn't have noticed otherwise). I'd look at passing an extra argument to the Scale3DShaper function to then draw the sprite from the other direction (I'm sure it's possible, I'm just not sure exactly how...).
Another nasty one, took a while to adapt for Ripper's Wolf4GW. It took me ages to see the assembly at the end of Scale3DShape to calculate height1/height2 wasn't working properly.
Place the following functions in WL_DRAW.cpp as WL_SCALE no longer exists, and prototype them at the start accordingly. The rest of the tutorial should work the same.
::: CODE :::
void Scale3DShaper (int x1,int x2,int shapenum,unsigned height1,unsigned height2,
fixed ny1,fixed ny2,fixed nx1,fixed nx2)
{
t_compshape *shape;
unsigned scale1,scale2,starty,endy;
word *cmdptr;
word *line;
byte *vmem;
int dx=x2-x1,len,i,j,newstart,ycnt,pixheight,screndy,upperedge,scrstarty;
fixed height,dheight;
int xpos[65];
int slinex;
fixed dxx=(ny2-ny1)<<8,dzz=(nx2-nx1)<<8;
fixed dxa=0,dza=0;
byte mask,col;
#ifdef SHADE_COUNT
byte shade;
byte *curshades;
#endif
if(!dx) return;
height=(((fixed)height1)<<12)+2048;
dheight=(((fixed)height2-(fixed)height1)<<12)/(fixed)dx;
// Get length/address of pixeldata
shape =(t_compshape *)(Pages+((PMSpriteStart+shapenum)<<12));
scale1 = height1>>3; // low three bits are fractional
scale2 = height2>>3; // low three bits are fractional
if (!scale1 && !scale2 /*|| scale1>maxscale && scale2>maxscale*/)
return; // too close or far away
len=shape->rightpix-shape->leftpix+1;
if(!len) return;
ny1+=dxx>>9;
nx1+=dzz>>9;
dxa=-(dxx>>1),dza=-(dzz>>1);
dxx>>=6,dzz>>=6;
dxa+=shape->leftpix*dxx,dza+=shape->leftpix*dzz;
xpos[0]=(int)((ny1+(dxa>>8))*scale/(nx1+(dza>>8))+centerx);
for(i=1;i<=len;i++)
{
dxa+=dxx,dza+=dzz;
xpos[i]=(int)((ny1+(dxa>>8))*scale/(nx1+(dza>>8))+centerx);
if(xpos[i-1]>viewwidth) break;
}
len=i-1;
//*(((unsigned *)&line)+1)=(unsigned)shape; // seg of shape
cmdptr = (word *) &shape->dataofs[0];
//*(((unsigned *)&vmem)+1)=0xa000;
i=0;
if(x2>viewwidth) x2=viewwidth;
for(i=0;i<len;i++)
{
for(slinex=xpos[i];slinex<xpos[i+1] && slinex<x2;slinex++)
{
height+=dheight;
if(slinex<0) continue;
scale1=(unsigned)(height>>15);
if(wallheight[slinex]<(height>>12) && scale1 /*&& scale1<=maxscale*/)
{
#ifdef SHADE_COUNT
shade=(scale1<<2)/((maxscaleshl2>>8)+1+LSHADE_flag);
if(shade>32) shade=32;
else if(shade<1) shade=1;
shade=32-shade;
curshades=shadetable[shade];
#endif
pixheight=scale1*2;
upperedge=viewheight/2-scale1;
mask=1<<(slinex&3);
VGAMAPMASK(mask);
line=(word *)((byte *)shape + cmdptr[i]);
while(*line)
{
starty=(*(line+2))>>1;
endy=(*line)>>1;
newstart=(*(line+1));
j=starty;
ycnt=j*pixheight;
screndy=(ycnt>>6)+upperedge;
if(screndy<0) vmem=vbuf+(slinex>>2);
else vmem=vbuf+screndy*80+(slinex>>2);
for(;j<endy;j++)
{
scrstarty=screndy;
ycnt+=pixheight;
screndy=(ycnt>>6)+upperedge;
if(scrstarty!=screndy && screndy>0)
{
#ifdef SHADE_COUNT
col=curshades[((byte *)shape)[newstart+j]];
#else
col=((byte *)shape)[newstart+j];
#endif
if(scrstarty<0) scrstarty=0;
if(screndy>viewheight) screndy=viewheight,j=endy;
while(scrstarty<screndy)
{
*vmem=col;
vmem+=80;
scrstarty++;
}
}
}
line+=3;
}
}
}
}
}
void Scale3DShape(statobj_t *ob)
{
fixed nx1,nx2,ny1,ny2;
int viewx1,viewx2;
long height1, height2;
fixed diradd;
//
// the following values for "diradd" aren't optimized yet
// if you have problems with sprites being visible through wall edges
// where they shouldn't, you can try to adjust these values and
// the -1024 and +2048 in both "if" blocks
//
if(ob->flags & FL_DIRFORWARD) diradd=0x7ff0+0x8000;
else if(ob->flags & FL_DIRBACKWARD) diradd=-0x7ff0+0x8000;
else diradd=0x8000;
if(ob->flags & FL_DIREAST)
{
fixed gx1,gx2,gy,gxt1,gxt2,gyt;
//
// translate point to view centered coordinates
//
gx1 = (((long)ob->tilex) << TILESHIFT)+0x8000-playx-0x8000L-1024;
gx2 = gx1+0x10000L+2048;
gy = (((long)ob->tiley) << TILESHIFT)+diradd-playy;
//
// calculate newx
//
gxt1 = FixedMul(gx1,viewcos);
gxt2 = FixedMul(gx2,viewcos);
gyt = FixedMul(gy,viewsin);
nx1 = gxt1-gyt-0x2000;
nx2 = gxt2-gyt-0x2000;
//
// calculate newy
//
gxt1 = FixedMul(gx1,viewsin);
gxt2 = FixedMul(gx2,viewsin);
gyt = FixedMul(gy,viewcos);
ny1 = gyt+gxt1;
ny2 = gyt+gxt2;
}
else
{
fixed gy1,gy2,gx,gyt1,gyt2,gxt;
//
// translate point to view centered coordinates
//
gy1 = (((long)ob->tiley) << TILESHIFT)+0x8000-playy-0x8000L-1024;
gy2 = gy1+0x10000L+2048;
gx = (((long)ob->tilex) << TILESHIFT)+diradd-playx;
//
// calculate newx
//
gxt = FixedMul(gx,viewcos);
gyt1 = FixedMul(gy1,viewsin);
gyt2 = FixedMul(gy2,viewsin);
nx1 = gxt-gyt1-0x2000;
nx2 = gxt-gyt2-0x2000;
//
// calculate newy
//
gxt = FixedMul(gx,viewsin);
gyt1 = FixedMul(gy1,viewcos);
gyt2 = FixedMul(gy2,viewcos);
ny1 = gyt1+gxt;
ny2 = gyt2+gxt;
}
//
// calculate perspective ratio
//
if(nx1>=0 && nx1<=1792) nx1=1792;
if(nx1<0 && nx1>=-1792) nx1=-1792;
if(nx2>=0 && nx2<=1792) nx2=1792;
if(nx2<0 && nx2>=-1792) nx2=-1792;
viewx1=(int)(centerx+ny1*scale/nx1);
viewx2=(int)(centerx+ny2*scale/nx2);
//
// calculate height (heightnumerator/(nx>>8)) (heightnumerator=0x36800)
//
height1 = (short)(heightnumerator/(nx1>>8));
height2 = (short)(heightnumerator/(nx2>>8));
if(viewx2 < viewx1)
{
Scale3DShaper(viewx2,viewx1,ob->shapenum,(unsigned)height2,
(unsigned)height1,ny2,ny1,nx2,nx1);
}
else
{
Scale3DShaper(viewx1,viewx2,ob->shapenum,(unsigned)height1,
(unsigned)height2,ny1,ny2,nx1,nx2);
}
}
Hope this helps someone,
the_fish |
|
|
 |
Anonymous
Guest

Last Visit:
|
Posted: Sat Feb 03, 2007 12:55 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
*Sorry double posted* |
Last edited by Anonymous on Sat Feb 03, 2007 1:00 pm; edited 1 time in total
|
|
 |
Anonymous
Guest

Last Visit:
|
Posted: Sat Feb 03, 2007 12:59 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
I added this tutorial to my code but i had a problem. First the 3d sprites weren`t 3d and rotated like any other sprite. So i changed this piece of code
::: CODE :::
if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
{
visptr->transsprite=NULL;
visptr++;
}
to this
::: CODE :::
if (visptr < &vislist[MAXVISABLE-1]) // don't let it overflow
{
visptr++;
visptr->transsprite=NULL;
}
Now I have two question.
1) Was this Ripper`s mistake or did I miss something
2) Once i did this(i also tried commenting the visptr->transsprite=NULL line) the actors in the game disappear when they are in certain states(ie. guard disappears while chasing but appears when killed). How can i fix this? This problem wasn`t there before i added the tutorial`s code. |
|
|
 |
Black Man
Registered User


Joined: 19 May 2006
Last Visit: 09 Aug 2016
Topics: 8
Posts: 22

|
Posted: Fri Nov 23, 2007 11:55 pm
Subject: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
How can i use DarkOne's sprite bug fix, when is use Rippers Removing the scalers tutorial?
Please Help me with this.
Blacky |
|
|
 |
KyleRTCW
DieHard Officer

Joined: 30 Jul 2003
Last Visit: 05 Aug 2018
Topics: 45
Posts: 510
Location: Ohio

|
|
 |
Dean
Moderator

Joined: 10 Jan 2006
Last Visit: 12 Feb 2019
Topics: 54
Posts: 2215
Location: Australia

|
Posted: Fri Sep 26, 2008 2:35 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
I'm trying to add this but I'm sure it's causing problems with other coding I have also added in WL_SCALE.C. Does anyone know what other tutorials have coding that is added or adjusted in this section so I can look at those to replace any required info I may have removed when replacing the ScaleShape and SimpleScaleShape functions? Thanks |
_________________ ... Still alive
|
|
 |
Tricob
Moderator


Joined: 14 Mar 2005
Last Visit: 6:01 ago.
Topics: 165
Posts: 8330
Location: Neo-traditions, Inc.

|
Posted: Fri Sep 26, 2008 7:35 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
Well, there's a 3D Sprites tutorial on Ripper's website, but the website keeps timing out on my PC right now ...  |
|
|
 |
Dean
Moderator

Joined: 10 Jan 2006
Last Visit: 12 Feb 2019
Topics: 54
Posts: 2215
Location: Australia

|
Posted: Sat Sep 27, 2008 2:10 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
I've added that as well. What I was asking was whether theres other coding that may have placed some code into those sections as I have just replaced the whole lot witht he directional sprites code. I'm concerned that I've affected something else that I've already coded. |
_________________ ... Still alive
|
|
 |
Tricob
Moderator


Joined: 14 Mar 2005
Last Visit: 6:01 ago.
Topics: 165
Posts: 8330
Location: Neo-traditions, Inc.

|
Posted: Sat Sep 27, 2008 8:43 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
I'm not sure how the 3D Sprites code would affect other routines. What feature have you coded in that has had problems since you put in the 3D Sprites code? |
|
|
 |
Dean
Moderator

Joined: 10 Jan 2006
Last Visit: 12 Feb 2019
Topics: 54
Posts: 2215
Location: Australia

|
Posted: Sun Sep 28, 2008 11:43 pm
Subject: Re: [Code] Directional Sprites - Ripper
[ IP : Logged ]
|

  
|
|
It won't compile to be able to give me an exe to be able to test and see....
Anyway, like every other piece of coding I have tried recently I have just over ridden it with my back up files. There goes about 10 hours of coding and attempted fixes over the last week or so!
I give up I think for now, I might just put the code asaide and try again in another couple of months. |
_________________ ... Still alive
|
|
 |
Tricob
Moderator


Joined: 14 Mar 2005
Last Visit: 6:01 ago.
Topics: 165
Posts: 8330
Location: Neo-traditions, Inc.

|
|
 |
Dean
Moderator

Joined: 10 Jan 2006
Last Visit: 12 Feb 2019
Topics: 54
Posts: 2215
Location: Australia

|
|
 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum
|
|
You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
Copyright ©2003-2008 DieHard Wolfers
A Modified subBunker Theme by BrotherTank
Powered by phpBB © 2001, 2005 phpBB Group
|