- Merged TTileList into TScreenBuffer
- Added shortcuts to TScreenBuffer to speed up the InsertionSort - Renamed TScreenBuffer.Store to TScreenBuffer.Insert - Added TScreenBuffer.Add to append to the list - Added TScreenBuffer.Sort to sort the list using MergeSort - Changed TLandscape.FillDrawList to just append to the list and sort afterwards - Added screen buffer invalidation on TfrmMain.OnLandscapeChanged
This commit is contained in:
parent
0d6c151c5f
commit
7fdfd1ee23
|
@ -166,37 +166,28 @@ type
|
||||||
Next: PBlockInfo;
|
Next: PBlockInfo;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTileList }
|
{ TScreenBuffer }
|
||||||
|
|
||||||
TTileList = class(TObject)
|
TScreenBuffer = class(TObject)
|
||||||
constructor Create; virtual;
|
constructor Create; virtual;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
protected
|
|
||||||
{ Fields }
|
|
||||||
FFirst: PBlockInfo;
|
|
||||||
FLastBlock: PBlockInfo;
|
|
||||||
public
|
|
||||||
{ Methods }
|
|
||||||
procedure Clear; virtual;
|
|
||||||
function Iterate(var ABlockInfo: PBlockInfo): Boolean; virtual;
|
|
||||||
procedure Add(AItem: TWorldItem); virtual;
|
|
||||||
procedure Delete(AItem: TWorldItem); virtual;
|
|
||||||
property LastBlock: PBlockInfo read FLastBlock;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TScreenBuffer }
|
|
||||||
|
|
||||||
TScreenBuffer = class(TTileList)
|
|
||||||
constructor Create; override;
|
|
||||||
protected
|
protected
|
||||||
{ Members }
|
{ Members }
|
||||||
|
FCount: Cardinal;
|
||||||
|
FShortCuts: array[-1..10] of PBlockInfo; //-1 = last, 0 = first, 1..10 = other shortcuts
|
||||||
|
FShortCutsValid: Boolean;
|
||||||
FSerial: Cardinal;
|
FSerial: Cardinal;
|
||||||
public
|
public
|
||||||
{ Methods }
|
{ Methods }
|
||||||
procedure Clear; override;
|
function Add(AItem: TWorldItem): PBlockInfo;
|
||||||
|
procedure Clear;
|
||||||
|
procedure Delete(AItem: TWorldItem);
|
||||||
function Find(AScreenPosition: TPoint): PBlockInfo;
|
function Find(AScreenPosition: TPoint): PBlockInfo;
|
||||||
function GetSerial: Cardinal;
|
function GetSerial: Cardinal;
|
||||||
function Store(AItem: TWorldItem): PBlockInfo;
|
function Iterate(var ABlockInfo: PBlockInfo): Boolean;
|
||||||
|
function Insert(AItem: TWorldItem): PBlockInfo;
|
||||||
|
procedure Sort;
|
||||||
|
procedure UpdateShortcuts;
|
||||||
{ Events }
|
{ Events }
|
||||||
procedure OnTileRemoved(ATile: TMulBlock);
|
procedure OnTileRemoved(ATile: TMulBlock);
|
||||||
end;
|
end;
|
||||||
|
@ -704,6 +695,7 @@ var
|
||||||
i, x, y: Integer;
|
i, x, y: Integer;
|
||||||
begin
|
begin
|
||||||
for x := AX to AX + AWidth do
|
for x := AX to AX + AWidth do
|
||||||
|
begin
|
||||||
for y := AY to AY + AWidth do
|
for y := AY to AY + AWidth do
|
||||||
begin
|
begin
|
||||||
if AMap then
|
if AMap then
|
||||||
|
@ -717,7 +709,7 @@ begin
|
||||||
drawMapCell.Priority := GetEffectiveAltitude(drawMapCell);
|
drawMapCell.Priority := GetEffectiveAltitude(drawMapCell);
|
||||||
drawMapCell.PriorityBonus := 0;
|
drawMapCell.PriorityBonus := 0;
|
||||||
drawMapCell.PrioritySolver := 0;
|
drawMapCell.PrioritySolver := 0;
|
||||||
ADrawList.Store(drawMapCell);
|
ADrawList.Add(drawMapCell);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -732,10 +724,12 @@ begin
|
||||||
((AStaticsFilter = nil) or AStaticsFilter(TStaticItem(drawStatics[i]))) then
|
((AStaticsFilter = nil) or AStaticsFilter(TStaticItem(drawStatics[i]))) then
|
||||||
begin
|
begin
|
||||||
UpdateStaticsPriority(TStaticItem(drawStatics[i]), ADrawList.GetSerial);
|
UpdateStaticsPriority(TStaticItem(drawStatics[i]), ADrawList.GetSerial);
|
||||||
ADrawList.Store(TWorldItem(drawStatics[i]));
|
ADrawList.Add(TWorldItem(drawStatics[i]));
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
ADrawList.Sort;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TLandscape.GetEffectiveAltitude(ATile: TMapCell): ShortInt;
|
function TLandscape.GetEffectiveAltitude(ATile: TMapCell): ShortInt;
|
||||||
|
@ -974,96 +968,52 @@ begin
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTileList }
|
|
||||||
|
|
||||||
constructor TTileList.Create;
|
|
||||||
begin
|
|
||||||
inherited Create;
|
|
||||||
FFirst := nil;
|
|
||||||
FLastBlock := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TTileList.Destroy;
|
|
||||||
begin
|
|
||||||
Clear;
|
|
||||||
inherited Destroy;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TTileList.Clear;
|
|
||||||
var
|
|
||||||
current, next: PBlockInfo;
|
|
||||||
begin
|
|
||||||
current := FFirst;
|
|
||||||
while current <> nil do
|
|
||||||
begin
|
|
||||||
next := current^.Next;
|
|
||||||
Dispose(current);
|
|
||||||
current := next;
|
|
||||||
end;
|
|
||||||
FFirst := nil;
|
|
||||||
FLastBlock := nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TTileList.Iterate(var ABlockInfo: PBlockInfo): Boolean;
|
|
||||||
begin
|
|
||||||
if ABlockInfo = nil then
|
|
||||||
ABlockInfo := FFirst
|
|
||||||
else
|
|
||||||
ABlockInfo := ABlockInfo^.Next;
|
|
||||||
Result := ABlockInfo <> nil;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TTileList.Add(AItem: TWorldItem);
|
|
||||||
var
|
|
||||||
current: PBlockInfo;
|
|
||||||
begin
|
|
||||||
New(current);
|
|
||||||
current^.Item := AItem;
|
|
||||||
current^.Next := nil;
|
|
||||||
if FFirst = nil then FFirst := current;
|
|
||||||
if FLastBlock <> nil then FLastBlock^.Next := current;
|
|
||||||
FLastBlock := current;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TTileList.Delete(AItem: TWorldItem);
|
|
||||||
var
|
|
||||||
current, last, next: PBlockInfo;
|
|
||||||
begin
|
|
||||||
last := nil;
|
|
||||||
current := FFirst;
|
|
||||||
while current <> nil do
|
|
||||||
begin
|
|
||||||
if current^.Item = AItem then
|
|
||||||
begin
|
|
||||||
if FFirst = current then FFirst := current^.Next;
|
|
||||||
if FLastBlock = current then FLastBlock := last;
|
|
||||||
if last <> nil then last^.Next := current^.Next;
|
|
||||||
|
|
||||||
if current^.Normals <> nil then Dispose(current^.Normals);
|
|
||||||
|
|
||||||
Dispose(current);
|
|
||||||
next := nil;
|
|
||||||
end else
|
|
||||||
next := current^.Next;
|
|
||||||
|
|
||||||
last := current;
|
|
||||||
current := next;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TScreenBuffer }
|
{ TScreenBuffer }
|
||||||
|
|
||||||
constructor TScreenBuffer.Create;
|
constructor TScreenBuffer.Create;
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
|
FCount := 0;
|
||||||
FSerial := 0;
|
FSerial := 0;
|
||||||
|
UpdateShortcuts;
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TScreenBuffer.Destroy;
|
||||||
|
begin
|
||||||
|
Clear;
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TScreenBuffer.Add(AItem: TWorldItem): PBlockInfo;
|
||||||
|
begin
|
||||||
|
New(Result);
|
||||||
|
AItem.Locked := True;
|
||||||
|
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
|
||||||
|
Result^.Item := AItem;
|
||||||
|
Result^.HighRes := nil;
|
||||||
|
Result^.LowRes := nil;
|
||||||
|
Result^.Normals := nil;
|
||||||
|
Result^.State := ssNormal;
|
||||||
|
Result^.Next := nil;
|
||||||
|
|
||||||
|
if FShortCuts[0] = nil then //First element
|
||||||
|
begin
|
||||||
|
FShortCuts[0] := Result;
|
||||||
|
FShortCuts[-1] := Result; //Last element
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
FShortCuts[-1]^.Next := Result;
|
||||||
|
FShortCuts[-1] := Result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Inc(FCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScreenBuffer.Clear;
|
procedure TScreenBuffer.Clear;
|
||||||
var
|
var
|
||||||
current, next: PBlockInfo;
|
current, next: PBlockInfo;
|
||||||
begin
|
begin
|
||||||
current := FFirst;
|
current := FShortCuts[0];
|
||||||
while current <> nil do
|
while current <> nil do
|
||||||
begin
|
begin
|
||||||
next := current^.Next;
|
next := current^.Next;
|
||||||
|
@ -1073,10 +1023,41 @@ begin
|
||||||
Dispose(current);
|
Dispose(current);
|
||||||
current := next;
|
current := next;
|
||||||
end;
|
end;
|
||||||
FFirst := nil;
|
FShortCuts[0] := nil;
|
||||||
FLastBlock := nil;
|
FShortCuts[-1] := nil;
|
||||||
|
|
||||||
|
FCount := 0;
|
||||||
FSerial := 0;
|
FSerial := 0;
|
||||||
|
|
||||||
|
UpdateShortcuts;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TScreenBuffer.Delete(AItem: TWorldItem);
|
||||||
|
var
|
||||||
|
current, last, next: PBlockInfo;
|
||||||
|
begin
|
||||||
|
last := nil;
|
||||||
|
current := FShortCuts[0];
|
||||||
|
while current <> nil do
|
||||||
|
begin
|
||||||
|
if current^.Item = AItem then
|
||||||
|
begin
|
||||||
|
if FShortCuts[-1] = current then FShortCuts[-1] := last;
|
||||||
|
if FShortCuts[0] = current then FShortCuts[0] := current^.Next;
|
||||||
|
if last <> nil then last^.Next := current^.Next;
|
||||||
|
|
||||||
|
if current^.Normals <> nil then Dispose(current^.Normals);
|
||||||
|
|
||||||
|
Dispose(current);
|
||||||
|
Dec(FCount);
|
||||||
|
FShortCutsValid := False;
|
||||||
|
next := nil;
|
||||||
|
end else
|
||||||
|
next := current^.Next;
|
||||||
|
|
||||||
|
last := current;
|
||||||
|
current := next;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TScreenBuffer.Find(AScreenPosition: TPoint): PBlockInfo;
|
function TScreenBuffer.Find(AScreenPosition: TPoint): PBlockInfo;
|
||||||
|
@ -1084,7 +1065,7 @@ var
|
||||||
current: PBlockInfo;
|
current: PBlockInfo;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := nil;
|
||||||
current := FFirst;
|
current := FShortCuts[0];
|
||||||
while (current <> nil) and (Result = nil) do
|
while (current <> nil) and (Result = nil) do
|
||||||
begin
|
begin
|
||||||
if (current^.State = ssNormal) and
|
if (current^.State = ssNormal) and
|
||||||
|
@ -1104,10 +1085,23 @@ begin
|
||||||
Inc(FSerial);
|
Inc(FSerial);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TScreenBuffer.Store(AItem: TWorldItem): PBlockInfo;
|
function TScreenBuffer.Iterate(var ABlockInfo: PBlockInfo): Boolean;
|
||||||
|
begin
|
||||||
|
if ABlockInfo = nil then
|
||||||
|
ABlockInfo := FShortCuts[0]
|
||||||
|
else
|
||||||
|
ABlockInfo := ABlockInfo^.Next;
|
||||||
|
Result := ABlockInfo <> nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TScreenBuffer.Insert(AItem: TWorldItem): PBlockInfo;
|
||||||
var
|
var
|
||||||
current: PBlockInfo;
|
current: PBlockInfo;
|
||||||
|
shortcut: Integer;
|
||||||
begin
|
begin
|
||||||
|
if not FShortCutsValid then
|
||||||
|
UpdateShortcuts;
|
||||||
|
|
||||||
New(Result);
|
New(Result);
|
||||||
AItem.Locked := True;
|
AItem.Locked := True;
|
||||||
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
|
AItem.OnDestroy.RegisterEvent(@OnTileRemoved);
|
||||||
|
@ -1117,27 +1111,118 @@ begin
|
||||||
Result^.Normals := nil;
|
Result^.Normals := nil;
|
||||||
Result^.State := ssNormal;
|
Result^.State := ssNormal;
|
||||||
|
|
||||||
if (FFirst = nil) or (CompareWorldItems(AItem, FFirst) > 0) then
|
if (FShortCuts[0] = nil) or (CompareWorldItems(AItem, FShortCuts[0]) > 0) then
|
||||||
begin
|
begin
|
||||||
Result^.Next := FFirst;
|
//TODO : update last element if necessary
|
||||||
if FFirst = nil then
|
Result^.Next := FShortCuts[0];
|
||||||
FLastBlock := Result;
|
FShortCuts[0] := Result;
|
||||||
FFirst := Result;
|
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
current := FFirst;
|
//find best entry point
|
||||||
|
shortcut := 0;
|
||||||
|
while (shortcut <= 10) and (FShortCuts[shortcut] <> nil) and
|
||||||
|
(CompareWorldItems(AItem, FShortCuts[shortcut]) <= 0) do
|
||||||
|
begin
|
||||||
|
current := FShortCuts[shortcut];
|
||||||
|
Inc(shortcut);
|
||||||
|
end;
|
||||||
|
|
||||||
|
//now find the real match
|
||||||
while (current^.Next <> nil) and
|
while (current^.Next <> nil) and
|
||||||
(CompareWorldItems(AItem, current^.Next^.Item) > 0) do
|
(CompareWorldItems(AItem, current^.Next^.Item) > 0) do
|
||||||
begin
|
begin
|
||||||
current := current^.Next;
|
current := current^.Next;
|
||||||
end;
|
end;
|
||||||
|
//TODO : update last element if necessary
|
||||||
if current^.Next = nil then
|
|
||||||
FLastBlock := Result;
|
|
||||||
|
|
||||||
Result^.Next := current^.Next;
|
Result^.Next := current^.Next;
|
||||||
current^.Next := Result;
|
current^.Next := Result;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Inc(FCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
//Mergesort
|
||||||
|
procedure TScreenBuffer.Sort;
|
||||||
|
|
||||||
|
function Merge(AHead1, AHead2: PBlockInfo): PBlockInfo;
|
||||||
|
begin
|
||||||
|
if AHead1 = nil then
|
||||||
|
Exit(AHead2);
|
||||||
|
|
||||||
|
if AHead2 = nil then
|
||||||
|
Exit(AHead1);
|
||||||
|
|
||||||
|
if CompareWorldItems(AHead1^.Item, AHead2^.Item) < 0 then
|
||||||
|
begin
|
||||||
|
Result := AHead1;
|
||||||
|
Result^.Next := Merge(Result^.Next, AHead2);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
Result := AHead2;
|
||||||
|
Result^.Next := Merge(AHead1, Result^.Next);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function MergeSort(AHead: PBlockInfo): PBlockInfo;
|
||||||
|
var
|
||||||
|
head1, head2: PBlockInfo;
|
||||||
|
begin
|
||||||
|
if (AHead <> nil) and (AHead^.Next <> nil) then
|
||||||
|
begin
|
||||||
|
head1 := AHead;
|
||||||
|
head2 := AHead^.Next;
|
||||||
|
while (head2 <> nil) and (head2^.Next <> nil) do
|
||||||
|
begin
|
||||||
|
AHead := AHead^.Next;
|
||||||
|
head2 := AHead^.Next^.Next;
|
||||||
|
end;
|
||||||
|
head2 := AHead^.Next;
|
||||||
|
AHead^.Next := nil;
|
||||||
|
|
||||||
|
Result := Merge(MergeSort(head1), MergeSort(head2));
|
||||||
|
end else
|
||||||
|
Result := AHead;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if FShortCuts[0] <> nil then
|
||||||
|
FShortCuts[0] := MergeSort(FShortCuts[0]);
|
||||||
|
UpdateShortcuts;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TScreenBuffer.UpdateShortcuts;
|
||||||
|
var
|
||||||
|
shortcut, step, nextStep, stepSize: Integer;
|
||||||
|
blockInfo: PBlockInfo;
|
||||||
|
begin
|
||||||
|
if FCount < 10 then
|
||||||
|
begin
|
||||||
|
for shortcut := 1 to 10 do
|
||||||
|
FShortCuts[shortcut] := nil;
|
||||||
|
end
|
||||||
|
else if FShortCuts[0] <> nil then
|
||||||
|
begin
|
||||||
|
stepSize := FCount div 10;
|
||||||
|
nextStep := stepSize;
|
||||||
|
step := 0;
|
||||||
|
shortcut := 1;
|
||||||
|
blockInfo := FShortCuts[0];
|
||||||
|
repeat
|
||||||
|
if step = nextStep then
|
||||||
|
begin
|
||||||
|
FShortCuts[shortcut] := blockInfo;
|
||||||
|
Inc(shortcut);
|
||||||
|
Inc(nextStep, stepSize);
|
||||||
|
end;
|
||||||
|
|
||||||
|
Inc(step);
|
||||||
|
|
||||||
|
FShortCuts[-1] := blockInfo; //update last known item
|
||||||
|
blockInfo := blockInfo^.Next;
|
||||||
|
until (blockInfo = nil);
|
||||||
|
end;
|
||||||
|
FShortCutsValid := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TScreenBuffer.OnTileRemoved(ATile: TMulBlock);
|
procedure TScreenBuffer.OnTileRemoved(ATile: TMulBlock);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
object frmMain: TfrmMain
|
object frmMain: TfrmMain
|
||||||
Left = 232
|
Left = 229
|
||||||
Height = 603
|
Height = 603
|
||||||
Top = 126
|
Top = 126
|
||||||
Width = 766
|
Width = 766
|
||||||
|
@ -1076,7 +1076,7 @@ object frmMain: TfrmMain
|
||||||
object MainMenu1: TMainMenu
|
object MainMenu1: TMainMenu
|
||||||
Images = ImageList1
|
Images = ImageList1
|
||||||
left = 232
|
left = 232
|
||||||
top = 32
|
top = 33
|
||||||
object mnuCentrED: TMenuItem
|
object mnuCentrED: TMenuItem
|
||||||
Caption = '&CentrED'
|
Caption = '&CentrED'
|
||||||
object mnuDisconnect: TMenuItem
|
object mnuDisconnect: TMenuItem
|
||||||
|
|
|
@ -838,6 +838,7 @@ begin
|
||||||
oglGameWindow.Repaint;
|
oglGameWindow.Repaint;
|
||||||
FLastDraw := Now;
|
FLastDraw := Now;
|
||||||
end;
|
end;
|
||||||
|
Done := False;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TfrmMain.btnAddLocationClick(Sender: TObject);
|
procedure TfrmMain.btnAddLocationClick(Sender: TObject);
|
||||||
|
@ -1540,7 +1541,6 @@ begin
|
||||||
edY.Value := FY;
|
edY.Value := FY;
|
||||||
dmNetwork.Send(TUpdateClientPosPacket.Create(AX, AY));
|
dmNetwork.Send(TUpdateClientPosPacket.Create(AX, AY));
|
||||||
InvalidateScreenBuffer;
|
InvalidateScreenBuffer;
|
||||||
Repaint;
|
|
||||||
if frmRadarMap <> nil then frmRadarMap.Repaint;
|
if frmRadarMap <> nil then frmRadarMap.Repaint;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -1921,6 +1921,7 @@ end;
|
||||||
|
|
||||||
procedure TfrmMain.OnLandscapeChanged;
|
procedure TfrmMain.OnLandscapeChanged;
|
||||||
begin
|
begin
|
||||||
|
InvalidateScreenBuffer;
|
||||||
oglGameWindow.Repaint;
|
oglGameWindow.Repaint;
|
||||||
UpdateCurrentTile;
|
UpdateCurrentTile;
|
||||||
end;
|
end;
|
||||||
|
@ -2155,6 +2156,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
FScreenBuffer.UpdateShortcuts;
|
||||||
FScreenBufferValid := True;
|
FScreenBufferValid := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue