From c414b87769c21e17010b8de0dfe36da681edcdbb Mon Sep 17 00:00:00 2001 From: Ketmar Dark Date: Tue, 22 Aug 2017 02:58:26 +0300 Subject: [PATCH] grid code uglification; particles are great again (i hope) --- src/game/g_basic.pas | 2 +- src/game/g_gfx.pas | 52 ++++++------- src/game/g_grid.pas | 174 +++++++++++++++++++++++++++---------------- src/game/g_map.pas | 44 +++++++++++ 4 files changed, 183 insertions(+), 89 deletions(-) diff --git a/src/game/g_basic.pas b/src/game/g_basic.pas index 1f3add5..a579023 100644 --- a/src/game/g_basic.pas +++ b/src/game/g_basic.pas @@ -201,7 +201,7 @@ begin Result := True; *) - //result := false; + result := false; if g_Map_traceToNearestWall(x1, y1, x2, y2, @wallHitX, @wallHitY) then begin // check distance diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas index d6244b7..44a9db4 100644 --- a/src/game/g_gfx.pas +++ b/src/game/g_gfx.pas @@ -19,7 +19,7 @@ unit g_gfx; interface uses - g_textures; + e_log, g_textures; const BLOOD_NORMAL = 0; @@ -102,49 +102,49 @@ var CurrentParticle: Integer; -function isBlockedAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isBlockedAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP)); + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP)); end; // ??? -function isWallAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isWallAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, (PANEL_WALL or PANEL_STEP)); + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_STEP)); end; -function isLiftUpAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isLiftUpAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, PANEL_LIFTUP); + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTUP); end; -function isLiftDownAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isLiftDownAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, PANEL_LIFTDOWN); + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTDOWN); end; -function isLiftLeftAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isLiftLeftAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, PANEL_LIFTLEFT); + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTLEFT); end; -function isLiftRightAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isLiftRightAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, PANEL_LIFTRIGHT); + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTRIGHT); end; -function isLiquidAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isLiquidAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, (PANEL_WATER or PANEL_ACID1 or PANEL_ACID2)); + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WATER or PANEL_ACID1 or PANEL_ACID2)); end; -function isAnythingAt (x, y: Integer; w: Integer=1; h: Integer=1): Boolean; inline; +function isAnythingAt (x, y: Integer): Boolean; inline; begin - result := g_Map_CollidePanel(x, y, w, h, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR or PANEL_WATER or PANEL_ACID1 or PANEL_ACID2 or PANEL_STEP or PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)); + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR or PANEL_WATER or PANEL_ACID1 or PANEL_ACID2 or PANEL_STEP or PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)); end; @@ -833,15 +833,15 @@ begin len := High(Particles); for a := 0 to len do - if Particles[a].State <> 0 then + begin + if Particles[a].State <> STATE_FREE then + begin with Particles[a] do begin - if Time = LiveTime then - State := STATE_FREE; - if (X+1 >= w) or (Y+1 >= h) or (X <= 0) or (Y <= 0) then - State := STATE_FREE; - if State = STATE_FREE then - Continue; + if Time = LiveTime then State := STATE_FREE; + if (X+1 >= w) or (Y+1 >= h) or (X <= 0) or (Y <= 0) then State := STATE_FREE; + if State = STATE_FREE then Continue; + //e_WriteLog(Format('particle #%d: %d', [State, ParticleType]), MSG_NOTIFY); case ParticleType of PARTICLE_BLOOD: @@ -1294,7 +1294,9 @@ begin end; // case CorrectOffsets(a); - end; + end; // with + end; // if + end; // for end; // Particles <> nil if OnceAnims <> nil then diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index 661e341..da26a5f 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -78,7 +78,6 @@ type mUData: TBodyProxyId; // for inserter/remover mTagMask: Integer; // for iterator mItCB: TGridQueryCB; // for iterator - mQueryInProcess: Boolean; private function allocCell: Integer; @@ -94,7 +93,6 @@ type function inserter (grida: Integer): Boolean; function remover (grida: Integer): Boolean; - function iterator (grida: Integer): Boolean; public constructor Create (aMinPixX, aMinPixY, aPixWidth, aPixHeight: Integer; aTileSize: Integer=GridDefaultTileSize); @@ -110,6 +108,9 @@ type //WARNING: can't do recursive queries function forEachInAABB (x, y, w, h: Integer; cb: TGridQueryCB; tagmask: Integer=-1): Boolean; + //WARNING: can't do recursive queries + function forEachAtPoint (x, y: Integer; cb: TGridQueryCB; tagmask: Integer=-1): Boolean; + //WARNING: can't do recursive queries // cb with `(nil)` will be called before processing new tile function traceRay (x0, y0, x1, y1: Integer; cb: TGridRayQueryCB; tagmask: Integer=-1): Boolean; overload; @@ -180,7 +181,6 @@ begin mUData := 0; mTagMask := -1; mItCB := nil; - mQueryInProcess := false; e_WriteLog(Format('created grid with size: %dx%d (tile size: %d); pix: %dx%d', [mWidth, mHeight, mTileSize, mWidth*mTileSize, mHeight*mTileSize]), MSG_NOTIFY); end; @@ -313,12 +313,66 @@ begin begin if (gx < 0) then continue; if (gx >= mWidth) then break; - if (cb(gy*mWidth+gx)) then begin result := true; exit; end; + result := cb(gy*mWidth+gx); + if result then exit; end; end; end; +// ////////////////////////////////////////////////////////////////////////// // +function TBodyGridBase.forEachAtPoint (x, y: Integer; cb: TGridQueryCB; tagmask: Integer=-1): Boolean; +var + idx, ga, curci: Integer; + f: Integer; + cc: PGridCell = nil; + px: PBodyProxyRec; + lq: LongWord; +begin + result := false; + if not assigned(cb) or (tagmask = 0) then exit; + + Dec(x, mMinX); + Dec(y, mMinY); + if (x < 0) or (y < 0) or (x >= mWidth*mTileSize) or (y >= mHeight*mTileSize) then exit; + + ga := (y div mTileSize)*mWidth+(x div mTileSize); + curci := mGrid[ga]; + Inc(x, mMinX); + Inc(y, mMinY); + + // increase query counter + Inc(mLastQuery); + if (mLastQuery = 0) then + begin + // just in case of overflow + mLastQuery := 1; + for idx := 0 to High(mProxies) do mProxies[idx].mQueryMark := 0; + end; + lq := mLastQuery; + + while (curci <> -1) do + begin + cc := @mCells[curci]; + for f := 0 to High(TGridCell.bodies) do + begin + if (cc.bodies[f] = -1) then break; + px := @mProxies[cc.bodies[f]]; + if (px.mQueryMark <> lq) and ((px.mTag and tagmask) <> 0) then + begin + if (x >= px.mX) and (y >= px.mY) and (x < px.mX+px.mWidth) and (y < px.mY+px.mHeight) then + begin + px.mQueryMark := lq; + result := cb(px.mObj, px.mTag); + if result then exit; + end; + end; + end; + curci := cc.next; + end; +end; + + // ////////////////////////////////////////////////////////////////////////// // function TBodyGridBase.traceRay (x0, y0, x1, y1: Integer; cb: TGridRayQueryCB; tagmask: Integer=-1): Boolean; var @@ -342,7 +396,7 @@ var prevX, prevY: Integer; minx, miny: Integer; begin - result := False; + result := false; if (tagmask = 0) then exit; @@ -572,22 +626,16 @@ end; function TBodyGridBase.insertBody (aObj: ITP; aX, aY, aWidth, aHeight: Integer; aTag: Integer=0): TBodyProxyId; begin - if mQueryInProcess then raise Exception.Create('grid doesn''t support recursive queries'); - mQueryInProcess := true; result := allocProxy(aX, aY, aWidth, aHeight, aObj, aTag); insert(result); - mQueryInProcess := false; end; procedure TBodyGridBase.removeBody (aObj: TBodyProxyId); begin if (aObj < 0) or (aObj > High(mProxies)) then exit; // just in case - if mQueryInProcess then raise Exception.Create('grid doesn''t support recursive queries'); - mQueryInProcess := true; remove(aObj); freeProxy(aObj); - mQueryInProcess := false; end; @@ -597,8 +645,6 @@ var begin if (body < 0) or (body > High(mProxies)) then exit; // just in case if ((dx = 0) and (dy = 0) and (sx = 0) and (sy = 0)) then exit; - if mQueryInProcess then raise Exception.Create('grid doesn''t support recursive queries'); - mQueryInProcess := true; remove(body); px := @mProxies[body]; Inc(px.mX, dx); @@ -606,7 +652,6 @@ begin Inc(px.mWidth, sx); Inc(px.mHeight, sy); insert(body); - mQueryInProcess := false; end; procedure TBodyGridBase.moveBody (body: TBodyProxyId; dx, dy: Integer); @@ -620,58 +665,33 @@ begin end; -function TBodyGridBase.iterator (grida: Integer): Boolean; +function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; cb: TGridQueryCB; tagmask: Integer=-1): Boolean; var idx: Integer; - px: PBodyProxyRec; - {$IFDEF grid_use_buckets} - pi: PGridCell; + gx, gy: Integer; + curci: Integer; f: Integer; - {$ENDIF} + cc: PGridCell = nil; + px: PBodyProxyRec; + lq: LongWord; + tsize, gw: Integer; + x0, y0: Integer; begin result := false; - idx := mGrid[grida]; - while (idx >= 0) do - begin - {$IFDEF grid_use_buckets} - pi := @mCells[idx]; - for f := 0 to High(TGridCell.bodies) do - begin - if (pi.bodies[f] = -1) then break; - px := @mProxies[pi.bodies[f]]; - if (px.mQueryMark <> mLastQuery) and ((mTagMask = -1) or ((px.mTag and mTagMask) <> 0)) then - begin - //e_WriteLog(Format(' query #%d body hit: (%d,%d)-(%dx%d) tag:%d', [mLastQuery, mCells[idx].body.mX, mCells[idx].body.mY, mCells[idx].body.mWidth, mCells[idx].body.mHeight, mCells[idx].body.mTag]), MSG_NOTIFY); - px.mQueryMark := mLastQuery; - if (mItCB(px.mObj, px.mTag)) then begin result := true; exit; end; - end; - end; - idx := pi.next; - {$ELSE} - if (mCells[idx].body <> -1) then - begin - px := @mProxies[mCells[idx].body]; - if (px.mQueryMark <> mLastQuery) and ((mTagMask = -1) or ((px.mTag and mTagMask) <> 0)) then - begin - //e_WriteLog(Format(' query #%d body hit: (%d,%d)-(%dx%d) tag:%d', [mLastQuery, mCells[idx].body.mX, mCells[idx].body.mY, mCells[idx].body.mWidth, mCells[idx].body.mHeight, mCells[idx].body.mTag]), MSG_NOTIFY); - px.mQueryMark := mLastQuery; - if (mItCB(px.mObj, px.mTag)) then begin result := true; exit; end; - end; - end; - idx := mCells[idx].next; - {$ENDIF} - end; -end; + if (w < 1) or (h < 1) or not assigned(cb) then exit; -function TBodyGridBase.forEachInAABB (x, y, w, h: Integer; cb: TGridQueryCB; tagmask: Integer=-1): Boolean; -var - idx: Integer; -begin - result := false; - if not assigned(cb) then exit; + x0 := x; + y0 := y; + + // fix coords + Dec(x, mMinX); + Dec(y, mMinY); + + gw := mWidth; + tsize := mTileSize; - if mQueryInProcess then raise Exception.Create('grid doesn''t support recursive queries'); - mQueryInProcess := true; + if (x+w <= 0) or (y+h <= 0) then exit; + if (x >= gw*tsize) or (y >= mHeight*tsize) then exit; // increase query counter Inc(mLastQuery); @@ -682,11 +702,39 @@ begin for idx := 0 to High(mProxies) do mProxies[idx].mQueryMark := 0; end; //e_WriteLog(Format('grid: query #%d: (%d,%d)-(%dx%d)', [mLastQuery, minx, miny, maxx, maxy]), MSG_NOTIFY); + lq := mLastQuery; - mTagMask := tagmask; - mItCB := cb; - result := forGridRect(x, y, w, h, iterator); - mQueryInProcess := false; + // go on + for gy := y div tsize to (y+h-1) div tsize do + begin + if (gy < 0) then continue; + if (gy >= mHeight) then break; + for gx := x div tsize to (x+w-1) div tsize do + begin + if (gx < 0) then continue; + if (gx >= gw) then break; + // process cells + curci := mGrid[gy*gw+gx]; + while (curci <> -1) do + begin + cc := @mCells[curci]; + for f := 0 to High(TGridCell.bodies) do + begin + if (cc.bodies[f] = -1) then break; + px := @mProxies[cc.bodies[f]]; + if (px.mQueryMark <> lq) and ((px.mTag and tagmask) <> 0) then + begin + if (x0 >= px.mX+px.mWidth) or (y0 >= px.mY+px.mHeight) then continue; + if (x0+w <= px.mX) or (y0+h <= px.mY) then continue; + px.mQueryMark := lq; + result := cb(px.mObj, px.mTag); + if result then exit; + end; + end; + curci := cc.next; + end; + end; + end; end; diff --git a/src/game/g_map.pas b/src/game/g_map.pas index ae230c2..bd8acf8 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -99,6 +99,8 @@ type function g_Map_ForEachPanelAt (x, y: Integer; cb: TForEachPanelCB; panelType: Word): Boolean; +function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; + procedure g_Map_ProfilersBegin (); procedure g_Map_ProfilersEnd (); @@ -456,6 +458,48 @@ begin end; +function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; + + function checker (pan: TPanel; tag: Integer): Boolean; + begin + result := false; // don't stop, ever + + if ((tag and (GridTagWall or GridTagDoor)) <> 0) then + begin + if not pan.Enabled then exit; + end; + + result := (x >= pan.X) and (y >= pan.Y) and (x < pan.X+pan.Width) and (y < pan.Y+pan.Height); + if not result then exit; + + if ((tag and GridTagLift) <> 0) then + begin + result := + ((WordBool(PanelType and PANEL_LIFTUP) and (pan.LiftType = 0)) or + (WordBool(PanelType and PANEL_LIFTDOWN) and (pan.LiftType = 1)) or + (WordBool(PanelType and PANEL_LIFTLEFT) and (pan.LiftType = 2)) or + (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = 3))); + end; + end; + +var + tagmask: Integer = 0; +begin + result := false; + + if WordBool(PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR)) then tagmask := tagmask or (GridTagWall or GridTagDoor); + if WordBool(PanelType and PANEL_WATER) then tagmask := tagmask or GridTagWater; + if WordBool(PanelType and PANEL_ACID1) then tagmask := tagmask or GridTagAcid1; + if WordBool(PanelType and PANEL_ACID2) then tagmask := tagmask or GridTagAcid2; + if WordBool(PanelType and PANEL_STEP) then tagmask := tagmask or GridTagStep; + if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) then tagmask := tagmask or GridTagLift; + if WordBool(PanelType and PANEL_BLOCKMON) then tagmask := tagmask or GridTagBlockMon; + + if (tagmask = 0) then exit;// just in case + result := gMapGrid.forEachAtPoint(x, y, checker, tagmask); +end; + + function g_Map_IsSpecialTexture(Texture: String): Boolean; begin Result := (Texture = TEXTURE_NAME_WATER) or -- 2.29.2