Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Iskhodnyy_kod_Doom

.pdf
Скачиваний:
7
Добавлен:
13.02.2015
Размер:
1.01 Mб
Скачать

void 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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]