diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas
index 3b36ba3acff15c455d8498cbae4f0afc60bd67a9..280fd90f3fd967f0753a31ee69cb6386ceb5fd05 100644 (file)
--- a/src/game/g_grid.pas
+++ b/src/game/g_grid.pas
function allocProxy (aX, aY, aWidth, aHeight: Integer; aObj: ITP; aTag: Integer): TBodyProxyId;
procedure freeProxy (body: TBodyProxyId);
- procedure insertInternal (body: TBodyProxyId);
- procedure removeInternal (body: TBodyProxyId);
-
function forGridRect (x, y, w, h: Integer; cb: TGridInternalCB; bodyId: TBodyProxyId): Boolean;
function inserter (grida: Integer; bodyId: TBodyProxyId): Boolean;
// ////////////////////////////////////////////////////////////////////////// //
-//procedure swapInt (var a: Integer; var b: Integer); inline; var t: Integer; begin t := a; a := b; b := t; end;
-procedure swapInt (var a: Integer; var b: Integer); inline; begin a := a xor b; b := b xor a; a := a xor b; end;
+procedure swapInt (var a: Integer; var b: Integer); inline; var t: Integer; begin t := a; a := b; b := t; end;
+//procedure swapInt (var a: Integer; var b: Integer); inline; begin a := a xor b; b := b xor a; a := a xor b; end;
//function minInt (a, b: Integer): Integer; inline; begin if (a < b) then result := a else result := b; end;
//function maxInt (a, b: Integer): Integer; inline; begin if (a > b) then result := a else result := b; end;
// ////////////////////////////////////////////////////////////////////////// //
function TBodyGridBase.forGridRect (x, y, w, h: Integer; cb: TGridInternalCB; bodyId: TBodyProxyId): Boolean;
var
- gx, gy: Integer;
gw, gh: Integer;
+ ex, ey: Integer;
+ gx, gy: Integer;
begin
result := false;
if (w < 1) or (h < 1) or not assigned(cb) then exit;
if (x+w <= 0) or (y+h <= 0) then exit;
gw := mWidth;
gh := mHeight;
- //tsize := mTileSize;
if (x >= gw*mTileSize) or (y >= gh*mTileSize) then exit;
- for gy := y div mTileSize to (y+h-1) div mTileSize do
- begin
- if (gy < 0) then continue;
- if (gy >= gh) then break;
- for gx := x div mTileSize to (x+w-1) div mTileSize do
+ ex := (x+w-1) div mTileSize;
+ ey := (y+h-1) div mTileSize;
+ x := x div mTileSize;
+ y := y div mTileSize;
+ // clip rect
+ if (x < 0) then x := 0 else if (x >= gw) then x := gw-1;
+ if (y < 0) then y := 0 else if (y >= gh) then y := 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 (x > ex) or (y > ey) then exit; // just in case
+ // do the work
+ for gy := y to ey do
+ begin
+ for gx := x to ex do
begin
- if (gx < 0) then continue;
- if (gx >= gw) then break;
result := cb(gy*gw+gx, bodyId);
if result then exit;
end;
mGrid[grida] := ccidx;
end;
-procedure TBodyGridBase.insertInternal (body: TBodyProxyId);
-var
- px: PBodyProxyRec;
-begin
- if (body < 0) or (body > High(mProxies)) then exit; // just in case
- px := @mProxies[body];
- forGridRect(px.mX, px.mY, px.mWidth, px.mHeight, inserter, body);
-end;
-
// assume that we cannot have one object added to bucket twice
function TBodyGridBase.remover (grida: Integer; bodyId: TBodyProxyId): Boolean;
end;
end;
-procedure TBodyGridBase.removeInternal (body: TBodyProxyId);
-var
- px: PBodyProxyRec;
-begin
- if (body < 0) or (body > High(mProxies)) then exit; // just in case
- px := @mProxies[body];
- forGridRect(px.mX, px.mY, px.mWidth, px.mHeight, remover, body);
-end;
-
// ////////////////////////////////////////////////////////////////////////// //
function TBodyGridBase.insertBody (aObj: ITP; aX, aY, aWidth, aHeight: Integer; aTag: Integer=-1): TBodyProxyId;
begin
aTag := aTag and TagFullMask;
result := allocProxy(aX, aY, aWidth, aHeight, aObj, aTag);
- insertInternal(result);
+ //insertInternal(result);
+ forGridRect(aX, aY, aWidth, aHeight, inserter, result);
end;
procedure TBodyGridBase.removeBody (body: TBodyProxyId);
+var
+ px: PBodyProxyRec;
begin
if (body < 0) or (body > High(mProxies)) then exit; // just in case
- removeInternal(body);
+ px := @mProxies[body];
+ //removeInternal(body);
+ forGridRect(px.mX, px.mY, px.mWidth, px.mHeight, remover, body);
freeProxy(body);
end;
// did any corner crossed tile boundary?
if (x0 div mTileSize <> nx div mTileSize) or
(y0 div mTileSize <> ny div mTileSize) or
- ((x0+w) div mTileSize <> (nx+nw) div mTileSize) or
- ((y0+h) div mTileSize <> (ny+nh) div mTileSize) then
+ ((x0+w-1) div mTileSize <> (nx+nw-1) div mTileSize) or
+ ((y0+h-1) div mTileSize <> (ny+nh-1) div mTileSize) then
begin
- removeInternal(body);
+ //writeln('moveResizeBody: cell occupation changed! old=(', x0, ',', y0, ')-(', x0+w-1, ',', y0+h-1, '); new=(', nx, ',', ny, ')-(', nx+nw-1, ',', ny+nh-1, ')');
+ //removeInternal(body);
+ forGridRect(px.mX, px.mY, px.mWidth, px.mHeight, remover, body);
px.mX := nx+mMinX;
px.mY := ny+mMinY;
px.mWidth := nw;
px.mHeight := nh;
- insertInternal(body);
+ //insertInternal(body);
+ forGridRect(px.mX, px.mY, nw, nh, inserter, body);
end
else
begin
end;
end;
+
//TODO: optimize for horizontal/vertical moves
procedure TBodyGridBase.moveBody (body: TBodyProxyId; nx, ny: Integer);
var
px.mY := ny+mMinY;
end;
+
procedure TBodyGridBase.resizeBody (body: TBodyProxyId; nw, nh: Integer);
var
px: PBodyProxyRec;
{$IF DEFINED(D2F_DEBUG_MOVER)}
e_WriteLog(Format('proxy #%d: RESIZE: xg=%d;yg=%d;w=%d;h=%d;nw=%d;nh=%d', [body, x0, y0, w, h, nw, nh]), MSG_NOTIFY);
{$ENDIF}
- if ((x0+w) div mTileSize <> (x0+nw) div mTileSize) or
- ((y0+h) div mTileSize <> (y0+nh) div mTileSize) then
+ if ((x0+w-1) div mTileSize <> (x0+nw-1) div mTileSize) or
+ ((y0+h-1) div mTileSize <> (y0+nh-1) div mTileSize) then
begin
// crossed tile boundary, do heavy work
- removeInternal(body);
+ //removeInternal(body);
+ forGridRect(px.mX, px.mY, px.mWidth, px.mHeight, remover, body);
px.mWidth := nw;
px.mHeight := nh;
- insertInternal(body);
+ //insertInternal(body);
+ forGridRect(px.mX, px.mY, nw, nh, inserter, body);
end
else
begin
@@ -1724,12 +1722,13 @@ function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; cb: TGridQueryCB; tag
var
idx: Integer;
gx, gy: Integer;
+ sx, sy, ex, ey: Integer;
curci: Integer;
f: Integer;
cc: PGridCell = nil;
px: PBodyProxyRec;
lq: LongWord;
- gw: Integer;
+ gw, gh: Integer;
x0, y0: Integer;
ptag: Integer;
begin
Dec(y, mMinY);
gw := mWidth;
- //tsize := mTileSize;
+ gh := mHeight;
if (x+w <= 0) or (y+h <= 0) then exit;
- if (x >= gw*mTileSize) or (y >= mHeight*mTileSize) then exit;
+ if (x >= gw*mTileSize) or (y >= gh*mTileSize) then exit;
+
+ sx := x div mTileSize;
+ sy := y div mTileSize;
+ ex := (x+w-1) div mTileSize;
+ ey := (y+h-1) div mTileSize;
+
+ // clip rect
+ if (sx < 0) then sx := 0 else if (sx >= gw) then sx := gw-1;
+ 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
+ // has something to do
if mInQuery then raise Exception.Create('recursive queries aren''t supported');
mInQuery := true;
lq := mLastQuery;
// go on
- for gy := y div mTileSize to (y+h-1) div mTileSize do
+ for gy := sy to ey do
begin
- if (gy < 0) then continue;
- if (gy >= mHeight) then break;
- for gx := x div mTileSize to (x+w-1) div mTileSize do
+ for gx := sx to ex do
begin
- if (gx < 0) then continue;
- if (gx >= gw) then break;
// process cells
curci := mGrid[gy*gw+gx];
while (curci <> -1) do
begin
if (cc.bodies[f] = -1) then break;
px := @mProxies[cc.bodies[f]];
- // shit. has to do it this way, so i can change tag in callback
+ // shit! has to do it this way, so i can change tag in callback
if (px.mQueryMark = lq) then continue;
px.mQueryMark := lq;
ptag := px.mTag;