X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_grid.pas;h=2dfb0ce43d4ff6cb49dece8b05fe3737ca7221b5;hb=987c4a835a103345b59937e8e1be8524a6228712;hp=99eb0ef6328eded53312d6727422e333b4baceb1;hpb=0cf1438ff1766dc311fbebc45f6171d64f757cd4;p=d2df-sdl.git diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index 99eb0ef..2dfb0ce 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -49,6 +48,9 @@ type x, y: Integer; end; + CellCoordIter = specialize PoolIter; + + type TBodyProxyId = Integer; @@ -57,6 +59,8 @@ type type PITP = ^ITP; type TCellQueryCB = procedure (x, y: Integer) is nested; // top-left cell corner coords + type Iter = specialize PoolIter; + const TagDisabled = $40000000; const TagFullMask = $3fffffff; @@ -194,11 +198,11 @@ type // return number of ITP thingys put into frame pool // if `firstHit` is `true`, return on first hit (obviously) - function forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; + function forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; // return number of ITP thingys put into frame pool // if `firstHit` is `true`, return on first hit (obviously) - function forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; + function forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; function atCellInPoint (x, y: Integer): TAtPointEnumerator; @@ -214,7 +218,7 @@ type // trace line along the grid, put all objects from passed cells into frame pool, in no particular order // return number of ITP thingys put into frame pool - function forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Integer; + function forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Iter; // trace box with the given velocity; return object hit (if any) // `cb` is used unconvetionally here: if it returns `false`, tracer will ignore the object @@ -222,8 +226,8 @@ type function traceBox (out ex, ey: Integer; const ax0, ay0, aw, ah: Integer; const dx, dy: Integer; tagmask: Integer=-1): ITP; // debug - function forEachBodyCell (body: TBodyProxyId): Integer; // this puts `TGridCellCoord` into frame pool for each cell - function forEachInCell (x, y: Integer): Integer; // this puts `ITP` into frame pool + function forEachBodyCell (body: TBodyProxyId): CellCoordIter; // this puts `TGridCellCoord` into frame pool for each cell + function forEachInCell (x, y: Integer): Iter; // this puts `ITP` into frame pool procedure dumpStats (); public @@ -693,14 +697,14 @@ begin end; -function TBodyGridBase.forEachBodyCell (body: TBodyProxyId): Integer; +function TBodyGridBase.forEachBodyCell (body: TBodyProxyId): CellCoordIter; var g, f, ccidx: Integer; cc: PGridCell; presobj: PGridCellCoord; begin - result := 0; - if (body < 0) or (body > High(mProxies)) then exit; + result := CellCoordIter.Create(framePool); + if (body < 0) or (body > High(mProxies)) then begin result.finishIt(); exit; end; for g := 0 to High(mGrid) do begin ccidx := mGrid[g]; @@ -715,7 +719,6 @@ begin presobj := PGridCellCoord(framePool.alloc(sizeof(TGridCellCoord))); presobj^.x := (g mod mWidth)*mTileSize+mMinX; presobj^.y := (g div mWidth)*mTileSize+mMinY; - Inc(result); //cb((g mod mWidth)*mTileSize+mMinX, (g div mWidth)*mTileSize+mMinY); end; end; @@ -723,19 +726,20 @@ begin ccidx := cc.next; end; end; + result.finishIt(); end; -function TBodyGridBase.forEachInCell (x, y: Integer): Integer; +function TBodyGridBase.forEachInCell (x, y: Integer): Iter; var f, ccidx: Integer; cc: PGridCell; presobj: PITP; begin - result := 0; + result := Iter.Create(framePool); Dec(x, mMinX); Dec(y, mMinY); - if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y > mHeight*mTileSize) then exit; + if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y > mHeight*mTileSize) then begin result.finishIt(); exit; end; ccidx := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)]; while (ccidx <> -1) do begin @@ -747,11 +751,11 @@ begin presobj := PITP(framePool.alloc(sizeof(ITP))); //presobj^ := mProxies[cc.bodies[f]].mObj; Move(mProxies[cc.bodies[f]].mObj, presobj^, sizeof(ITP)); - Inc(result); end; // next cell ccidx := cc.next; end; + result.finishIt(); end; @@ -1331,7 +1335,7 @@ end; // ////////////////////////////////////////////////////////////////////////// // // no callback: return `true` on the first hit -function TBodyGridBase.forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; +function TBodyGridBase.forEachAtPoint (x, y: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; var f: Integer; idx, curci: Integer; @@ -1341,9 +1345,9 @@ var ptag: Integer; presobj: PITP; begin - result := 0; + result := Iter.Create(framePool); tagmask := tagmask and TagFullMask; - if (tagmask = 0) then exit; + if (tagmask = 0) then begin result.finishIt(); exit; end; {$IF DEFINED(D2F_DEBUG_XXQ)} if (assigned(cb)) then e_WriteLog(Format('0: grid pointquery: (%d,%d)', [x, y]), MSG_NOTIFY); @@ -1352,7 +1356,7 @@ begin // make coords (0,0)-based Dec(x, mMinX); Dec(y, mMinY); - if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then exit; + if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then begin result.finishIt(); exit; end; curci := mGrid[(y div mTileSize)*mWidth+(x div mTileSize)]; @@ -1400,19 +1404,19 @@ begin begin presobj := PITP(framePool.alloc(sizeof(ITP))); Move(px.mObj, presobj^, sizeof(ITP)); - Inc(result); - if (firstHit) then exit; + if (firstHit) then begin result.finishIt(); exit; end; end; end; curci := cc.next; end; + result.finishIt(); end; // ////////////////////////////////////////////////////////////////////////// // // no callback: return `true` on the first hit // return number of ITP thingys put into frame pool -function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Integer; +function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; tagmask: Integer=-1; allowDisabled: Boolean=false; firstHit: Boolean=false): Iter; var idx: Integer; gx, gy: Integer; @@ -1427,17 +1431,17 @@ var ptag: Integer; presobj: PITP; begin - result := 0; - if (w < 1) or (h < 1) then exit; - if (w = 1) and (h = 1) then begin result := forEachAtPoint(x, y, tagmask, allowDisabled, firstHit); exit; end; + result := Iter.Create(framePool); + if (w < 1) or (h < 1) then begin result.finishIt(); exit; end; + tagmask := tagmask and TagFullMask; - if (tagmask = 0) then exit; + if (tagmask = 0) then begin result.finishIt(); exit; end; x0 := x; y0 := y; @@ -1449,8 +1453,8 @@ begin gw := mWidth; gh := mHeight; - if (x+w <= 0) or (y+h <= 0) then exit; - if (x >= gw*mTileSize) or (y >= gh*mTileSize) then exit; + if (x+w <= 0) or (y+h <= 0) then begin result.finishIt(); exit; end; + if (x >= gw*mTileSize) or (y >= gh*mTileSize) then begin result.finishIt(); exit; end; sx := x div mTileSize; sy := y div mTileSize; @@ -1462,7 +1466,7 @@ begin if (sy < 0) then sy := 0 else if (sy >= gh) then sy := gh-1; if (ex < 0) then ex := 0 else if (ex >= gw) then ex := gw-1; if (ey < 0) then ey := 0 else if (ey >= gh) then ey := gh-1; - if (sx > ex) or (sy > ey) then exit; // just in case + if (sx > ex) or (sy > ey) then begin result.finishIt(); exit; end; // just in case // has something to do @@ -1501,18 +1505,18 @@ begin if (x0+w <= px.mX) or (y0+h <= px.mY) then continue; presobj := PITP(framePool.alloc(sizeof(ITP))); Move(px.mObj, presobj^, sizeof(ITP)); - Inc(result); - if (firstHit) then exit; + if (firstHit) then begin result.finishIt(); exit; end; end; curci := cc.next; end; end; end; + result.finishIt(); end; // ////////////////////////////////////////////////////////////////////////// // -function TBodyGridBase.forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Integer; +function TBodyGridBase.forEachAlongLine (ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1; log: Boolean=false): Iter; var lw: TLineWalker; ccidx: Integer; @@ -1528,9 +1532,9 @@ var presobj: PITP; begin log := false; - result := 0; + result := Iter.Create(framePool); tagmask := tagmask and TagFullMask; - if (tagmask = 0) then exit; + if (tagmask = 0) then begin result.finishIt(); exit; end; gw := mWidth; gh := mHeight; @@ -1544,7 +1548,7 @@ begin y1 := ay1-miny; lw := TLineWalker.Create(0, 0, gw*mTileSize-1, gh*mTileSize-1); - if not lw.setup(x0, y0, x1, y1) then exit; // out of screen + if not lw.setup(x0, y0, x1, y1) then begin result.finishIt(); exit; end; // out of screen // increase query counter Inc(mLastQuery); @@ -1574,7 +1578,6 @@ begin px.mQueryMark := lq; // mark as processed presobj := PITP(framePool.alloc(sizeof(ITP))); Move(px.mObj, presobj^, sizeof(ITP)); - Inc(result); end; end; // next cell @@ -1582,12 +1585,12 @@ begin end; // done processing cells, move to next tile until lw.stepToNextTile(); + result.finishIt(); end; // ////////////////////////////////////////////////////////////////////////// // // trace box with the given velocity; return object hit (if any) -// `cb` is used unconvetionally here: if it returns `false`, tracer will ignore the object function TBodyGridBase.traceBox (out ex, ey: Integer; const ax0, ay0, aw, ah: Integer; const dx, dy: Integer; tagmask: Integer=-1): ITP; var gx, gy: Integer; @@ -1701,7 +1704,7 @@ var {$IF DEFINED(D2F_DEBUG_OTR)} s: AnsiString = ''; {$ENDIF} - pmark: PoolMark; + it: Iter; begin result := false; ex := ax1; @@ -1711,9 +1714,9 @@ begin tagmask := tagmask and TagFullMask; if (tagmask = 0) then exit; - pmark := framePool.mark(); - if (forEachAtPoint(ax0, ay0, tagmask, false, true) = 0) then exit; - framePool.release(pmark); + it := forEachAtPoint(ax0, ay0, tagmask, false, true); + if (it.length = 0) then begin it.release(); exit; end; + it.release(); minx := mMinX; miny := mMinY; @@ -1828,7 +1831,6 @@ begin end; -// no callback: return `true` on the nearest hit // you are not supposed to understand this function TBodyGridBase.traceRay (out ex, ey: Integer; const ax0, ay0, ax1, ay1: Integer; tagmask: Integer=-1): ITP; var