summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0cf1438)
raw | patch | inline | side by side (parent: 0cf1438)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sat, 20 Jan 2018 23:10:48 +0000 (01:10 +0200) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sat, 20 Jan 2018 23:14:00 +0000 (01:14 +0200) |
diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas
index 99eb0ef6328eded53312d6727422e333b4baceb1..ce31c63546d60a9721f1211e1cdeab54ad4fa950 100644 (file)
--- a/src/game/g_grid.pas
+++ b/src/game/g_grid.pas
x, y: Integer;
end;
+ CellCoordIter = specialize PoolIter<TGridCellCoord>;
+
+
type
TBodyProxyId = Integer;
type PITP = ^ITP;
type TCellQueryCB = procedure (x, y: Integer) is nested; // top-left cell corner coords
+ type Iter = specialize PoolIter<ITP>;
+
const TagDisabled = $40000000;
const TagFullMask = $3fffffff;
// 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;
// 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
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
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(true);
+ if (body < 0) or (body > High(mProxies)) then begin result.finishIt(); exit; end;
for g := 0 to High(mGrid) do
begin
ccidx := mGrid[g];
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;
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(true);
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
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;
// ////////////////////////////////////////////////////////////////////////// //
// 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;
ptag: Integer;
presobj: PITP;
begin
- result := 0;
+ result := Iter.Create(true);
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);
// 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)];
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;
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(true);
+ 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;
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;
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
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;
presobj: PITP;
begin
log := false;
- result := 0;
+ result := Iter.Create(true);
tagmask := tagmask and TagFullMask;
- if (tagmask = 0) then exit;
+ if (tagmask = 0) then begin result.finishIt(); exit; end;
gw := mWidth;
gh := mHeight;
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);
px.mQueryMark := lq; // mark as processed
presobj := PITP(framePool.alloc(sizeof(ITP)));
Move(px.mObj, presobj^, sizeof(ITP));
- Inc(result);
end;
end;
// next cell
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;
{$IF DEFINED(D2F_DEBUG_OTR)}
s: AnsiString = '';
{$ENDIF}
- pmark: PoolMark;
+ it: Iter;
begin
result := false;
ex := ax1;
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;
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
diff --git a/src/game/g_holmes.pas b/src/game/g_holmes.pas
index f4fe415cbf97a6f499b01b65e342e0ae1b12136e..d16aa603f57a480a8319ae940fde412e0763bb10 100644 (file)
--- a/src/game/g_holmes.pas
+++ b/src/game/g_holmes.pas
procedure hilightBodyCells (proxyId: Integer);
var
- pmark: PoolMark;
- hitcount: Integer;
+ it: CellCoordIter;
pcellxy: PGridCellCoord;
begin
//monsGrid.forEachBodyCell(mon.proxyId, hilightCell);
- pmark := framePool.mark();
- hitcount := monsGrid.forEachBodyCell(proxyId);
- pcellxy := PGridCellCoord(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- hilightCell(pcellxy^.x, pcellxy^.y);
- Inc(pcellxy);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := monsGrid.forEachBodyCell(proxyId);
+ for pcellxy in it do hilightCell(pcellxy^.x, pcellxy^.y);
+ it.release();
end;
procedure hilightCell1 (cx, cy: Integer);
var
mon: TMonster;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
mx, my, mw, mh: Integer;
//pan: TPanel;
//ex, ey: Integer;
- pmark: PoolMark;
- hitcount: Integer;
- pmon: PMonster;
begin
if (gPlayer1 = nil) then exit;
if (laserSet) then
begin
//g_Mons_AlongLine(laserX0, laserY0, laserX1, laserY1, monsCollector, true);
- pmark := framePool.mark();
- hitcount := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true);
- pmon := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- monsCollector(pmon^);
- Inc(pmon);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := monsGrid.forEachAlongLine(laserX0, laserY0, laserX1, laserY1, -1, true);
+ for mit in it do monsCollector(mit^);
+ it.release();
end;
if (monMarkedUID <> -1) then
var
plr: TPlayer;
x, y, w, h: Integer;
- pmark: PoolMark;
- hitcount: Integer;
- pmon: PMonster;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
begin
monMarkedUID := -1;
if (Length(gPlayers) > 0) then
end;
end;
//e_WriteLog('===========================', MSG_NOTIFY);
- pmark := framePool.mark();
- hitcount := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
- pmon := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- monsAtDump(pmon^);
- Inc(pmon);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
+ for mit in it do monsAtDump(mit^);
+ it.release();
//e_WriteLog('---------------------------', MSG_NOTIFY);
end;
e_WriteLog(Format('monster #%d (UID:%u) (proxyid:%d)', [mon.arrIdx, mon.UID, mon.proxyId]), TMsgType.Notify);
end;
var
- pmark: PoolMark;
- hitcount: Integer;
- pmon: PMonster;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
begin
- pmark := framePool.mark();
- hitcount := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
- if (hitcount > 0) then
+ it := monsGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY);
+ if (it.length > 0) then
begin
e_WriteLog('===========================', TMsgType.Notify);
- pmon := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- monsAtDump(pmon^);
- Inc(pmon);
- Dec(hitcount);
- end;
+ for mit in it do monsAtDump(mit^);
e_WriteLog('---------------------------', TMsgType.Notify);
end;
- framePool.release(pmark);
+ it.release();
end;
procedure cbAtcurDumpWalls ();
hasTrigs: Boolean = false;
f: Integer;
trig: PTrigger;
- pmark: PoolMark;
- hitcount: Integer;
- ppan: PPanel;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
begin
platMarkedGUID := -1;
- pmark := framePool.mark();
- hitcount := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
- if (hitcount > 0) then
+ it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
+ if (it.length > 0) then
begin
e_WriteLog('=== TOGGLE WALL ===', TMsgType.Notify);
- ppan := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- wallToggle(ppan^);
- Inc(ppan);
- Dec(hitcount);
- end;
+ for mwit in it do wallToggle(mwit^);
e_WriteLog('--- toggle wall ---', TMsgType.Notify);
end;
- framePool.release(pmark);
+ it.release();
if showTriggers then
begin
for f := 0 to High(gTriggers) do
if pan.Enabled then g_Map_DisableWallGUID(pan.guid) else g_Map_EnableWallGUID(pan.guid);
end;
var
- pmark: PoolMark;
- hitcount: Integer;
- ppan: PPanel;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
begin
//e_WriteLog('=== TOGGLE WALL ===', MSG_NOTIFY);
//e_WriteLog('--- toggle wall ---', MSG_NOTIFY);
- pmark := framePool.mark();
- hitcount := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
- ppan := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- wallToggle(ppan^);
- Inc(ppan);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := mapGrid.forEachAtPoint(pmsCurMapX, pmsCurMapY, (GridTagWall or GridTagDoor));
+ for mwit in it do wallToggle(mwit^);
+ it.release();
end;
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 4455ed9a66578a53b0e53cca9dec46c7ab79292c..1ddbffdd052253d446f2163e1f4597294dd445ff 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean;
var
tagmask: Integer = 0;
- pmark: PoolMark;
- hitcount: Integer;
- ppan: PPanel;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
begin
result := false;
if (tagmask = 0) then exit;// just in case
- pmark := framePool.mark();
if ((tagmask and GridTagLift) <> 0) then
begin
// slow
- hitcount := mapGrid.forEachAtPoint(x, y, tagmask);
- ppan := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- if (xxPanAtPointChecker(ppan^, PanelType)) then begin result := true; break; end;
- Inc(ppan);
- Dec(hitcount);
- end;
+ it := mapGrid.forEachAtPoint(x, y, tagmask);
+ for mwit in it do if (xxPanAtPointChecker(mwit^, PanelType)) then begin result := true; break; end;
end
else
begin
// fast
- result := (mapGrid.forEachAtPoint(x, y, tagmask, false, true) <> 0); // firsthit
+ it := mapGrid.forEachAtPoint(x, y, tagmask, false, true);
+ result := (it.length <> 0); // firsthit
end;
- framePool.release(pmark);
+ it.release();
end;
function g_Map_PanelAtPoint (x, y: Integer; tagmask: Integer=-1): TPanel;
var
- pmark: PoolMark;
- hitcount: Integer;
+ it: TPanelGrid.Iter;
begin
result := nil;
if (tagmask = 0) then exit;
- pmark := framePool.mark();
- hitcount := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit
- if (hitcount <> 0) then result := PPanel(framePool.getPtr(pmark))^;
- framePool.release(pmark);
+ it := mapGrid.forEachAtPoint(x, y, tagmask, false, true); // firsthit
+ if (it.length <> 0) then result := it.first^;
+ it.release();
end;
// new algo
procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer);
var
- pmark: PoolMark;
- phit: PPanel;
- hitcount: Integer;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
begin
dplClear();
- pmark := framePool.mark();
- hitcount := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask);
- if (hitcount = 0) then exit;
- phit := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- if (((phit^.tag and GridTagDoor) <> 0) = phit^.Door) then gDrawPanelList.insert(phit^);
- Inc(phit);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := mapGrid.forEachInAABB(x0, y0, wdt, hgt, GridDrawableMask);
+ for mwit in it do if (((mwit^.tag and GridTagDoor) <> 0) = mwit^.Door) then gDrawPanelList.insert(mwit^);
+ it.release();
// list will be rendered in `g_game.DrawPlayer()`
end;
procedure g_Map_DrawPanelShadowVolumes (lightX: Integer; lightY: Integer; radius: Integer);
var
- pmark: PoolMark;
- phit: PPanel;
- hitcount: Integer;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
begin
- pmark := framePool.mark();
- hitcount := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor));
- if (hitcount = 0) then exit;
- phit := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- phit^.DrawShadowVolume(lightX, lightY, radius);
- Inc(phit);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor));
+ for mwit in it do mwit^.DrawShadowVolume(lightX, lightY, radius);
+ it.release();
end;
var
tagmask: Integer = 0;
- pmark: PoolMark;
- phit: PPanel;
- hitcount: Integer;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
pan: TPanel;
begin
result := false;
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids');
if gdbg_map_use_accel_coldet then
begin
- pmark := framePool.mark();
if ((tagmask and SlowMask) <> 0) then
begin
// slow
- hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask);
- phit := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
+ it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask);
+ for mwit in it do
begin
- pan := phit^;
+ pan := mwit^;
if ((pan.tag and GridTagLift) <> 0) then
begin
result :=
result := true; // i found her!
end;
if (result) then break;
- Inc(phit);
- Dec(hitcount);
end;
end
else
begin
// fast
- hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit
- result := (hitcount > 0);
+ it := mapGrid.forEachInAABB(X, Y, Width, Height, tagmask, false, true); // return first hit
+ result := (it.length > 0);
end;
- framePool.release(pmark);
+ it.release();
end
else
begin
function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD;
var
cctype: Integer = 3; // priority: 0: water was hit, 1: acid1 was hit, 2: acid2 was hit; 3: nothing was hit
- pmark: PoolMark;
- phit: PPanel;
- hitcount: Integer;
- pan: TPanel;
+ mwit: PPanel;
+ it: TPanelGrid.Iter;
begin
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('liquids');
if gdbg_map_use_accel_coldet then
begin
result := LongWord(TEXTURE_NONE);
- pmark := framePool.mark();
- hitcount := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2));
- if (hitcount = 0) then exit;
- phit := PPanel(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- pan := phit^;
- Inc(phit);
- Dec(hitcount);
- if (liquidChecker(pan, result, cctype)) then break;
- end;
- framePool.release(pmark);
+ it := mapGrid.forEachInAABB(X, Y, Width, Height, (GridTagWater or GridTagAcid1 or GridTagAcid2));
+ for mwit in it do if (liquidChecker(mwit^, result, cctype)) then break;
+ it.release();
end
else
begin
index 018a69359a90fa4598097ea48ad3fc4193454653..bb3d293ded57dc0413327ff01394b2a2055f41f8 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
var
a: Integer;
- mon: TMonster = nil;
- pmark: PoolMark;
- phit: PMonster;
- hitcount: Integer;
+ mon: PMonster;
+ mres: TMonster = nil;
+ it: TMonsterGrid.Iter;
begin
result := -1;
begin
//mon := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height, monsCollCheck);
//if (mon <> nil) then result := mon.mArrIdx;
- pmark := framePool.mark();
- hitcount := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height);
- if (hitcount = 0) then exit;
- phit := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
+ it := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height);
+ for mon in it do
begin
- mon := phit^;
- Inc(phit);
- Dec(hitcount);
case mon.FMonsterType of // Íå âîñêðåñèòü:
MONSTER_SOUL, MONSTER_PAIN, MONSTER_CYBER, MONSTER_SPIDER,
- MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: mon := nil;
+ MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: begin end;
// Îñòàëüíûõ ìîæíî âîñêðåñèòü
+ else mres := mon^;
end;
- if (mon <> nil) then break;
+ if (mres <> nil) then break;
end;
- framePool.release(pmark);
- if (mon <> nil) then result := mon.mArrIdx;
+ it.release();
+ if (mres <> nil) then result := mres.mArrIdx;
end
else
begin
@@ -4725,27 +4719,17 @@ function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean;
var
idx: Integer;
mon: TMonster;
- pmark: PoolMark;
- phit: PMonster;
- hitcount: Integer;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
begin
result := false;
if (width < 1) or (height < 1) then exit;
if gmon_debug_use_sqaccel then
begin
//result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
- pmark := framePool.mark();
- hitcount := monsGrid.forEachInAABB(x, y, width, height);
- if (hitcount = 0) then exit;
- phit := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- mon := phit^;
- Inc(phit);
- Dec(hitcount);
- if (mon.alive) then begin result := true; break; end;
- end;
- framePool.release(pmark);
+ it := monsGrid.forEachInAABB(x, y, width, height);
+ for mit in it do if (mit.alive) then begin result := true; break; end;
+ it.release();
end
else
begin
@@ -4775,27 +4759,17 @@ function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonst
var
idx: Integer;
mon: TMonster;
- pmark: PoolMark;
- phit: PMonster;
- hitcount: Integer;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
begin
result := false;
if (width < 1) or (height < 1) then exit;
if gmon_debug_use_sqaccel then
begin
//result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
- pmark := framePool.mark();
- hitcount := monsGrid.forEachInAABB(x, y, width, height);
- if (hitcount = 0) then exit;
- phit := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- mon := phit^;
- Inc(phit);
- Dec(hitcount);
- if (cb(mon)) then begin result := true; break; end;
- end;
- framePool.release(pmark);
+ it := monsGrid.forEachInAABB(x, y, width, height);
+ for mit in it do if (cb(mit^)) then begin result := true; break; end;
+ it.release();
end
else
begin
@@ -4827,9 +4801,8 @@ function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEach
var
idx: Integer;
mon: TMonster;
- pmark: PoolMark;
- phit: PMonster;
- hitcount: Integer;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
begin
result := false;
if (width < 1) or (height < 1) then exit;
result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
end;
}
- pmark := framePool.mark();
- hitcount := monsGrid.forEachInAABB(x, y, width, height);
- if (hitcount = 0) then exit;
- phit := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
+ it := monsGrid.forEachInAABB(x, y, width, height);
+ for mit in it do
begin
- mon := phit^;
- Inc(phit);
- Dec(hitcount);
- if (mon.alive) then
+ if (mit^.alive) then
begin
- if (cb(mon)) then begin result := true; break; end;
+ if (cb(mit^)) then begin result := true; break; end;
end;
end;
- framePool.release(pmark);
+ it.release();
end
else
begin
diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas
index 725ab6d701a05634adb9baffe2e256e6b94d41ee..3b1330170a988940f5d158494d4972a722faff6d 100644 (file)
--- a/src/game/g_weapons.pas
+++ b/src/game/g_weapons.pas
{$IF DEFINED(D2F_DEBUG)}
stt: UInt64;
{$ENDIF}
- pmark: PoolMark;
- hitcount: Integer;
- pmon: PMonster;
+ mit: PMonster;
+ it: TMonsterGrid.Iter;
begin
(*
if not gwep_debug_fast_trace then
// collect monsters
//g_Mons_AlongLine(x, y, x2, y2, sqchecker);
- pmark := framePool.mark();
- hitcount := monsGrid.forEachAlongLine(x, y, x2, y2, -1);
- pmon := PMonster(framePool.getPtr(pmark));
- while (hitcount > 0) do
- begin
- sqchecker(pmon^);
- Inc(pmon);
- Dec(hitcount);
- end;
- framePool.release(pmark);
+ it := monsGrid.forEachAlongLine(x, y, x2, y2, -1);
+ for mit in it do sqchecker(mit^);
+ it.release();
// here, we collected all monsters and players in `wgunHitHeap` and `wgunHitTime`
// also, if `wallWasHit` is `true`, then `wallHitX` and `wallHitY` contains spark coords
diff --git a/src/shared/mempool.pas b/src/shared/mempool.pas
index 1604055c028f6620f115998343a90966a458eb5d..ae67f034aa60363ec362b8b04b4a6ff2f4bec870 100644 (file)
--- a/src/shared/mempool.pas
+++ b/src/shared/mempool.pas
// get pointer for the given mark
// WARNING! pointer can become invalid after next call to `alloc()`!
function getPtr (amark: PoolMark): Pointer; inline;
+ function curPtr (): Pointer; inline;
+ end;
+
+
+type
+ generic PoolIter<T> = record
+ public
+ type Ptr = ^T;
+ type MyType = specialize PoolIter<T>;
+
+ private
+ mMark: PoolMark;
+ mCount: Integer;
+ mCurrent: Integer;
+ mFinished: Boolean;
+
+ public
+ constructor Create (dummy: Boolean); // idiotic FPC doesn't support arg-less ctors for rectord
+ procedure startIt (); inline; // automatically called by ctor; does NO checks!
+ procedure finishIt (); inline; // sets count
+
+ procedure rewind (); inline;
+ function length (): Integer; inline;
+ procedure release (); inline; // reset pool
+
+ function moveNext (): Boolean; inline;
+ function getCurrent (): Ptr; inline;
+ function getEnumerator (): MyType; inline;
+
+ function first (): Ptr; inline;
+
+ public
+ property current: Ptr read getCurrent;
end;
end;
+function TPoolMarkRelease.curPtr (): Pointer; inline;
+begin
+ result := Pointer(PAnsiChar(mMemory)+mUsed);
+end;
+
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor PoolIter.Create (dummy: Boolean);
+begin
+ startIt();
+end;
+
+
+procedure PoolIter.startIt (); inline; // automatically called by ctor; does NO checks!
+begin
+ mMark := framePool.mark();
+ mCount := 0;
+ mCurrent := -1;
+ mFinished := false;
+end;
+
+
+procedure PoolIter.finishIt (); inline; // sets count
+begin
+ if (mFinished) then raise Exception.Create('double fatality');
+ if (mMark = -1) then raise Exception.Create('void fatality');
+ mFinished := true;
+ mCount := Integer(PtrUInt(framePool.curPtr)-PtrUInt(framePool.getPtr(mMark))) div Integer(sizeof(T));
+ if (mCount < 0) then raise Exception.Create('wutafu?');
+end;
+
+
+procedure PoolIter.rewind (); inline;
+begin
+ if (mMark = -1) then raise Exception.Create('void rewind');
+ mCurrent := -1;
+end;
+
+
+function PoolIter.length (): Integer; inline;
+begin
+ //if (mCurrent+1 >= 0) and (mCurrent+1 < mCount) then result := mCount-(mCurrent+1) else result := 0;
+ result := mCount;
+end;
+
+
+procedure PoolIter.release (); inline; // reset pool
+begin
+ if (mMark = -1) then raise Exception.Create('double release');
+ framePool.release(mMark);
+ mMark := -1;
+ mCount := 0;
+ mCurrent := -1;
+ mFinished := false;
+end;
+
+
+function PoolIter.moveNext (): Boolean; inline;
+begin
+ if (mMark = -1) then raise Exception.Create('void moveNext()');
+ if (not mFinished) then raise Exception.Create('moveNext() on unfinished');
+ Inc(mCurrent);
+ result := (mCurrent < mCount);
+end;
+
+
+function PoolIter.getCurrent (): Ptr; inline;
+begin
+ if (mCurrent < 0) or (mCurrent >= mCount) then raise Exception.Create('getCurrent() range error');
+ result := Ptr(framePool.getPtr(mMark+mCurrent*Integer(sizeof(T))));
+end;
+
+
+function PoolIter.getEnumerator (): PoolIter; inline;
+begin
+ result := self;
+end;
+
+
+function PoolIter.first (): Ptr; inline;
+begin
+ if (mMark = -1) then raise Exception.Create('void moveNext()');
+ if (not mFinished) then raise Exception.Create('moveNext() on unfinished');
+ result := Ptr(framePool.getPtr(mMark));
+end;
+
+
// ////////////////////////////////////////////////////////////////////////// //
{$IFDEF USE_MEMPOOL}
uses