summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 9358607)
raw | patch | inline | side by side (parent: 9358607)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sat, 19 Aug 2017 12:10:35 +0000 (15:10 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sat, 19 Aug 2017 13:28:00 +0000 (16:28 +0300) |
src/game/g_game.pas | patch | blob | history | |
src/game/g_grid.pas | patch | blob | history | |
src/game/g_map.pas | patch | blob | history | |
src/game/g_panel.pas | patch | blob | history |
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index f1dd84fe5988eb8e0162adca742d0137925c5ede..a50ce72609f18dfddfa5d3781b785dd0b16ad684 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
uses
g_textures, g_main, g_window, g_menu,
- e_input, e_log, g_console, g_items, g_map,
+ e_input, e_log, g_console, g_items, g_map, g_panel,
g_playermodel, g_gfx, g_options, g_weapons, Math,
g_triggers, MAPDEF, g_monsters, e_sound, CONFIG,
BinEditor, g_language, g_net, SDL,
// ////////////////////////////////////////////////////////////////////////// //
-(*
-procedure drawProfiles (x, y: Integer; title: AnsiString); overload;
-var
- wdt, hgt: Integer;
- yy: Integer;
-
- {
- procedure drawItems ();
- begin
- repeat
- e_TextureFontPrintEx(x+2+4*xprofItLevel, yy, Format('%s: %d', [xprofItName, Integer(xprofItMicro)]), gStdFont, 255, 255, 0, 1, false);
- Inc(yy, 16+2);
- if xprofItHasChildren then
- begin
- xprofItDive();
- drawItems();
- xprofItPop();
- end;
- until not xprofItNext();
- end;
- }
-
- procedure drawItems ();
- var
- ii, idx: Integer;
- begin
- for ii := 0 to xprofTotalCount-1 do
- begin
- e_TextureFontPrintEx(x+2+4*xprofLevelAt(ii), yy, Format('%s: %d', [xprofNameAt(ii), Integer(xprofMicroAt(ii))]), gStdFont, 255, 255, 0, 1, false);
- Inc(yy, 16+2);
- end;
- end;
-
-begin
- // gScreenWidth
- //if not xprofItReset() then exit;
- if (xprofTotalCount = 0) then exit;
- wdt := 256;
- hgt := 16+2+xprofTotalCount*(16+2); // title, items
- // background
- //e_DrawFillQuad(x, y, x+wdt-1, y+hgt-1, 255, 255, 255, 200, B_BLEND);
- e_DrawFillQuad(x, y, x+wdt-1, y+hgt-1, 20, 20, 20, 0, B_NONE);
- // title
- e_TextureFontPrintEx(x+2, y+2, Format('%s: %d', [title, Integer(xprofTotalMicro)]), gStdFont, 255, 255, 0, 1, false);
- yy := y+16+2;
- drawItems();
-end;
-*)
-
-
function calcProfilesHeight (prof: TProfiler): Integer;
begin
result := 0;
end;
end;
+
+// setup sX, sY, sWidth, sHeight, and transformation matrix before calling this!
+procedure renderDynLightsInternal ();
+var
+ lln: Integer;
+ lx, ly, lrad: Integer;
+begin
+ //TODO: lights should be in separate grid, i think
+ // but on the other side: grid may be slower for dynlights, as their lifetime is short
+ if not gwin_has_stencil or (g_dynLightCount < 1) then exit;
+
+ // setup OpenGL parameters
+ glStencilMask($FFFFFFFF);
+ glStencilFunc(GL_ALWAYS, 0, $FFFFFFFF);
+ glEnable(GL_STENCIL_TEST);
+ glEnable(GL_SCISSOR_TEST);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ glStencilFunc(GL_EQUAL, 0, $ff);
+
+ for lln := 0 to g_dynLightCount-1 do
+ begin
+ lx := g_dynLights[lln].x;
+ ly := g_dynLights[lln].y;
+ lrad := g_dynLights[lln].radius;
+ if lrad < 3 then continue;
+
+ if lx-sX+lrad < 0 then continue;
+ if ly-sY+lrad < 0 then continue;
+ if lx-sX-lrad >= gPlayerScreenSize.X then continue;
+ if ly-sY-lrad >= gPlayerScreenSize.Y then continue;
+
+ // set scissor to optimize drawing
+ glScissor((lx-sX)-lrad+2, gPlayerScreenSize.Y-(ly-sY)-lrad-1+2, lrad*2-4, lrad*2-4);
+ // no need to clear stencil buffer, light blitting will do it for us
+ glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
+ // draw extruded panels
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no need to modify color buffer
+ if (lrad > 4) then g_Map_DrawPanelShadowVolumes(lx, ly, lrad);
+ // render light texture
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // modify color buffer
+ glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // draw light, and clear stencil buffer
+ // blend it
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_TEXTURE_2D);
+ // color and opacity
+ glColor4f(g_dynLights[lln].r, g_dynLights[lln].g, g_dynLights[lln].b, g_dynLights[lln].a);
+ glBindTexture(GL_TEXTURE_2D, g_Texture_Light());
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0, 0.0); glVertex2i(lx-lrad, ly-lrad); // top-left
+ glTexCoord2f(1.0, 0.0); glVertex2i(lx+lrad, ly-lrad); // top-right
+ glTexCoord2f(1.0, 1.0); glVertex2i(lx+lrad, ly+lrad); // bottom-right
+ glTexCoord2f(0.0, 1.0); glVertex2i(lx-lrad, ly+lrad); // bottom-left
+ glEnd();
+ end;
+
+ // done
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
+ glScissor(0, 0, sWidth, sHeight);
+end;
+
+
+// setup sX, sY, sWidth, sHeight, and transformation matrix before calling this!
+// WARNING! this WILL CALL `glTranslatef()`, but won't restore matrices!
+procedure renderMapInternal (backXOfs, backYOfs: Integer; transX, transY: Integer; setTransMatrix: Boolean);
+type
+ TDrawCB = procedure ();
+
+ procedure drawPanelType (profname: AnsiString; panType: DWord);
+ var
+ tagmask: Integer;
+ pan: TPanel;
+ begin
+ profileFrameDraw.sectionBegin(profname);
+ if gdbg_map_use_accel_render then
+ begin
+ tagmask := panelTypeToTag(panType);
+ {$IF TRUE}
+ while (gDrawPanelList.count > 0) do
+ begin
+ pan := TPanel(gDrawPanelList.front());
+ if ((pan.tag and tagmask) = 0) then break;
+ pan.Draw();
+ gDrawPanelList.popFront();
+ end;
+ {$ELSE}
+ e_WriteLog(Format('=== PANELS: %d ===', [gDrawPanelList.count]), MSG_NOTIFY);
+ while (gDrawPanelList.count > 0) do
+ begin
+ pan := TPanel(gDrawPanelList.front());
+ e_WriteLog(Format('tagmask: 0x%04x; pan.tag: 0x%04x; pan.ArrIdx: %d', [tagmask, pan.tag, pan.ArrIdx]), MSG_NOTIFY);
+ pan.Draw();
+ gDrawPanelList.popFront();
+ end;
+ {$ENDIF}
+ end
+ else
+ begin
+ g_Map_DrawPanels(panType);
+ end;
+ profileFrameDraw.sectionEnd();
+ end;
+
+ procedure drawOther (profname: AnsiString; cb: TDrawCB);
+ begin
+ profileFrameDraw.sectionBegin(profname);
+ if assigned(cb) then cb();
+ profileFrameDraw.sectionEnd();
+ end;
+
+begin
+ profileFrameDraw.sectionBegin('map rendering');
+
+ // our accelerated renderer will collect all panels to gDrawPanelList
+ // we can use panel tag to render level parts (see GridTagXXX in g_map.pas)
+ profileFrameDraw.sectionBegin('pancollect');
+ if gdbg_map_use_accel_render then
+ begin
+ g_Map_CollectDrawPanels(sX, sY, sWidth, sHeight);
+ end;
+ profileFrameDraw.sectionEnd();
+
+ profileFrameDraw.sectionBegin('map background');
+ g_Map_DrawBack(backXOfs, backYOfs);
+ profileFrameDraw.sectionEnd();
+
+ if (setTransMatrix) then glTranslatef(transX, transY, 0);
+
+ drawPanelType('panel_back', PANEL_BACK);
+ drawPanelType('panel_step', PANEL_STEP);
+ drawOther('items', @g_Items_Draw);
+ drawOther('weapons', @g_Weapon_Draw);
+ drawOther('shells', @g_Player_DrawShells);
+ drawOther('drawall', @g_Player_DrawAll);
+ drawOther('corpses', @g_Player_DrawCorpses);
+ drawPanelType('panel_wall', PANEL_WALL);
+ drawOther('monsters', @g_Monsters_Draw);
+ drawPanelType('panel_closedoor', PANEL_CLOSEDOOR);
+ drawOther('gfx', @g_GFX_Draw);
+ drawOther('flags', @g_Map_DrawFlags);
+ drawPanelType('panel_acid1', PANEL_ACID1);
+ drawPanelType('panel_acid2', PANEL_ACID2);
+ drawPanelType('panel_water', PANEL_WATER);
+ drawOther('dynlights', @renderDynLightsInternal);
+ drawPanelType('panel_fore', PANEL_FORE);
+
+ if g_debug_HealthBar then
+ begin
+ g_Monsters_DrawHealth();
+ g_Player_DrawHealth();
+ end;
+
+ profileFrameDraw.mainEnd(); // map rendering
+end;
+
+
procedure DrawMapView(x, y, w, h: Integer);
+
var
bx, by: Integer;
begin
bx := Round(x/(gMapInfo.Width - w)*(gBackSize.X - w));
by := Round(y/(gMapInfo.Height - h)*(gBackSize.Y - h));
- g_Map_DrawBack(-bx, -by);
sX := x;
sY := y;
sWidth := w;
sHeight := h;
- glTranslatef(-x, -y, 0);
-
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_BACK);
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_STEP);
- g_Items_Draw();
- g_Weapon_Draw();
- g_Player_DrawShells();
- g_Player_DrawAll();
- g_Player_DrawCorpses();
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_WALL);
- g_Monsters_Draw();
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_CLOSEDOOR);
- g_GFX_Draw();
- g_Map_DrawFlags();
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_ACID1);
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_ACID2);
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_WATER);
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_FORE);
- if g_debug_HealthBar then
- begin
- g_Monsters_DrawHealth();
- g_Player_DrawHealth();
- end;
+ renderMapInternal(-bx, -by, -x, -y, true);
glPopMatrix();
end;
+
procedure DrawPlayer(p: TPlayer);
var
px, py, a, b, c, d: Integer;
//R: TRect;
- lln: Integer;
- lx, ly, lrad: Integer;
+
begin
if (p = nil) or (p.FDummy) then
begin
px := p.GameX + PLAYER_RECT_CX;
py := p.GameY + PLAYER_RECT_CY;
- if px > (gPlayerScreenSize.X div 2) then
- a := -px + (gPlayerScreenSize.X div 2)
- else
- a := 0;
- if py > (gPlayerScreenSize.Y div 2) then
- b := -py + (gPlayerScreenSize.Y div 2)
- else
- b := 0;
- if px > (gMapInfo.Width - (gPlayerScreenSize.X div 2)) then
- a := -gMapInfo.Width + gPlayerScreenSize.X;
- if py > (gMapInfo.Height - (gPlayerScreenSize.Y div 2)) then
- b := -gMapInfo.Height + gPlayerScreenSize.Y;
- if gMapInfo.Width <= gPlayerScreenSize.X then
- a := 0;
- if gMapInfo.Height <= gPlayerScreenSize.Y then
- b := 0;
+ if px > (gPlayerScreenSize.X div 2) then a := -px+(gPlayerScreenSize.X div 2) else a := 0;
+ if py > (gPlayerScreenSize.Y div 2) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0;
+
+ if px > gMapInfo.Width-(gPlayerScreenSize.X div 2) then a := -gMapInfo.Width+gPlayerScreenSize.X;
+ if py > gMapInfo.Height-(gPlayerScreenSize.Y div 2) then b := -gMapInfo.Height+gPlayerScreenSize.Y;
+
+ if gMapInfo.Width <= gPlayerScreenSize.X then a := 0;
+ if gMapInfo.Height <= gPlayerScreenSize.Y then b := 0;
if p.IncCam <> 0 then
begin
- if py > (gMapInfo.Height - (gPlayerScreenSize.Y div 2)) then
+ if py > gMapInfo.Height-(gPlayerScreenSize.Y div 2) then
begin
if p.IncCam > 120-(py-(gMapInfo.Height-(gPlayerScreenSize.Y div 2))) then
+ begin
p.IncCam := 120-(py-(gMapInfo.Height-(gPlayerScreenSize.Y div 2)));
+ end;
end;
- if py < (gPlayerScreenSize.Y div 2) then
+ if py < gPlayerScreenSize.Y div 2 then
begin
if p.IncCam < -120+((gPlayerScreenSize.Y div 2)-py) then
+ begin
p.IncCam := -120+((gPlayerScreenSize.Y div 2)-py);
+ end;
end;
if p.IncCam < 0 then
- while (py+(gPlayerScreenSize.Y div 2)-p.IncCam > gMapInfo.Height) and
- (p.IncCam < 0) do
- p.IncCam := p.IncCam + 1;
+ begin
+ while (py+(gPlayerScreenSize.Y div 2)-p.IncCam > gMapInfo.Height) and (p.IncCam < 0) do p.IncCam := p.IncCam+1; //Inc(p.IncCam);
+ end;
if p.IncCam > 0 then
- while (py-(gPlayerScreenSize.Y div 2)-p.IncCam < 0) and
- (p.IncCam > 0) do
- p.IncCam := p.IncCam - 1;
+ begin
+ while (py-(gPlayerScreenSize.Y div 2)-p.IncCam < 0) and (p.IncCam > 0) do p.IncCam := p.IncCam-1; //Dec(p.IncCam);
+ end;
end;
- if (px< gPlayerScreenSize.X div 2) or
- (gMapInfo.Width-gPlayerScreenSize.X <= 256) then
- c := 0
- else
- if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then
- c := gBackSize.X - gPlayerScreenSize.X
- else
- c := Round((px-(gPlayerScreenSize.X div 2))/(gMapInfo.Width-gPlayerScreenSize.X)*(gBackSize.X-gPlayerScreenSize.X));
+ if (px < gPlayerScreenSize.X div 2) or (gMapInfo.Width-gPlayerScreenSize.X <= 256) then c := 0
+ else if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then c := gBackSize.X-gPlayerScreenSize.X
+ else c := round((px-(gPlayerScreenSize.X div 2))/(gMapInfo.Width-gPlayerScreenSize.X)*(gBackSize.X-gPlayerScreenSize.X));
- if (py-p.IncCam <= gPlayerScreenSize.Y div 2) or
- (gMapInfo.Height-gPlayerScreenSize.Y <= 256) then
- d := 0
- else
- if (py-p.IncCam >= gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then
- d := gBackSize.Y - gPlayerScreenSize.Y
- else
- d := Round((py-p.IncCam-(gPlayerScreenSize.Y div 2))/(gMapInfo.Height-gPlayerScreenSize.Y)*(gBackSize.Y-gPlayerScreenSize.Y));
-
- profileFrameDraw.sectionBegin('map background');
- g_Map_DrawBack(-c, -d);
- profileFrameDraw.sectionEnd();
+ if (py-p.IncCam <= gPlayerScreenSize.Y div 2) or (gMapInfo.Height-gPlayerScreenSize.Y <= 256) then d := 0
+ else if (py-p.IncCam >= gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then d := gBackSize.Y-gPlayerScreenSize.Y
+ else d := round((py-p.IncCam-(gPlayerScreenSize.Y div 2))/(gMapInfo.Height-gPlayerScreenSize.Y)*(gBackSize.Y-gPlayerScreenSize.Y));
sX := -a;
sY := -(b+p.IncCam);
sWidth := gPlayerScreenSize.X;
sHeight := gPlayerScreenSize.Y;
- glTranslatef(a, b+p.IncCam, 0);
-
- profileFrameDraw.sectionBegin('map rendering');
-
- profileFrameDraw.sectionBegin('panel_back');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_BACK);
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('panel_step');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_STEP);
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('items');
- g_Items_Draw();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('weapons');
- g_Weapon_Draw();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('shells');
- g_Player_DrawShells();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('drawall');
- g_Player_DrawAll();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('corpses');
- g_Player_DrawCorpses();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('panel_wall');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_WALL);
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('monsters');
- g_Monsters_Draw();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('panel_closedoor');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_CLOSEDOOR);
- profileFrameDraw.sectionEnd();
+ //glTranslatef(a, b+p.IncCam, 0);
- profileFrameDraw.sectionBegin('gfx');
- g_GFX_Draw();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('flags');
- g_Map_DrawFlags();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('panel_acid1');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_ACID1);
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('panel_acid2');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_ACID2);
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('panel_water');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_WATER);
- profileFrameDraw.sectionEnd();
-
- //TODO: lights should be in separate grid, i think
- // but on the other side: grid may be slower for dynlights, as their lifetime is short
- if gwin_has_stencil and (g_dynLightCount > 0) then
- begin
- profileFrameDraw.sectionBegin('dynlights');
-
- // setup OpenGL parameters
- glStencilMask($FFFFFFFF);
- glStencilFunc(GL_ALWAYS, 0, $FFFFFFFF);
- glEnable(GL_STENCIL_TEST);
- glEnable(GL_SCISSOR_TEST);
- glClear(GL_STENCIL_BUFFER_BIT);
- glStencilFunc(GL_EQUAL, 0, $ff);
-
- for lln := 0 to g_dynLightCount-1 do
- begin
- lx := g_dynLights[lln].x;
- ly := g_dynLights[lln].y;
- lrad := g_dynLights[lln].radius;
- if lrad < 3 then continue;
-
- if lx-sX+lrad < 0 then continue;
- if ly-sY+lrad < 0 then continue;
- if lx-sX-lrad >= gPlayerScreenSize.X then continue;
- if ly-sY-lrad >= gPlayerScreenSize.Y then continue;
-
- // set scissor to optimize drawing
- glScissor((lx-sX)-lrad+2, gPlayerScreenSize.Y-(ly-sY)-lrad-1+2, lrad*2-4, lrad*2-4);
- // no need to clear stencil buffer, light blitting will do it for us
- glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
- // draw extruded panels
- glDisable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no need to modify color buffer
- if (lrad > 4) then g_Map_DrawPanelShadowVolumes(lx, ly, lrad);
- // render light texture
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // modify color buffer
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // draw light, and clear stencil buffer
- // blend it
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_TEXTURE_2D);
- // color and opacity
- glColor4f(g_dynLights[lln].r, g_dynLights[lln].g, g_dynLights[lln].b, g_dynLights[lln].a);
- glBindTexture(GL_TEXTURE_2D, g_Texture_Light());
- glBegin(GL_QUADS);
- glTexCoord2f(0.0, 0.0); glVertex2i(lx-lrad, ly-lrad); // top-left
- glTexCoord2f(1.0, 0.0); glVertex2i(lx+lrad, ly-lrad); // top-right
- glTexCoord2f(1.0, 1.0); glVertex2i(lx+lrad, ly+lrad); // bottom-right
- glTexCoord2f(0.0, 1.0); glVertex2i(lx-lrad, ly+lrad); // bottom-left
- glEnd();
- end;
-
- // done
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_BLEND);
- glDisable(GL_SCISSOR_TEST);
- glScissor(0, 0, sWidth, sHeight);
-
- profileFrameDraw.sectionEnd();
- end
- else
- begin
- profileFrameDraw.sectionBegin('dynlights');
- profileFrameDraw.sectionEnd();
- end;
-
- profileFrameDraw.sectionBegin('panel_fore');
- g_Map_DrawPanels(sX, sY, sWidth, sHeight, PANEL_FORE);
- profileFrameDraw.sectionEnd();
-
- if g_debug_HealthBar then
- begin
- profileFrameDraw.sectionBegin('monster health');
- g_Monsters_DrawHealth();
- profileFrameDraw.sectionEnd();
-
- profileFrameDraw.sectionBegin('player health');
- g_Player_DrawHealth();
- profileFrameDraw.sectionEnd();
- end;
+ renderMapInternal(-c, -d, a, b+p.IncCam, true);
if p.FSpectator then
e_TextureFontPrintEx(p.GameX + PLAYER_RECT_CX - 4,
glPopMatrix();
- profileFrameDraw.mainEnd(); // map rendering
-
p.DrawPain();
p.DrawPickup();
p.DrawRulez();
begin
Parse_Params(pars);
- s := Find_Param_Value(pars, '--profile-frame');
+ s := Find_Param_Value(pars, '--profile-render');
if (s <> '') then g_profile_frame_draw := true;
s := Find_Param_Value(pars, '--profile-coldet');
diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas
index 17319db65fd01a3685bdd9b3b875a9843753fe11..3ed66124c29bdcf9d725e8812fa0f634895e3ba1 100644 (file)
--- a/src/game/g_grid.pas
+++ b/src/game/g_grid.pas
GridCellBucketSize = 8; // WARNING! can't be less than 2!
type
- GridQueryCB = function (obj: TObject; tag: Integer): Boolean is nested; // return `true` to stop
+ GridQueryCB = function (obj: TObject; var proxy: PBodyProxyRec; tag: Integer): Boolean is nested; // return `true` to stop
type
TBodyGrid = class;
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 634eff9be7ae4625b4483ad4e2b929508075922e..dd2f455ec38d17a4e668c4fed1339083710f4da2 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
uses
e_graphics, g_basic, MAPSTRUCT, g_textures, Classes,
- g_phys, wadreader, BinEditor, g_panel, g_grid, z_aabbtree, md5, xprofiler;
+ g_phys, wadreader, BinEditor, g_panel, g_grid, z_aabbtree, md5, binheap, xprofiler;
type
TMapInfo = record
procedure g_Map_Free();
procedure g_Map_Update();
-procedure g_Map_DrawPanels(x0, y0, wdt, hgt: Integer; PanelType: Word);
+procedure g_Map_DrawPanels (PanelType: Word); // unaccelerated
+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;
SKY_STRETCH: Single = 1.5;
+const
+ GridTagInvalid = 0;
+
+ (* draw order:
+ PANEL_BACK
+ PANEL_STEP
+ PANEL_WALL
+ PANEL_CLOSEDOOR
+ PANEL_ACID1
+ PANEL_ACID2
+ PANEL_WATER
+ PANEL_FORE
+ *)
+ // sorted by draw priority
+ GridTagBack = 1 shl 0;
+ GridTagStep = 1 shl 1;
+ GridTagWall = 1 shl 2;
+ GridTagDoor = 1 shl 3;
+ GridTagAcid1 = 1 shl 4;
+ GridTagAcid2 = 1 shl 5;
+ GridTagWater = 1 shl 6;
+ GridTagFore = 1 shl 7;
+ // the following are invisible
+ GridTagLift = 1 shl 8;
+ GridTagBlockMon = 1 shl 9;
+
+
var
gWalls: TPanelArray;
gRenderBackgrounds: TPanelArray;
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
implementation
GL, GLExt, g_weapons, g_game, g_sound, e_sound, CONFIG,
g_options, MAPREADER, g_triggers, g_player, MAPDEF,
Math, g_monsters, g_saveload, g_language, g_netmsg,
- utils, sfs, binheap,
+ utils, sfs,
ImagingTypes, Imaging, ImagingUtility,
ImagingGif, ImagingNetworkGraphics;
MUSIC_SIGNATURE = $4953554D; // 'MUSI'
FLAG_SIGNATURE = $47414C46; // 'FLAG'
- GridTagInvalid = 0;
- GridTagWallDoor = $0001;
- GridTagBack = $0002;
- GridTagFore = $0004;
- GridTagWater = $0008;
- GridTagAcid1 = $0010;
- GridTagAcid2 = $0020;
- GridTagStep = $0040;
- GridTagLift = $0080;
- GridTagBlockMon = $0100;
function panelTypeToTag (panelType: Word): Integer;
begin
case panelType of
- PANEL_WALL, PANEL_OPENDOOR, PANEL_CLOSEDOOR: result := GridTagWallDoor; // gWalls
+ PANEL_WALL: result := GridTagWall; // gWalls
+ PANEL_OPENDOOR, PANEL_CLOSEDOOR: result := GridTagDoor; // gWalls
PANEL_BACK: result := GridTagBack; // gRenderBackgrounds
PANEL_FORE: result := GridTagFore; // gRenderForegrounds
PANEL_WATER: result := GridTagWater; // gWater
end;
+function dplLess (a, b: TObject): Boolean;
+var
+ pa, pb: TPanel;
+begin
+ //result := ((a as TPanel).ArrIdx < (b as TPanel).ArrIdx);
+ pa := TPanel(a);
+ pb := TPanel(b);
+ if (pa.tag < pb.tag) then begin result := true; exit; end;
+ if (pa.tag > pb.tag) then begin result := false; exit; end;
+ result := (pa.ArrIdx < pb.ArrIdx);
+end;
+
+procedure dplClear ();
+begin
+ if (gDrawPanelList = nil) then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
+end;
+
+
type
TPanelID = record
PWhere: ^TPanelArray;
begin
result := false;
if (flesh = nil) then begin aabb := AABB2D.Create(0, 0, 0, 0); exit; end;
- pan := (flesh as TPanel);
+ //pan := (flesh as TPanel);
+ pan := TPanel(flesh);
aabb := AABB2D.Create(pan.X, pan.Y, pan.X+pan.Width, pan.Y+pan.Height);
if (pan.Width < 1) or (pan.Height < 1) then exit;
//if (pan.Width = 1) then aabb.maxX += 1;
mapX1: Integer = -$3fffffff;
mapY1: Integer = -$3fffffff;
- procedure fixMinMax (var panels: TPanelArray);
+ procedure calcBoundingBox (var panels: TPanelArray);
var
idx: Integer;
+ pan: TPanel;
begin
for idx := 0 to High(panels) do
begin
- if (panels[idx].Width < 1) or (panels[idx].Height < 1) then continue;
- if mapX0 > panels[idx].X then mapX0 := panels[idx].X;
- if mapY0 > panels[idx].Y then mapY0 := panels[idx].Y;
- if mapX1 < panels[idx].X+panels[idx].Width-1 then mapX1 := panels[idx].X+panels[idx].Width-1;
- if mapY1 < panels[idx].Y+panels[idx].Height-1 then mapY1 := panels[idx].Y+panels[idx].Height-1;
+ pan := panels[idx];
+ if not pan.visvalid then continue;
+ if (pan.Width < 1) or (pan.Height < 1) then continue;
+ if (mapX0 > pan.x0) then mapX0 := pan.x0;
+ if (mapY0 > pan.y0) then mapY0 := pan.y0;
+ if (mapX1 < pan.x1) then mapX1 := pan.x1;
+ if (mapY1 < pan.y1) then mapY1 := pan.y1;
end;
end;
procedure addPanelsToGrid (var panels: TPanelArray; tag: Integer);
var
idx: Integer;
+ pan: TPanel;
begin
tag := panelTypeToTag(tag);
for idx := High(panels) downto 0 do
begin
- panels[idx].tag := tag;
- gMapGrid.insertBody(panels[idx], panels[idx].X, panels[idx].Y, panels[idx].Width, panels[idx].Height, tag);
- mapTree.insertObject(panels[idx], tag, true); // as static object
+ pan := panels[idx];
+ 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
end;
end;
mapTree.Free();
mapTree := nil;
- fixMinMax(gWalls);
- fixMinMax(gRenderBackgrounds);
- fixMinMax(gRenderForegrounds);
- fixMinMax(gWater);
- fixMinMax(gAcid1);
- fixMinMax(gAcid2);
- fixMinMax(gSteps);
- fixMinMax(gLifts);
- fixMinMax(gBlockMon);
-
- if (mapX0 < 0) or (mapY0 < 0) then
- begin
- e_WriteLog(Format('funny map dimensions: (%d,%d)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1]), MSG_WARNING);
- //raise Exception.Create('we are fucked');
- end;
+ calcBoundingBox(gWalls);
+ calcBoundingBox(gRenderBackgrounds);
+ calcBoundingBox(gRenderForegrounds);
+ calcBoundingBox(gWater);
+ calcBoundingBox(gAcid1);
+ calcBoundingBox(gAcid2);
+ calcBoundingBox(gSteps);
+ calcBoundingBox(gLifts);
+ calcBoundingBox(gBlockMon);
+
+ e_WriteLog(Format('map dimensions: (%d,%d)-(%d,%d)', [mapX0, mapY0, mapX1, mapY1]), MSG_WARNING);
gMapGrid := TBodyGrid.Create(mapX0, mapY0, mapX1-mapX0+1, mapY1-mapY0+1);
mapTree := TDynAABBTreeMap.Create();
- addPanelsToGrid(gWalls, PANEL_WALL); // and PANEL_CLOSEDOOR
+ addPanelsToGrid(gWalls, PANEL_WALL);
+ addPanelsToGrid(gWalls, PANEL_CLOSEDOOR);
+ addPanelsToGrid(gWalls, PANEL_OPENDOOR);
addPanelsToGrid(gRenderBackgrounds, PANEL_BACK);
addPanelsToGrid(gRenderForegrounds, PANEL_FORE);
addPanelsToGrid(gWater, PANEL_WATER);
end;
-procedure g_Map_DrawPanelsOld(PanelType: Word);
+// old algo
+procedure g_Map_DrawPanels (PanelType: Word);
- procedure DrawPanels (stp: Integer; var panels: TPanelArray; drawDoors: Boolean=False);
+ procedure DrawPanels (var panels: TPanelArray; drawDoors: Boolean=False);
var
idx: Integer;
begin
- if (panels <> nil) and (stp >= 0) and (stp <= 6) then
+ if (panels <> nil) then
begin
// alas, no visible set
for idx := 0 to High(panels) do
begin
case PanelType of
- PANEL_WALL: DrawPanels(0, gWalls);
- PANEL_CLOSEDOOR: DrawPanels(0, gWalls, True);
- PANEL_BACK: DrawPanels(1, gRenderBackgrounds);
- PANEL_FORE: DrawPanels(2, gRenderForegrounds);
- PANEL_WATER: DrawPanels(3, gWater);
- PANEL_ACID1: DrawPanels(4, gAcid1);
- PANEL_ACID2: DrawPanels(5, gAcid2);
- PANEL_STEP: DrawPanels(6, gSteps);
+ PANEL_WALL: DrawPanels(gWalls);
+ PANEL_CLOSEDOOR: DrawPanels(gWalls, True);
+ PANEL_BACK: DrawPanels(gRenderBackgrounds);
+ PANEL_FORE: DrawPanels(gRenderForegrounds);
+ PANEL_WATER: DrawPanels(gWater);
+ PANEL_ACID1: DrawPanels(gAcid1);
+ PANEL_ACID2: DrawPanels(gAcid2);
+ PANEL_STEP: DrawPanels(gSteps);
end;
end;
-var
- gDrawPanelList: TBinaryHeapObj = nil;
-
-function dplLess (a, b: TObject): Boolean;
-begin
- result := ((a as TPanel).ArrIdx < (b as TPanel).ArrIdx);
-end;
-
-procedure dplClear ();
-begin
- if gDrawPanelList = nil then gDrawPanelList := TBinaryHeapObj.Create(@dplLess) else gDrawPanelList.clear();
-end;
-
-procedure dplAddPanel (pan: TPanel);
-begin
- if pan = nil then exit;
- gDrawPanelList.insert(pan);
-end;
-
-
-procedure g_Map_DrawPanels(x0, y0, wdt, hgt: Integer; PanelType: Word);
-var
- ptag: Integer;
-
- function checker (obj: TObject; tag: Integer): Boolean;
+// new algo
+procedure g_Map_CollectDrawPanels (x0, y0, wdt, hgt: Integer);
+ function checker (obj: TObject; ; var proxy: PBodyProxyRectag: Integer): Boolean;
var
pan: TPanel;
begin
result := false; // don't stop, ever
- //e_WriteLog(Format(' *body: tag:%d; ptag:%d; pantype=%d', [tag, ptag, PanelType]), MSG_NOTIFY);
- if (tag <> ptag) then exit;
-
- if obj = nil then begin e_WriteLog(Format(' !bodyFUUUUU0: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY); exit; end;
- if not (obj is TPanel) then begin e_WriteLog(Format(' !bodyFUUUUU1: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY); exit; end;
//pan := (obj as TPanel);
- //e_WriteLog(Format(' !body: (%d,%d)-(%dx%d) tag:%d; qtag:%d', [pan.X, pan.Y, pan.Width, pan.Height, tag, PanelType]), MSG_NOTIFY);
-
- pan := (obj as TPanel);
- if (PanelType = PANEL_CLOSEDOOR) then begin if not pan.Door then exit; end else begin if pan.Door then exit; end;
- //e_WriteLog(Format(' body hit: (%d,%d)-(%dx%d) tag: %d; qtag:%d', [pan.X, pan.Y, pan.Width, pan.Height, tag, PanelType]), MSG_NOTIFY);
- dplAddPanel(pan);
- end;
-
- procedure DrawPanels (stp: Integer; var panels: TPanelArray; drawDoors: Boolean=False);
- var
- idx: Integer;
- pan: TPanel;
- begin
- if (panels <> nil) and (stp >= 0) and (stp <= 6) then
- begin
- // alas, no visible set
- for idx := 0 to High(panels) do
- begin
- if not (drawDoors xor panels[idx].Door) then
- begin
- pan := panels[idx];
- {
- if (pan.Width < 1) or (pan.Height < 1) then continue;
- if (pan.X+pan.Width <= x0) or (pan.Y+pan.Height <= y0) then continue;
- if (pan.X >= x0+wdt) or (pan.Y >= y0+hgt) then continue;
- }
- pan.Draw();
- //e_WriteLog(Format(' *body hit: (%d,%d)-(%dx%d) tag: %d; qtag:%d', [pan.X, pan.Y, pan.Width, pan.Height, PanelType, PanelType]), MSG_NOTIFY);
- end;
- end;
- end;
+ pan := TPanel(obj);
+ //if (PanelType = PANEL_CLOSEDOOR) then begin if not pan.Door then exit; end else begin if pan.Door then exit; end;
+ if ((tag and GridTagDoor) <> 0) <> pan.Door then exit;
+ //dplAddPanel(pan);
+ gDrawPanelList.insert(pan);
end;
begin
- //g_Map_DrawPanelsOld(PanelType); exit;
- //e_WriteLog('==================', MSG_NOTIFY);
- //e_WriteLog(Format('***QQQ: qtag:%d', [PanelType]), MSG_NOTIFY);
dplClear();
- ptag := panelTypeToTag(PanelType);
+ //tagmask := panelTypeToTag(PanelType);
- if gdbg_map_use_accel_render then
+ if gdbg_map_use_tree_draw then
begin
- if gdbg_map_use_tree_draw then
- begin
- mapTree.aabbQuery(x0, y0, wdt, hgt, checker, ptag);
- end
- else
- begin
- gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, ptag);
- end;
- // sort and draw the list (we need to sort it, or rendering is fucked)
- while gDrawPanelList.count > 0 do
- begin
- (gDrawPanelList.front() as TPanel).Draw();
- gDrawPanelList.popFront();
- end;
+ mapTree.aabbQuery(x0, y0, wdt, hgt, checker, (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore));
end
else
begin
- //e_WriteLog(Format('+++QQQ: qtag:%d', [PanelType]), MSG_NOTIFY);
- case PanelType of
- PANEL_WALL: DrawPanels(0, gWalls);
- PANEL_CLOSEDOOR: DrawPanels(0, gWalls, True);
- PANEL_BACK: DrawPanels(1, gRenderBackgrounds);
- PANEL_FORE: DrawPanels(2, gRenderForegrounds);
- PANEL_WATER: DrawPanels(3, gWater);
- PANEL_ACID1: DrawPanels(4, gAcid1);
- PANEL_ACID2: DrawPanels(5, gAcid2);
- PANEL_STEP: DrawPanels(6, gSteps);
- end;
+ gMapGrid.forEachInAABB(x0, y0, wdt, hgt, checker, (GridTagBack or GridTagStep or GridTagWall or GridTagDoor or GridTagAcid1 or GridTagAcid2 or GridTagWater or GridTagFore));
end;
-
- //e_WriteLog('==================', MSG_NOTIFY);
+ // list will be rendered in `g_game.DrawPlayer()`
+ (*
+ while (gDrawPanelList.count > 0) do
+ begin
+ //(gDrawPanelList.front() as TPanel).Draw();
+ TPanel(gDrawPanelList.front()).Draw();
+ gDrawPanelList.popFront();
+ end;
+ *)
end;
procedure g_Map_DrawPanelShadowVolumes(lightX: Integer; lightY: Integer; radius: Integer);
- function checker (obj: TObject; tag: Integer): Boolean;
+ function checker (obj: TObject; ; var proxy: PBodyProxyRectag: Integer): Boolean;
var
pan: TPanel;
begin
result := false; // don't stop, ever
- if (tag <> GridTagWallDoor) then exit; // only walls
- pan := (obj as TPanel);
+ //if (tag <> GridTagWall) and (tag <> GridTagDoor) then exit; // only walls
+ //pan := (obj as TPanel);
+ pan := TPanel(obj);
pan.DrawShadowVolume(lightX, lightY, radius);
end;
begin
if gdbg_map_use_tree_draw then
begin
- mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checker, GridTagWallDoor);
+ mapTree.aabbQuery(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
end
else
begin
- gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, GridTagWallDoor);
+ gMapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, checker, (GridTagWall or GridTagDoor));
end;
end;
function g_Map_CollidePanel(X, Y: Integer; Width, Height: Word; PanelType: Word; b1x3: Boolean): Boolean;
- function checker (obj: TObject; tag: Integer): Boolean;
+ function checker (obj: TObject; ; var proxy: PBodyProxyRectag: Integer): Boolean;
var
pan: TPanel;
- a: Integer;
begin
result := false; // don't stop, ever
- //e_WriteLog(Format(' *body: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY);
-
- if obj = nil then
+ if ((tag and GridTagLift) <> 0) then
begin
- e_WriteLog(Format(' !bodyFUUUUU0: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY);
- end;
- if not (obj is TPanel) then
- begin
- e_WriteLog(Format(' !bodyFUUUUU1: tag:%d; qtag:%d', [tag, PanelType]), MSG_NOTIFY);
- exit;
- end;
-
- pan := (obj as TPanel);
- a := pan.ArrIdx;
-
- if WordBool(PanelType and PANEL_WALL) and (tag = GridTagWallDoor) then
- begin
- if gWalls[a].Enabled and g_Collide(X, Y, Width, Height, gWalls[a].X, gWalls[a].Y, gWalls[a].Width, gWalls[a].Height) then
+ pan := TPanel(obj);
+ if ((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) then
begin
result := true;
exit;
end;
end;
- if WordBool(PanelType and PANEL_WATER) and (tag = GridTagWater) then
- begin
- if g_Collide(X, Y, Width, Height, gWater[a].X, gWater[a].Y, gWater[a].Width, gWater[a].Height) then
- begin
- result := True;
- exit;
- end;
- end;
-
- if WordBool(PanelType and PANEL_ACID1) and (tag = GridTagAcid1) then
- begin
- if g_Collide(X, Y, Width, Height, gAcid1[a].X, gAcid1[a].Y, gAcid1[a].Width, gAcid1[a].Height) then
- begin
- result := True;
- exit;
- end;
- end;
-
- if WordBool(PanelType and PANEL_ACID2) and (tag = GridTagAcid2) then
+ if ((pan.tag and GridTagBlockMon) <> 0) then
begin
- if g_Collide(X, Y, Width, Height, gAcid2[a].X, gAcid2[a].Y, gAcid2[a].Width, gAcid2[a].Height) then
+ if ((not b1x3) or (pan.Width+pan.Height >= 64)) and g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height) then
begin
result := True;
exit;
end;
end;
- if WordBool(PanelType and PANEL_STEP) and (tag = GridTagStep) then
- begin
- if g_Collide(X, Y, Width, Height, gSteps[a].X, gSteps[a].Y, gSteps[a].Width, gSteps[a].Height) then
- begin
- result := True;
- exit;
- end;
- end;
-
- if WordBool(PanelType and (PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)) and (tag = GridTagLift) then
- begin
- if ((WordBool(PanelType and (PANEL_LIFTUP)) and (gLifts[a].LiftType = 0)) or
- (WordBool(PanelType and (PANEL_LIFTDOWN)) and (gLifts[a].LiftType = 1)) or
- (WordBool(PanelType and (PANEL_LIFTLEFT)) and (gLifts[a].LiftType = 2)) or
- (WordBool(PanelType and (PANEL_LIFTRIGHT)) and (gLifts[a].LiftType = 3))) and
- g_Collide(X, Y, Width, Height, gLifts[a].X, gLifts[a].Y, gLifts[a].Width, gLifts[a].Height) then
- begin
- result := true;
- exit;
- end;
- end;
-
- if WordBool(PanelType and PANEL_BLOCKMON) and (tag = GridTagBlockMon) then
- begin
- if ((not b1x3) or ((gBlockMon[a].Width + gBlockMon[a].Height) >= 64)) and
- g_Collide(X, Y, Width, Height, gBlockMon[a].X, gBlockMon[a].Y, gBlockMon[a].Width, gBlockMon[a].Height) then
- begin
- result := True;
- exit;
- end;
- end;
+ // other shit
+ result := g_Collide(X, Y, Width, Height, pan.X, pan.Y, pan.Width, pan.Height);
end;
+var
+ tagmask: Integer = 0;
begin
//TODO: detailed profile
+ if WordBool(PanelType and PANEL_WALL) 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 begin result := false; exit; end; // just in case
+
if (profMapCollision <> nil) then profMapCollision.sectionBeginAccum('wall coldet');
if gdbg_map_use_accel_coldet then
begin
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, (GridTagWallDoor or GridTagWater or GridTagAcid1 or GridTagAcid2 or GridTagStep or GridTagLift or GridTagBlockMon)) <> nil);
+ result := (mapTree.aabbQuery(X, Y, Width, Height, checker, tagmask) <> nil);
if (gdbg_map_dump_coldet_tree_queries) and (mapTree.nodesVisited <> 0) then
begin
//e_WriteLog(Format('map collision: %d nodes visited (%d deep)', [mapTree.nodesVisited, mapTree.nodesDeepVisited]), MSG_NOTIFY);
end
else
begin
- result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker, (GridTagWallDoor or GridTagWater or GridTagAcid1 or GridTagAcid2 or GridTagStep or GridTagLift or GridTagBlockMon));
+ result := gMapGrid.forEachInAABB(X, Y, Width, Height, checker, tagmask);
end;
end
else
function checker (obj: TObject; tag: Integer): Boolean;
var
pan: TPanel;
- a: Integer;
begin
result := false; // don't stop, ever
- if (tag <> GridTagWater) and (tag <> GridTagAcid1) and (tag <> GridTagAcid2) then exit;
- pan := (obj as TPanel);
- a := pan.ArrIdx;
- // water
- if (tag = GridTagWater) then
- begin
- if g_Collide(X, Y, Width, Height, gWater[a].X, gWater[a].Y, gWater[a].Width, gWater[a].Height) then
- begin
- result := true; // water has highest priority, so stop right here
- texid := gWater[a].GetTextureID();
- exit;
- end;
- end;
- // acid1
- if (cctype > 1) and (tag = GridTagAcid1) then
- begin
- if g_Collide(X, Y, Width, Height, gAcid1[a].X, gAcid1[a].Y, gAcid1[a].Width, gAcid1[a].Height) then
- begin
- cctype := 1;
- texid := gAcid1[a].GetTextureID();
- exit;
- end;
+ if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2)) = 0) then exit;
+ //pan := (obj as TPanel);
+ pan := TPanel(obj);
+ // check priorities
+ case cctype of
+ 0: if ((tag and GridTagWater) = 0) then exit; // only water
+ 1: if ((tag and (GridTagWater or GridTagAcid1)) = 0) then exit; // water, acid1
+ //2: if ((tag and (GridTagWater or GridTagAcid1 or GridTagAcid2) = 0) then exit; // water, acid1, acid2
end;
+ // collision?
+ 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
+ if ((tag and GridTagWater) <> 0) then begin cctype := 0; result := true; exit; end;
// acid2
- if (cctype > 2) and (tag = GridTagAcid2) then
- begin
- if g_Collide(X, Y, Width, Height, gAcid2[a].X, gAcid2[a].Y, gAcid2[a].Width, gAcid2[a].Height) then
- begin
- cctype := 2;
- texid := gAcid2[a].GetTextureID();
- exit;
- end;
- end;
+ if ((tag and GridTagAcid2) <> 0) then cctype := 2;
+ // acid1
+ if ((tag and GridTagAcid1) <> 0) then cctype := 1;
end;
begin
diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas
index 39237f182d1a692e481043dc90640dba4624e169..ab996040406168f29ced2f9c131f576d080b86fd 100644 (file)
--- a/src/game/g_panel.pas
+++ b/src/game/g_panel.pas
True: (AnTex: TAnimation);
end;
+ private
+ function getx1 (): Integer; inline;
+ function gety1 (): Integer; inline;
+ function getvisvalid (): Boolean; inline;
+
public
FCurTexture: Integer; // Íîìåð òåêóùåé òåêñòóðû
FCurFrame: Integer;
procedure SaveState(var Mem: TBinMemoryWriter);
procedure LoadState(var Mem: TBinMemoryReader);
+
+ property x0: Integer read X;
+ property y0: Integer read Y;
+ property x1: Integer read getx1; // inclusive!
+ property y1: Integer read gety1; // inclusive!
+ property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive
end;
PPanel = ^TPanel;
Inherited;
end;
+function TPanel.getx1 (): Integer; inline; begin result := X+Width-1; end;
+function TPanel.gety1 (): Integer; inline; begin result := Y+Height-1; end;
+function TPanel.getvisvalid (): Boolean; inline; begin result := (Width > 0) and (Height > 0); end;
+
procedure TPanel.Draw();
var
xx, yy: Integer;