X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_map.pas;h=45a3fa3ccfb5b5c0e48acc5281dd295b55d782a3;hb=2b79b90a46d647d1d5bf4205862be5ffa296add1;hp=36ac9072a2fc315286abddb31042cba92eb9e053;hpb=6eab64d006f1081bc5096507bb634928cadd6d66;p=d2df-sdl.git diff --git a/src/game/g_map.pas b/src/game/g_map.pas index 36ac907..45a3fa3 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -67,7 +67,7 @@ procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer); procedure g_Map_DrawBack(dx, dy: Integer); function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; - PanelType: Word; b1x3: Boolean): Boolean; + PanelType: Word; b1x3: Boolean=false): Boolean; function g_Map_CollideLiquid_Texture(X, Y: Integer; Width, Height: Word): DWORD; procedure g_Map_EnableWall(ID: DWORD); procedure g_Map_DisableWall(ID: DWORD); @@ -91,6 +91,15 @@ procedure g_Map_LoadState(Var Mem: TBinMemoryReader); procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius: Integer); +// returns wall index in `gWalls` or -1 +function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Boolean; + +type + TForEachPanelCB = function (pan: TPanel): Boolean; // return `true` to stop + +function g_Map_HasAnyPanelAtPoint (x, y: Integer; panelType: Word): Boolean; + + procedure g_Map_ProfilersBegin (); procedure g_Map_ProfilersEnd (); @@ -164,16 +173,14 @@ var gdbg_map_use_accel_render: Boolean = true; gdbg_map_use_accel_coldet: Boolean = true; - gdbg_map_use_tree_draw: Boolean = false; - gdbg_map_use_tree_coldet: Boolean = false; - gdbg_map_dump_coldet_tree_queries: Boolean = false; + //gdbg_map_use_tree_draw: Boolean = false; + //gdbg_map_use_tree_coldet: Boolean = false; + //gdbg_map_dump_coldet_tree_queries: Boolean = false; profMapCollision: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY! gDrawPanelList: TBinaryHeapObj = nil; // binary heap of all walls we have to render, populated by `g_Map_CollectDrawPanels()` function panelTypeToTag (panelType: Word): Integer; // returns GridTagXXX -function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Integer; - implementation @@ -195,12 +202,15 @@ const type TPanelGrid = specialize TBodyGridBase; + { TDynAABBTreePanelBase = specialize TDynAABBTreeBase; TDynAABBTreeMap = class(TDynAABBTreePanelBase) function getFleshAABB (out aabb: AABB2D; pan: TPanel; tag: Integer): Boolean; override; end; + { +{ function TDynAABBTreeMap.getFleshAABB (out aabb: AABB2D; pan: TPanel; tag: Integer): Boolean; begin result := false; @@ -210,6 +220,7 @@ begin if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!'); result := true; end; +} function panelTypeToTag (panelType: Word): Integer; @@ -261,7 +272,7 @@ var FlagPoints: Array [FLAG_RED..FLAG_BLUE] of PFlagPoint; //DOMFlagPoints: Array of TFlagPoint; gMapGrid: TPanelGrid = nil; - mapTree: TDynAABBTreeMap = nil; + //mapTree: TDynAABBTreeMap = nil; procedure g_Map_ProfilersBegin (); @@ -285,7 +296,8 @@ end; // wall index in `gWalls` or -1 -function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Integer; +(* +function g_Map_traceToNearestWallOld (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Integer; function sqchecker (pan: TPanel; var ray: Ray2D): Single; var @@ -298,6 +310,7 @@ function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; if not aabb.valid then exit; if aabb.intersects(ray, @tmin) then begin + //if (tmin*tmin > maxDistSq) then exit; if (tmin >= 0.0) then begin //e_WriteLog(Format('sqchecker(%d,%d,%d,%d): panel #%d (%d,%d)-(%d,%d); tmin=%f', [x0, y0, x1, y1, pan.arrIdx, pan.X, pan.Y, pan.Width, pan.Height, tmin]), MSG_NOTIFY); @@ -312,12 +325,14 @@ var ray: Ray2D; hxf, hyf: Single; hx, hy: Integer; + maxDistSq: Single; begin result := -1; if (mapTree = nil) then exit; if mapTree.segmentQuery(qr, x0, y0, x1, y1, sqchecker, (GridTagWall or GridTagDoor)) then begin - if (qr.flesh <> nil) then + maxDistSq := (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0); + if (qr.flesh <> nil) and (qr.time*qr.time <= maxDistSq) then begin result := qr.flesh.arrIdx; if (hitx <> nil) or (hity <> nil) then @@ -346,6 +361,95 @@ begin end; end; end; +*) + + +// wall index in `gWalls` or -1 +function g_Map_traceToNearestWall (x0, y0, x1, y1: Integer; hitx: PInteger=nil; hity: PInteger=nil): Boolean; +var + lastX, lastY, lastDistSq: Integer; + wasHit: Boolean = false; + + // pan=nil: before processing new tile + function sqchecker (pan: TPanel; tag: Integer; x, y, prevx, prevy: Integer): Boolean; + var + distSq: Integer; + begin + if (pan = nil) then + begin + // stop if something was hit at the previous tile + result := wasHit; + end + else + begin + result := false; + if ((tag and (GridTagWall or GridTagDoor)) <> 0) then + begin + if not pan.Enabled then exit; + end; + distSq := (prevx-x0)*(prevx-x0)+(prevy-y0)*(prevy-y0); + if (distSq < lastDistSq) then + begin + wasHit := true; + lastDistSq := distSq; + lastX := prevx; + lastY := prevy; + end; + end; + end; + +begin + result := false; + if (gMapGrid = nil) then exit; + lastDistSq := (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)+1; + lastX := 0; + lastY := 0; + result := gMapGrid.traceRay(x0, y0, x1, y1, sqchecker, (GridTagWall or GridTagDoor)); + if (hitx <> nil) then hitx^ := lastX; + if (hity <> nil) then hity^ := lastY; +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; @@ -1129,15 +1233,15 @@ var pan.tag := tag; if not pan.visvalid then continue; gMapGrid.insertBody(pan, pan.X, pan.Y, pan.Width, pan.Height, tag); - mapTree.insertObject(pan, tag, true); // as static object + //mapTree.insertObject(pan, tag, true); // as static object end; end; begin gMapGrid.Free(); gMapGrid := nil; - mapTree.Free(); - mapTree := nil; + //mapTree.Free(); + //mapTree := nil; calcBoundingBox(gWalls); calcBoundingBox(gRenderBackgrounds); @@ -1152,7 +1256,7 @@ begin e_WriteLog(Format('map dimensions: (%d,%d)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1]), MSG_WARNING); gMapGrid := TPanelGrid.Create(mapX0, mapY0, mapX1-mapX0+1, mapY1-mapY0+1); - mapTree := TDynAABBTreeMap.Create(); + //mapTree := TDynAABBTreeMap.Create(); addPanelsToGrid(gWalls, PANEL_WALL); addPanelsToGrid(gWalls, PANEL_CLOSEDOOR); @@ -1167,8 +1271,8 @@ begin addPanelsToGrid(gBlockMon, PANEL_BLOCKMON); gMapGrid.dumpStats(); - e_WriteLog(Format('tree depth: %d; %d nodes used, %d nodes allocated', [mapTree.computeTreeHeight, mapTree.nodeCount, mapTree.nodeAlloced]), MSG_NOTIFY); - mapTree.forEachLeaf(nil); + //e_WriteLog(Format('tree depth: %d; %d nodes used, %d nodes allocated', [mapTree.computeTreeHeight, mapTree.nodeCount, mapTree.nodeAlloced]), MSG_NOTIFY); + //mapTree.forEachLeaf(nil); end; function g_Map_Load(Res: String): Boolean; @@ -1205,8 +1309,8 @@ var begin gMapGrid.Free(); gMapGrid := nil; - mapTree.Free(); - mapTree := nil; + //mapTree.Free(); + //mapTree := nil; Result := False; gMapInfo.Map := Res; @@ -2005,11 +2109,11 @@ begin dplClear(); //tagmask := panelTypeToTag(PanelType); - if gdbg_map_use_tree_draw then + {if gdbg_map_use_tree_draw then begin mapTree.aabbQuery(x0, y0, wdt, hgt, checker, (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore)); end - else + else} begin gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore)); end; @@ -2025,11 +2129,11 @@ procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius: end; begin - if gdbg_map_use_tree_draw then + {if gdbg_map_use_tree_draw then begin mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor)); end - else + else} begin gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor)); end; @@ -2045,7 +2149,7 @@ begin end; function g_Map_CollidePanelOld(X, Y: Integer; Width, Height: Word; - PanelType: Word; b1x3: Boolean): Boolean; + PanelType: Word; b1x3: Boolean=false): Boolean; var a, h: Integer; begin @@ -2211,8 +2315,8 @@ function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; ((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))) and - g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); + (WordBool(PanelType and PANEL_LIFTRIGHT) and (pan.LiftType = 3))) {and + g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height)}; exit; end; @@ -2223,7 +2327,8 @@ function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; end; // other shit - result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); + //result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height); + result := true; end; var @@ -2242,7 +2347,7 @@ begin if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('*solids'); if gdbg_map_use_accel_coldet then begin - if gdbg_map_use_tree_coldet then + {if gdbg_map_use_tree_coldet then begin //e_WriteLog(Format('coldet query: x=%d; y=%d; w=%d; h=%d', [X, Y, Width, Height]), MSG_NOTIFY); result := (mapTree.aabbQuery(X, Y, Width, Height, checker, tagmask) <> nil); @@ -2252,9 +2357,16 @@ begin g_Console_Add(Format('map collision: %d nodes visited (%d deep)', [mapTree.nodesVisited, mapTree.nodesDeepVisited])); end; end - else + else} begin - result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker, tagmask); + if (Width = 1) and (Height = 1) then + begin + result := gMapGrid.forEachAtPoint(X, Y, checker, tagmask); + end + else + begin + result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker, tagmask); + end; end; end else @@ -2282,7 +2394,7 @@ var //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // allowed: water, acid1, acid2 end; // collision? - if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit; + //if not g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then exit; // yeah texid := pan.GetTextureID(); // water? water has the highest priority, so stop right here @@ -2298,13 +2410,20 @@ begin if gdbg_map_use_accel_coldet then begin texid := TEXTURE_NONE; - if gdbg_map_use_tree_coldet then + {if gdbg_map_use_tree_coldet then begin mapTree.aabbQuery(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2)); end - else + else} begin - gMapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2)); + if (Width = 1) and (Height = 1) then + begin + gMapGrid.forEachAtPoint(X, Y, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2)); + end + else + begin + gMapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWater or GridTagAcid1 or GridTagAcid2)); + end; end; result := texid; end @@ -2320,7 +2439,7 @@ begin with gWalls[ID] do begin Enabled := True; - g_Mark(X, Y, Width, Height, MARK_DOOR, True); + //g_Mark(X, Y, Width, Height, MARK_DOOR, True); if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID); end; @@ -2331,7 +2450,7 @@ begin with gWalls[ID] do begin Enabled := False; - g_Mark(X, Y, Width, Height, MARK_DOOR, False); + //g_Mark(X, Y, Width, Height, MARK_DOOR, False); if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID); end; @@ -2374,6 +2493,7 @@ begin begin LiftType := t; + { g_Mark(X, Y, Width, Height, MARK_LIFT, False); if LiftType = 0 then @@ -2384,6 +2504,7 @@ begin g_Mark(X, Y, Width, Height, MARK_LIFTLEFT, True) else if LiftType = 3 then g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT, True); + } if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID); end;