⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_maputl.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 2 页
字号:
    thing->subsector = ss;    if ( ! (thing->flags & MF_NOSECTOR) )    {        // invisible things don't go into the sector links        sec = ss->sector;#ifdef PARANOIA        if ( thing->sprev != NULL || thing->snext != NULL )            I_Error("linking a think(%d) that is allready linked",thing->type);#endif        thing->sprev = NULL;        thing->snext = sec->thinglist;        if (sec->thinglist)            sec->thinglist->sprev = thing;        sec->thinglist = thing;        //SoM: 4/6/2000        //        // If sector_list isn't NULL, it has a collection of sector        // nodes that were just removed from this Thing.        // Collect the sectors the object will live in by looking at        // the existing sector_list and adding new nodes and deleting        // obsolete ones.        // When a node is deleted, its sector links (the links starting        // at sector_t->touching_thinglist) are broken. When a node is        // added, new sector links are created.        P_CreateSecNodeList(thing,thing->x,thing->y);        thing->touching_sectorlist = sector_list; // Attach to Thing's mobj_t        sector_list = NULL; // clear for next time    }    // link into blockmap    if ( ! (thing->flags & MF_NOBLOCKMAP) )    {        // inert things don't need to be in blockmap        blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;        blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;        if (blockx>=0            && blockx < bmapwidth            && blocky>=0            && blocky < bmapheight)        {            link = &blocklinks[blocky*bmapwidth+blockx];            thing->bprev = NULL;            thing->bnext = *link;            if (*link)                (*link)->bprev = thing;            *link = thing;        }        else        {            // thing is off the map            thing->bnext = thing->bprev = NULL;        }    }}//// BLOCK MAP ITERATORS// For each line/thing in the given mapblock,// call the passed PIT_* function.// If the function returns false,// exit with false without checking anything else.////// P_BlockLinesIterator// The validcount flags are used to avoid checking lines// that are marked in multiple mapblocks,// so increment validcount before the first call// to P_BlockLinesIterator, then make one or more calls// to it.//boolean P_BlockLinesIterator (int       x,                              int       y,                              boolean   (*func)(line_t*) ){    int                 offset;    short*              list;    line_t*             ld;    if (x<0        || y<0        || x>=bmapwidth        || y>=bmapheight)    {        return true;    }    offset = y*bmapwidth+x;    offset = *(blockmap+offset);    for ( list = blockmaplump+offset ; *list != -1 ; list++)    {        ld = &lines[*list];        if (ld->validcount == validcount)            continue;   // line has already been checked        ld->validcount = validcount;        if ( !func(ld) )            return false;    }    return true;        // everything was checked}//// P_BlockThingsIterator//boolean P_BlockThingsIterator ( int                   x,                                int                   y,                                boolean(*func)(mobj_t*) ){    mobj_t*             mobj;    if ( x<0         || y<0         || x>=bmapwidth         || y>=bmapheight)    {        return true;    }    //added:15-02-98: check interaction (ligne de tir, ...)    //                avec les objets dans le blocmap    for (mobj = blocklinks[y*bmapwidth+x] ;         mobj ;         mobj = mobj->bnext)    {        if (!func( mobj ) )            return false;    }    return true;}//// INTERCEPT ROUTINES////SoM: 4/6/2000: Limit removalintercept_t*    intercepts = NULL;intercept_t*    intercept_p = NULL;divline_t       trace;boolean         earlyout;int             ptflags;//SoM: 4/6/2000: Remove limit on intercepts.void P_CheckIntercepts(){static int max_intercepts = 0;  int count = intercept_p - intercepts;  if(max_intercepts <= count)  {    if(!max_intercepts)      max_intercepts = 128;    else      max_intercepts = max_intercepts * 2;    intercepts = realloc(intercepts, sizeof(intercept_t) * max_intercepts);    intercept_p = intercepts + count;  }}//// PIT_AddLineIntercepts.// Looks for lines in the given block// that intercept the given trace// to add to the intercepts list.//// A line is crossed if its endpoints// are on opposite sides of the trace.// Returns true if earlyout and a solid line hit.//booleanPIT_AddLineIntercepts (line_t* ld){    int                 s1;    int                 s2;    fixed_t             frac;    divline_t           dl;    // avoid precision problems with two routines    if ( trace.dx > FRACUNIT*16         || trace.dy > FRACUNIT*16         || trace.dx < -FRACUNIT*16         || trace.dy < -FRACUNIT*16)    {        s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);        s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);    }    else    {        s1 = P_PointOnLineSide (trace.x, trace.y, ld);        s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);    }    if (s1 == s2)        return true;    // line isn't crossed    // hit the line    P_MakeDivline (ld, &dl);    frac = P_InterceptVector (&trace, &dl);    if (frac < 0)        return true;    // behind source    // try to early out the check    if (earlyout        && frac < FRACUNIT        && !ld->backsector)    {        return false;   // stop checking    }    //SoM: 4/6/2000: Limit removal    P_CheckIntercepts();    intercept_p->frac = frac;    intercept_p->isaline = true;    intercept_p->d.line = ld;    intercept_p++;    return true;        // continue}//// PIT_AddThingIntercepts//boolean PIT_AddThingIntercepts (mobj_t* thing){    fixed_t             x1;    fixed_t             y1;    fixed_t             x2;    fixed_t             y2;    int                 s1;    int                 s2;    boolean             tracepositive;    divline_t           dl;    fixed_t             frac;    tracepositive = (trace.dx ^ trace.dy)>0;    // check a corner to corner crossection for hit    if (tracepositive)    {        x1 = thing->x - thing->radius;        y1 = thing->y + thing->radius;        x2 = thing->x + thing->radius;        y2 = thing->y - thing->radius;    }    else    {        x1 = thing->x - thing->radius;        y1 = thing->y - thing->radius;        x2 = thing->x + thing->radius;        y2 = thing->y + thing->radius;    }    s1 = P_PointOnDivlineSide (x1, y1, &trace);    s2 = P_PointOnDivlineSide (x2, y2, &trace);    if (s1 == s2)        return true;            // line isn't crossed    dl.x = x1;    dl.y = y1;    dl.dx = x2-x1;    dl.dy = y2-y1;    frac = P_InterceptVector (&trace, &dl);    if (frac < 0)        return true;            // behind source    P_CheckIntercepts();    intercept_p->frac = frac;    intercept_p->isaline = false;    intercept_p->d.thing = thing;    intercept_p++;    return true;                // keep going}//// P_TraverseIntercepts// Returns true if the traverser function returns true// for all lines.//boolean P_TraverseIntercepts ( traverser_t   func,                               fixed_t       maxfrac ){    int                 count;    fixed_t             dist;    intercept_t*        scan;    intercept_t*        in;    count = intercept_p - intercepts;    in = 0;                     // shut up compiler warning    while (count--)    {        dist = MAXINT;        for (scan = intercepts ; scan<intercept_p ; scan++)        {            if (scan->frac < dist)            {                dist = scan->frac;                in = scan;            }        }        if (dist > maxfrac)            return true;        // checked everything in range#if 0  // UNUSED    {        // don't check these yet, there may be others inserted        in = scan = intercepts;        for ( scan = intercepts ; scan<intercept_p ; scan++)            if (scan->frac > maxfrac)                *in++ = *scan;        intercept_p = in;        return false;    }#endif        // appelle la fonction en commencant par l' intercept_t le plus        // proche        if ( !func (in) )            return false;       // don't bother going farther        in->frac = MAXINT;    }    return true;                // everything was traversed}//// P_PathTraverse// Traces a line from x1,y1 to x2,y2,// calling the traverser function for each.// Returns true if the traverser function returns true// for all lines.//boolean P_PathTraverse ( fixed_t       x1,                         fixed_t       y1,                         fixed_t       x2,                         fixed_t       y2,                         int           flags,                         traverser_t   trav){    fixed_t     xt1;    fixed_t     yt1;    fixed_t     xt2;    fixed_t     yt2;    fixed_t     xstep;    fixed_t     ystep;    fixed_t     partial;    fixed_t     xintercept;    fixed_t     yintercept;    int         mapx;    int         mapy;    int         mapxstep;    int         mapystep;    int         count;    earlyout = flags & PT_EARLYOUT;    validcount++;    intercept_p = intercepts;    if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)        x1 += FRACUNIT; // don't side exactly on a line    if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)        y1 += FRACUNIT; // don't side exactly on a line    trace.x = x1;    trace.y = y1;    trace.dx = x2 - x1;    trace.dy = y2 - y1;    x1 -= bmaporgx;    y1 -= bmaporgy;    xt1 = x1>>MAPBLOCKSHIFT;    yt1 = y1>>MAPBLOCKSHIFT;    x2 -= bmaporgx;    y2 -= bmaporgy;    xt2 = x2>>MAPBLOCKSHIFT;    yt2 = y2>>MAPBLOCKSHIFT;    if (xt2 > xt1)    {        mapxstep = 1;        partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));        ystep = FixedDiv (y2-y1,abs(x2-x1));    }    else if (xt2 < xt1)    {        mapxstep = -1;        partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);        ystep = FixedDiv (y2-y1,abs(x2-x1));    }    else    {        mapxstep = 0;        partial = FRACUNIT;        ystep = 256*FRACUNIT;    }    yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);    if (yt2 > yt1)    {        mapystep = 1;        partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));        xstep = FixedDiv (x2-x1,abs(y2-y1));    }    else if (yt2 < yt1)    {        mapystep = -1;        partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);        xstep = FixedDiv (x2-x1,abs(y2-y1));    }    else    {        mapystep = 0;        partial = FRACUNIT;        xstep = 256*FRACUNIT;    }    xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);    // Step through map blocks.    // Count is present to prevent a round off error    // from skipping the break.    mapx = xt1;    mapy = yt1;    for (count = 0 ; count < 64 ; count++)    {        if (flags & PT_ADDLINES)        {            if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts))                return false;   // early out        }        if (flags & PT_ADDTHINGS)        {            if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts))                return false;   // early out        }        if (mapx == xt2            && mapy == yt2)        {            break;        }        if ( (yintercept >> FRACBITS) == mapy)        {            yintercept += ystep;            mapx += mapxstep;        }        else if ( (xintercept >> FRACBITS) == mapx)        {            xintercept += xstep;            mapy += mapystep;        }    }    // go through the sorted list    return P_TraverseIntercepts ( trav, FRACUNIT );}// =========================================================================//                                                        BLOCKMAP ITERATORS// =========================================================================// blockmap iterator for all sorts of use// your routine must return FALSE to exit the loop earlier// returns FALSE if the loop exited early after a false return// value from your user function//abandoned, maybe I'll need it someday..  /*boolean P_RadiusLinesCheck (  fixed_t    radius,                              fixed_t    x,                              fixed_t    y,                              boolean   (*func)(line_t*)){    int   xl, xh, yl, yh;    int   bx, by;    tmbbox[BOXTOP] = y + radius;    tmbbox[BOXBOTTOM] = y - radius;    tmbbox[BOXRIGHT] = x + radius;    tmbbox[BOXLEFT] = x - radius;        // check lines    xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;    xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;    yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;    yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;    for (bx=xl ; bx<=xh ; bx++)        for (by=yl ; by<=yh ; by++)            if (!P_BlockLinesIterator (bx,by,func))                return false;    return true;}*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -