-
Notifications
You must be signed in to change notification settings - Fork 4
/
flood.pas
164 lines (144 loc) · 3.44 KB
/
flood.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
unit flood;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,rmcore;
procedure ScanFill(x, y, width, height, newColor : integer);
procedure ReplaceAllFill(x, y, MaxX,MaxY,color : integer);
implementation
const
MaxQueueSize = 100;
Type
TFPoint = record
x,y : integer;
end;
TPixelQueue = Class
Count : integer;
PointList : array[1..MaxQueueSize] of TFPoint;
constructor Create;
procedure push(var pt : TFPoint);
procedure popfirst(var pt : TFPoint);
procedure pop(var pt : TFPoint);
function GetCount : integer;
end;
constructor TPixelQueue.Create;
begin
count:=0;
end;
procedure TPixelQueue.push(var pt : TFPoint);
begin
if (count+1) > MaxQueueSize then exit;
if (pt.x < 0) or (pt.y<0) then exit;
inc(count);
PointList[count]:=pt;
end;
procedure TPixelQueue.popfirst(var pt : TFPoint);
var
i : integer;
begin
if count > 0 then
begin
pt:=PointList[1];
dec(count);
for i:=1 to count do
begin
PointList[i]:=PointList[i+1];
end;
end;
end;
procedure TPixelQueue.pop(var pt : TFPoint);
begin
if count > 0 then
begin
pt:=PointList[count];
dec(count);
end;
end;
function TPixelQueue.GetCount : integer;
begin
GetCount:=count;
end;
function GetPix(x,y : integer) : integer;
begin
// if (x<0) or (y<0) or (x>RMCoreBase.GetWidth-1) or (y>RMCoreBase.GetHeight-1) then
// result:=-1
// else
result:=RMCoreBase.GetPixel(x,y);
end;
procedure PutPix(x,y,color : integer);
begin
if (x<0) or (y<0) or (x>RMCoreBase.GetWidth-1) or (y>RMCoreBase.GetHeight-1) then exit;
RMCoreBase.PutPixel(x,y,color);
end;
procedure ScanFill(x, y, width, height, newColor : integer);
var
x1 : integer;
spanAbove, spanBelow : boolean;
PQ : TPixelQueue;
temp : TFPoint;
oldColor : integer;
begin
if GetPix(x,y) = newColor then exit;
oldColor:=GetPix(x,y);
PQ:=TPixelQueue.Create;
temp.x:=x;
temp.y:=y;
PQ.push(temp);
while PQ.GetCount>0 do
begin
PQ.popfirst(temp);
x:=temp.x;
y:=temp.y;
x1 := x;
while ((x1 >= 0) and (GetPix(x1,y) = oldColor)) do
begin
x1:=x1-1;
end;
x1:=x1+1;
spanAbove := false;
spanBelow := false;
while((x1 < width) and (GetPix(x1,y) = oldColor)) do
begin
PutPix( x1,y, newColor);
if((NOT spanAbove) and (y > 0) and (GetPix(x1,(y - 1) ) = oldColor)) then
begin
temp.x:=x1;
temp.y:=y-1;
PQ.push(temp);
spanAbove := true;
end
else if (spanAbove and (y > 0) and (GetPix(x1,(y - 1)) <> oldColor)) then
begin
spanAbove := false;
end;
if ((NOT spanBelow) and (y < height - 1) and (GetPix(x1,(y + 1)) = oldColor)) then
begin
temp.x:=x1;
temp.y:=y+1;
PQ.push(temp);
spanBelow := true;
end
else if(spanBelow and (y < height - 1) and (GetPix(x1,(y + 1)) <> oldColor)) then
begin
spanBelow := false;
end;
x1:=x1+1;
end;
end;
end;
//replaces all occurances in Map of selected Tile - like flood fill but for all - does not need to be connected - mainly to be used for missing tiles
procedure ReplaceAllFill(x, y, MaxX,MaxY,color : integer);
var
i,j,ReplaceColor : integer;
begin
if GetPix(x,y) = color then exit;
ReplaceColor:=GetPix(x,y);
for j:=0 to MaxY-1 do
begin
for i:=0 to MaxX-1 do
begin
if GetPix(i,j) = ReplaceColor then PutPix( i,j, color);
end;
end;
end;
end.