📄 am_map.c
字号:
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)) { 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; 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.//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.//booleanAM_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) 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); } if (outcode1 & outcode2) return false; // trivially outside } return true;}#undef DOOUTCODE//// Classic Bresenham w/ whatever optimizations needed for speed//voidAM_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; } 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.//voidAM_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); } // 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); } } } 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.//voidAM_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;}voidAM_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; if (scale) { l.b.x = FixedMul(scale, l.b.x); l.b.y = FixedMul(scale, l.b.y); } if (angle) AM_rotate(&l.b.x, &l.b.y, angle); l.b.x += x; l.b.y += y; AM_drawMline(&l, color); }}void AM_drawPlayers(void){ int i; player_t* p; static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS }; int their_color = -1; int color; if (!netgame) { if (cheating) AM_drawLineCharacter (cheat_player_arrow, NUMCHEATPLYRLINES, 0, plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); else AM_drawLineCharacter (player_arrow, NUMPLYRLINES, 0, plr->mo->angle, WHITE, plr->mo->x, plr->mo->y); return; } for (i=0;i<MAXPLAYERS;i++) { their_color++; p = &players[i]; if ( (deathmatch && !singledemo) && p != plr) continue; if (!playeringame[i]) continue; if (p->powers[pw_invisibility]) color = 246; // *close* to black else color = their_colors[their_color]; AM_drawLineCharacter (player_arrow, NUMPLYRLINES, 0, p->mo->angle, color, p->mo->x, p->mo->y); }}voidAM_drawThings( int colors, int colorrange){ int i; mobj_t* t; for (i=0;i<numsectors;i++) { t = sectors[i].thinglist; while (t) { AM_drawLineCharacter (thintriangle_guy, NUMTHINTRIANGLEGUYLINES, 16<<FRACBITS, t->angle, colors+lightlev, t->x, t->y); t = t->snext; } }}void AM_drawMarks(void){ int i, fx, fy, w, h; for (i=0;i<AM_NUMMARKPOINTS;i++) { if (markpoints[i].x != -1) { // w = SHORT(marknums[i]->width); // h = SHORT(marknums[i]->height); w = 5; // because something's wrong with the wad, i guess h = 6; // because something's wrong with the wad, i guess fx = CXMTOF(markpoints[i].x); fy = CYMTOF(markpoints[i].y); if (fx >= f_x && fx <= f_w - w && fy >= f_y && fy <= f_h - h) V_DrawPatch(fx, fy, FB, marknums[i]); } }}void AM_drawCrosshair(int color){ fb[(f_w*(f_h+1))/2] = color; // single point for now}void AM_Drawer (void){ if (!automapactive) return; AM_clearFB(BACKGROUND); if (grid) AM_drawGrid(GRIDCOLORS); AM_drawWalls(); AM_drawPlayers(); if (cheating==2) AM_drawThings(THINGCOLORS, THINGRANGE); AM_drawCrosshair(XHAIRCOLORS); AM_drawMarks(); V_MarkRect(f_x, f_y, f_w, f_h);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -