Iskhodnyy_kod_Doom
.pdfvoid AM_Start (void)
{
static int lastlevel = -1, lastepisode = -1;
if (!stopped) AM_Stop(); stopped = false;
if (lastlevel != gamemap || lastepisode != gameepisode)
{
AM_LevelInit(); lastlevel = gamemap;
lastepisode = gameepisode;
}
AM_initVariables();
AM_loadPics();
}
//
// set the window scale to the maximum size
//
void AM_minOutWindowScale(void)
{
scale_mtof = min_scale_mtof;
scale_ftom = FixedDiv(FRACUNIT, scale_mtof); AM_activateNewScale();
}
//
// set the window scale to the minimum size
//
void AM_maxOutWindowScale(void)
{
scale_mtof = max_scale_mtof;
scale_ftom = FixedDiv(FRACUNIT, scale_mtof); AM_activateNewScale();
}
//
// Handle events (user inputs) in automap mode
//
boolean AM_Responder
( event_t* |
ev ) |
{ |
|
int rc;
static int cheatstate=0; static int bigstate=0; static char buffer[20];
rc = false;
if (!automapactive)
{
if (ev->type == ev_keydown && ev->data1 == AM_STARTKEY)
{
AM_Start (); viewactive = false; rc = true;
}
}
else if (ev->type == ev_keydown)
{
31
rc = true; switch(ev->data1)
{
case AM_PANRIGHTKEY: // pan right
if (!followplayer) m_paninc.x = FTOM(F_PANINC); else rc = false;
break;
case AM_PANLEFTKEY: // pan left
if (!followplayer) m_paninc.x = -FTOM(F_PANINC); else rc = false;
break;
case AM_PANUPKEY: // pan up
if (!followplayer) m_paninc.y = FTOM(F_PANINC); else rc = false;
break;
case AM_PANDOWNKEY: // pan down
if (!followplayer) m_paninc.y = -FTOM(F_PANINC); else rc = false;
break;
case AM_ZOOMOUTKEY: // zoom out mtof_zoommul = M_ZOOMOUT; ftom_zoommul = M_ZOOMIN; break;
case AM_ZOOMINKEY: // zoom in mtof_zoommul = M_ZOOMIN; ftom_zoommul = M_ZOOMOUT; break;
case AM_ENDKEY: bigstate = 0; viewactive = true; AM_Stop ();
break;
case AM_GOBIGKEY: bigstate = !bigstate; if (bigstate)
{
AM_saveScaleAndLoc();
AM_minOutWindowScale();
}
else AM_restoreScaleAndLoc(); break;
case AM_FOLLOWKEY: followplayer = !followplayer; f_oldloc.x = MAXINT;
plr->message = followplayer ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF; break;
case AM_GRIDKEY: grid = !grid;
plr->message = grid ? AMSTR_GRIDON : AMSTR_GRIDOFF; break;
case AM_MARKKEY:
sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, markpointnum); plr->message = buffer;
AM_addMark(); break;
case AM_CLEARMARKKEY: AM_clearMarks();
plr->message = AMSTR_MARKSCLEARED; break;
default:
cheatstate=0; rc = false;
}
if (!deathmatch && cht_CheckCheat(&cheat_amap, ev->data1))
{
32
rc = false;
cheating = (cheating+1) % 3;
}
}
else if (ev->type == ev_keyup)
{
rc = false;
switch |
(ev->data1) |
{ |
|
case |
AM_PANRIGHTKEY: |
if |
(!followplayer) m_paninc.x = 0; |
break; |
|
case |
AM_PANLEFTKEY: |
if |
(!followplayer) m_paninc.x = 0; |
break; |
|
case |
AM_PANUPKEY: |
if |
(!followplayer) m_paninc.y = 0; |
break; |
|
case |
AM_PANDOWNKEY: |
if |
(!followplayer) m_paninc.y = 0; |
break; |
|
case |
AM_ZOOMOUTKEY: |
case |
AM_ZOOMINKEY: |
mtof_zoommul = FRACUNIT; ftom_zoommul = FRACUNIT; break;
}
}
return rc;
}
//
// Zooming
//
void AM_changeWindowScale(void)
{
// Change the scaling multipliers
scale_mtof = FixedMul(scale_mtof, mtof_zoommul); scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
if (scale_mtof < min_scale_mtof) AM_minOutWindowScale();
else if (scale_mtof > max_scale_mtof) AM_maxOutWindowScale();
else
AM_activateNewScale();
}
//
//
//
void AM_doFollowPlayer(void)
{
if (f_oldloc.x != plr->mo->x || f_oldloc.y != plr->mo->y)
{
m_x = FTOM(MTOF(plr->mo->x)) - m_w/2; m_y = FTOM(MTOF(plr->mo->y)) - m_h/2; m_x2 = m_x + m_w;
33
m_y2 = m_y + m_h; f_oldloc.x = plr->mo->x; f_oldloc.y = plr->mo->y;
//m_x = FTOM(MTOF(plr->mo->x - m_w/2));
//m_y = FTOM(MTOF(plr->mo->y - m_h/2));
//m_x = plr->mo->x - m_w/2;
//m_y = plr->mo->y - m_h/2;
}
}
//
//
//
void AM_updateLightLev(void)
{
static nexttic = 0;
//static int litelevels[] = { 0, 3, 5, 6, 6, 7, 7, 7 }; static int litelevels[] = { 0, 4, 7, 10, 12, 14, 15, 15 }; static int litelevelscnt = 0;
// Change light level if (amclock>nexttic)
{
lightlev = litelevels[litelevelscnt++];
if (litelevelscnt == sizeof(litelevels)/sizeof(int)) litelevelscnt = 0; nexttic = amclock + 6 - (amclock % 6);
}
}
//
// Updates on Game Tick
//
void AM_Ticker (void)
{
if (!automapactive) return;
amclock++;
if (followplayer) AM_doFollowPlayer();
//Change the zoom if necessary if (ftom_zoommul != FRACUNIT)
AM_changeWindowScale();
//Change x,y location
if (m_paninc.x || m_paninc.y) AM_changeWindowLoc();
//Update light level
//AM_updateLightLev();
}
//
// Clear automap frame buffer.
//
34
void AM_clearFB(int color)
{
memset(fb, color, f_w*f_h);
}
//
//Automap clipping of lines.
//Based on Cohen-Sutherland clipping algorithm but with a slightly
//faster reject and precalculated slopes. If the speed is needed,
//use a hash algorithm to handle the common cases.
// |
|
boolean |
|
AM_clipMline |
|
( mline_t* |
ml, |
fline_t* |
fl ) |
{ |
|
enum |
|
{ |
|
LEFT |
=1, |
RIGHT |
=2, |
BOTTOM |
=4, |
TOP |
=8 |
}; |
|
register |
outcode1 = 0; |
register |
outcode2 = 0; |
register |
outside; |
fpoint_t |
tmp; |
int |
dx; |
int |
dy; |
#define DOOUTCODE(oc, mx, |
my) \ |
|
|
(oc) = 0; \ |
|
|
|
if ((my) < 0) |
(oc) |= |
TOP; \ |
|
else if ((my) |
>= f_h) |
(oc) |= |
BOTTOM; \ |
if ((mx) < 0) |
(oc) |= |
LEFT; \ |
|
else if ((mx) |
>= f_w) |
(oc) |= |
RIGHT; |
// do trivial |
rejects |
and outcodes |
|
if (ml->a.y > |
m_y2) |
|
|
outcode1 = TOP; else if (ml->a.y < m_y)
outcode1 = BOTTOM;
if (ml->b.y > m_y2) outcode2 = TOP;
else if (ml->b.y < m_y) outcode2 = BOTTOM;
if (outcode1 & outcode2)
return false; // trivially outside
if (ml->a.x < m_x) outcode1 |= LEFT;
else if (ml->a.x > m_x2) outcode1 |= RIGHT;
if (ml->b.x < m_x) outcode2 |= LEFT;
else if (ml->b.x > m_x2)
35
outcode2 |= RIGHT;
if (outcode1 & outcode2)
return false; // trivially outside
// transform to frame-buffer coordinates. fl->a.x = CXMTOF(ml->a.x);
fl->a.y = CYMTOF(ml->a.y); fl->b.x = CXMTOF(ml->b.x); fl->b.y = CYMTOF(ml->b.y);
DOOUTCODE(outcode1, fl->a.x, fl->a.y);
DOOUTCODE(outcode2, fl->b.x, fl->b.y);
if (outcode1 & outcode2) return false;
while (outcode1 | outcode2)
{
//may be partially inside box
//find an outside point
if (outcode1)
outside = outcode1;
else
outside = outcode2;
// clip to each side if (outside & TOP)
{
dy = fl->a.y - fl->b.y; dx = fl->b.x - fl->a.x;
tmp.x = fl->a.x + (dx*(fl->a.y))/dy; tmp.y = 0;
}
else if (outside & BOTTOM)
{
dy = fl->a.y - fl->b.y; dx = fl->b.x - fl->a.x;
tmp.x = fl->a.x + (dx*(fl->a.y-f_h))/dy; tmp.y = f_h-1;
}
else if (outside & RIGHT)
{
dy = fl->b.y - fl->a.y; dx = fl->b.x - fl->a.x;
tmp.y = fl->a.y + (dy*(f_w-1 - fl->a.x))/dx; tmp.x = f_w-1;
}
else if (outside & LEFT)
{
dy = fl->b.y - fl->a.y; dx = fl->b.x - fl->a.x;
tmp.y = fl->a.y + (dy*(-fl->a.x))/dx; tmp.x = 0;
}
if (outside == outcode1)
{
fl->a = tmp;
DOOUTCODE(outcode1, fl->a.x, fl->a.y);
}
else
{
fl->b = tmp;
DOOUTCODE(outcode2, fl->b.x, fl->b.y);
36
}
if (outcode1 & outcode2)
return false; // trivially outside
}
return true;
}
#undef DOOUTCODE
//
// Classic Bresenham w/ whatever optimizations needed for speed
//
void |
|
AM_drawFline |
|
( fline_t* |
fl, |
int |
color ) |
{ |
|
register int x; register int y; register int dx; register int dy; register int sx; register int sy; register int ax; register int ay; register int d;
static fuck = 0;
// For debugging only
if ( fl->a.x < 0 || fl->a.x >= f_w
||fl->a.y < 0 || fl->a.y >= f_h
||fl->b.x < 0 || fl->b.x >= f_w
||fl->b.y < 0 || fl->b.y >= f_h)
{
fprintf(stderr, "fuck %d \r", fuck++); return;
}
#define PUTDOT(xx,yy,cc) fb[(yy)*f_w+(xx)]=(cc)
dx = fl->b.x - fl->a.x;
ax = 2 * (dx<0 ? -dx : dx); sx = dx<0 ? -1 : 1;
dy = fl->b.y - fl->a.y;
ay = 2 * (dy<0 ? -dy : dy); sy = dy<0 ? -1 : 1;
x = fl->a.x; y = fl->a.y;
if (ax > ay)
{
d = ay - ax/2; while (1)
{
PUTDOT(x,y,color);
if (x == fl->b.x) return; if (d>=0)
{
y += sy; d -= ax;
37
}
x += sx; d += ay;
}
}
else
{
d = ax - ay/2; while (1)
{
PUTDOT(x, y, color);
if (y == fl->b.y) return; if (d >= 0)
{
x += sx; d -= ay;
}
y += sy; d += ax;
}
}
}
//
// Clip lines, draw visible part sof lines.
// |
|
void |
|
AM_drawMline |
|
( mline_t* |
ml, |
int |
color ) |
{ |
|
static fline_t fl;
if (AM_clipMline(ml, &fl))
AM_drawFline(&fl, color); // draws it on frame buffer using fb coords
}
//
// Draws flat (floor/ceiling tile) aligned grid lines.
//
void AM_drawGrid(int color)
{
fixed_t x, y; fixed_t start, end; mline_t ml;
//Figure out start of vertical gridlines start = m_x;
if ((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS)) start += (MAPBLOCKUNITS<<FRACBITS)
-((start-bmaporgx)%(MAPBLOCKUNITS<<FRACBITS)); end = m_x + m_w;
//draw vertical gridlines
ml.a.y = m_y; ml.b.y = m_y+m_h;
for (x=start; x<end; x+=(MAPBLOCKUNITS<<FRACBITS))
{
ml.a.x = x; ml.b.x = x;
AM_drawMline(&ml, color);
}
38
//Figure out start of horizontal gridlines start = m_y;
if ((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS)) start += (MAPBLOCKUNITS<<FRACBITS)
-((start-bmaporgy)%(MAPBLOCKUNITS<<FRACBITS)); end = m_y + m_h;
//draw horizontal gridlines
ml.a.x = m_x; ml.b.x = m_x + m_w;
for (y=start; y<end; y+=(MAPBLOCKUNITS<<FRACBITS))
{
ml.a.y = y; ml.b.y = y;
AM_drawMline(&ml, color);
}
}
//
//Determines visible lines, draws them.
//This is LineDef based, not LineSeg based.
void AM_drawWalls(void)
{
int i;
static mline_t l;
for (i=0;i<numlines;i++)
{
l.a.x = lines[i].v1->x; l.a.y = lines[i].v1->y; l.b.x = lines[i].v2->x; l.b.y = lines[i].v2->y;
if (cheating || (lines[i].flags & ML_MAPPED))
{
if ((lines[i].flags & LINE_NEVERSEE) && !cheating) continue;
if (!lines[i].backsector)
{
AM_drawMline(&l, WALLCOLORS+lightlev);
}
else
{
if (lines[i].special == 39) { // teleporters
AM_drawMline(&l, WALLCOLORS+WALLRANGE/2);
}
else if (lines[i].flags & ML_SECRET) // secret door
{
if (cheating) AM_drawMline(&l, SECRETWALLCOLORS + lightlev); else AM_drawMline(&l, WALLCOLORS+lightlev);
}
else if (lines[i].backsector->floorheight
!= lines[i].frontsector->floorheight) {
AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
}
else if (lines[i].backsector->ceilingheight
!= lines[i].frontsector->ceilingheight) { AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
}
else if (cheating) {
AM_drawMline(&l, TSWALLCOLORS+lightlev);
}
39
}
}
else if (plr->powers[pw_allmap])
{
if (!(lines[i].flags & LINE_NEVERSEE)) AM_drawMline(&l, GRAYS+3);
}
}
}
//
//Rotation in 2D.
//Used to rotate player arrow line character.
void AM_rotate
( fixed_t* x, fixed_t* y,
angle_t |
a ) |
{
fixed_t tmpx;
tmpx = FixedMul(*x,finecosine[a>>ANGLETOFINESHIFT]) - FixedMul(*y,finesine[a>>ANGLETOFINESHIFT]);
*y = FixedMul(*x,finesine[a>>ANGLETOFINESHIFT])
+ FixedMul(*y,finecosine[a>>ANGLETOFINESHIFT]);
*x = tmpx;
}
void AM_drawLineCharacter
( mline_t* |
lineguy, |
int |
lineguylines, |
fixed_t |
scale, |
angle_t |
angle, |
int |
color, |
fixed_t |
x, |
fixed_t |
y ) |
{ |
|
int |
i; |
mline_t |
l; |
for (i=0;i<lineguylines;i++)
{
l.a.x = lineguy[i].a.x; l.a.y = lineguy[i].a.y;
if (scale)
{
l.a.x = FixedMul(scale, l.a.x); l.a.y = FixedMul(scale, l.a.y);
}
if (angle)
AM_rotate(&l.a.x, &l.a.y, angle);
l.a.x += x; l.a.y += y;
l.b.x = lineguy[i].b.x; l.b.y = lineguy[i].b.y;
40