PDA

View Full Version : AutoColoring for intermediates



nielsie95
05-04-2007, 04:25 PM
Hello and welcome to the tutorial:


Autocoloring for intermediates




With this tutorial you will hopefully learn how you automaticly get a color! :)

Chapters

SRL Autocoloring
Bitmaps
BruteForce
Unique facts






SRL AutoColoring

This is the most simple way to automaticly get a color for your script. I made you a list of all the functions. The names pretty much explain what they are for. The red colors are the map in where they can be found.

/core/AutoColor.scar
FindWaterColor
FindRoadColor
FindFallyRoadColor
FindRockColor
FindDirtRoadColor
FindBridgeColor
FindLadderColor

/core/DoorProfiles.scar
GetDoorColor;


Place specified:
/misc/DraynorColorFinder.scar
/misc/FaladorColorFinder.scar
/misc/MiscellaneousColorFinder.scar
/misc/VarrockWestColorFinder.scar


How to use:
This is how you use the SRL autocolor functions in your script:


procedure WalkToWater;
var Water: integer; //All colors are integers!
begin
Water := FindWaterColor; //Now the variable water contains the WaterColor
if FindColorSpiral(x, y, Water, MMX1, MMY1, MMX2, MMY2) then //You DONT need tolerance if you've autocolored a color.
Mouse(x, y, 1, 1, True);
Flag;
end;








Bitmaps

Another way that's used a lot is using Bitmaps.
With this way you make a little bitmap and look for it. If the bitmap is found it will get the color from the TOP-LEFT corner of the bitmap. So make sure that the top-left of your bitmap contains the color you want.
Also make sure you dont use too big bitmaps, slices of 2*15 are most of the time more then enough.
SRL has also for bitmaps a nice autocolor function: AutoColorThis.


How to use:

Before you can find the bitmap, you have to declare the bitmap somewhere in your script or procedure!


procedure FindDockColor;
var DockColor, TheBitmap, MaxTolerance: integer;
begin
TheBitmap := BitmapFromString(33, 2, 'z78DA33713436333433192507' +
'01090001FF53CB'); //Declare the bitmap first!
MaxTolerance := 40;
DockColor := AutoColorThis(TheBitmap, MaxTolerance, MMX1, MMY1, MMX2, MMY2); //40 is the Maximal tolerance that can be used to find your bitmap.
WriteLn('DockColor: '+IntToStr(DockColor));
FreeBitmap(TheBitmap); /Be sure to release a bmp after use =]
end;







Bruteforce

Bruteforce is a hard way to autocolor. In this way all the colors on the minimap are being compared to set values. Most of the time these values are RGB (SRL autocoloring is based on this). What you need to do is: get a lot of colors from different world and convert these to RGB:


procedure ConvertColorToRGB(Color: integer);
begin
WriteLn('Red: '+IntTostr(Color mod 256)+' Green: '+IntToStr((Color / 256) mod 256)+' Blue: '+IntToStr((Color / 256) / 256));
end;


After you've done that, you only need to keep the highest and the lowest value of each color and fill it in:


function AutoColor:integer; //Based on Boreas GetLadderColor
var
TmpBmp,MyX,MyY:integer;
MyColor,TmpInt: integer;
MyCanvas:tcanvas;
TmpBool:boolean;

begin
TmpBmp:= BitmapFromString(100,90,'');
MyCanvas:=GetBitmapCanvas(TmpBmp);
CopyCanvas(GetClientCanvas,MyCanvas,598,39,698,129 ,0,0,100,90)
for MyY:=0 to 99 do
begin
for MyX:=0 to 89 do
begin
MyColor:= MyCanvas.pixels[MyX,MyY];
if ((MyColor/256) / 256) < {Biggest value of Blue}then
begin
if ((MyColor/256) mod 256) < {Biggest value of Green} then
begin
if ((MyColor/256) mod 256) > {Lowest value of Green} then
begin
if (MyColor mod 256) < {Biggest value of Red} then
begin
if (MyColor mod 256) > {Lowest value of Red}then
TmpBool:=true;
end;
end;
end;
end;
if TmpBool then break;
end;
if TmpBool then break;
end;
if TmpBool then result:=MyColor;
end;

This is an explanation of Tarajunky, how the SRL AutoColoring procedures work (thank Tara):


function FindWaterColor: Integer;
var
GC, a, l, TestColor, Red, Green, Blue : integer;
var
P:array of Tpoint;
begin
GC := 12095356; { <--- You put the 'Generic Color' here (median color value)}
Flag;
FindColorsSpiralTolerance(x, y, P, GC, MMX1, MMY1, MMX2, MMY2, 50); { <--- This grabs ALL the colors
as TPoints on the minimap that are within 50 tolerance of the GC and puts them in an array.
(This can be thousands of points!)}
l:=GetArrayLength(P);
for a:= 0 to l-1 do { <--- Takes each TPoint position in the array. }
begin
TestColor := GetColor(P[a].x, P[a].y); { <--- Grabs the color at the TPoint}
red := (TestColor mod 256); { <-- Splits the color}
green := ((TestColor / 256) mod 256);
blue := ((TestColor / 256) / 256);
if Green - Red <= 22 then if Green - Red >= 18 then { //Unique criteria for your color goes in
the next few lines. Usually comparisons between color components work best.
(R-G or G-B or R-B) In this case Green-Red ranges between a lower limit of 18
and and upper limit of 22}
if Blue - Red >= 55 then if Blue - Red <= 72 then
if Blue - Green >= 35 then if Blue - Green <= 52 then
if GetColor(P[a].x + 2, P[a].y + 2) = TestColor then { <--- Checks if matching color appears as
a block of uniform color}
if GetColor(P[a].x + 1, P[a].y + 1) = TestColor then
if GetColor(P[a].x, P[a].y + 2) = TestColor then
if GetColor(P[a].x + 2, P[a].y) = TestColor then
if GetColor(P[a].x, P[a].y + 1) = TestColor then
if GetColor(P[a].x + 1, P[a].y) = TestColor then
if GetColor(P[a].x + 2, P[a].y + 1) = TestColor then
if GetColor(P[a].x + 1, P[a].y + 2) = TestColor then
begin
Result := TestColor; { <--- Yep, it matched ALL criteria! Must be the correct color}
WaterColor := TestColor;
WriteLn('WaterColor = ' + IntToStr(TestColor));
Exit;
end;
end; { <--- Oops, wasn't your color, goes back and tests the next TPoint in the array}
WriteLn('Could not find Water Color!'); { <--- NONE of the Tpoints matched!}
Result := 0;
end;




Unique facts

This is probably the hardest, but maybe the best way to autocolor: use the unique facts of the color (and the place). These unique things you will have to find out yourself, but here are some examples:

Using the amount of the colors on the minimap:

program UniqueColorFinder;
{.Include SRL/SRL.SCAR}

const ReferenceColor = 1587244; // Refence color of the one we're looking for.
Tolerance = 15; // Tolerance added to the reference color.
Count = 30; // How much of these colors can be found on the MM.
Range = 15; // Range added to Count.

DebugCount = False; // Set to true to get / test your settings for above.
Color = 1191977; // Color you want to count / Usefull for finding the right settings for above.

type ColorMatch = Record
Color, Pixels: Integer;
end;

procedure WriteCount(Color: integer);
begin
WriteLn('Color: '+IntTostr(Color)+' Count: '+IntToStr(CountColor(Color, MMX1, MMY1, MMX2, MMY2)));
end;

function GetUniqueColor(var Color: integer; RefColor, Tol, HowManyOnMM, Range: integer): Boolean;
var
ColorArray: Array of ColorMatch;
Colors: Array of integer;
TempCount, TempCount2, TempColor, i, j: integer;
begin
SetArrayLength(Colors, 0);
for i := MMX1 to MMX2 do
for j := MMY1 to MMY2 do
if Rs_OnMinimap(i, j) then
begin
TempColor := GetColor(i, j);
if SimilarColors(RefColor, TempColor, Tol) then
begin
SetArrayLength(Colors, Length(Colors) +1);
Colors[(Length(Colors)) -1] := TempColor;
end
end
SetArrayLength(ColorArray, 0);
for i := 0 to Length(Colors) -1 do
begin
TempCount := CountColor(Colors[i], MMX1, MMY1, MMX2, MMY2);
if TempCount = HowManyOnMM then
begin
if Colors[i] > 0 then
begin
Color := Colors[i];
Result := True;
WriteLn('Found color with range 0');
Exit;
end
end else
begin
if Colors[i] > 0 then
begin
TempCount2 := HowManyOnMM - TempCount;
if TempCount2 < 0 then TempCount2 := TempCount - HowManyOnMM;
if (TempCount2 < Range) then
begin
SetArrayLength(ColorArray, Length(ColorArray) +1);
ColorArray[(Length(ColorArray)) -1].Color := Colors[i];
ColorArray[(Length(ColorArray)) -1].Pixels := TempCount2;
end
end;
end;
end;

if Length(ColorArray) = 1 then
begin
Color := ColorArray[0].Color;
Result := True;
WriteLn('Found color with range '+IntTostr(ColorArray[0].Pixels));
Exit;
end
try
begin
TempCount := Min(ColorArray[0].Pixels, ColorArray[1].Pixels)
for i := 1 to Length(ColorArray) -2 do TempCount := Min(TempCount, ColorArray[i +1].Pixels);
for i := 0 to Length(ColorArray) -1 do if TempCount = ColorArray[i].Pixels then
begin
Color := ColorArray[i].Color;
Result := True;
WriteLn('Found color with range '+IntTostr(ColorArray[i].Pixels));
Exit;
end
end
except
Result := False;
end;
if not Result then WriteLn('Unique Color NOT found! Please set it yourself.');
end;

var Color1: integer;
begin
SetupSRl;
ActivateClient;
if DebugCount then WriteCount(Color);
GetUniqueColor(Color1, ReferenceColor, Tolerance, Count, Range);
WriteLn('Color found: '+IntTostr(Color1));
end.

Using the length of the door (they are always 4 pixels long): (Tarajunky)

program FindDoorColor;
{.include SRL/SRL.scar}
var DoorColor:integer;
var ColorArray: array of integer;

Function CountArray:integer;
var TestColor,n:integer;
begin
TestColor:=GetColor(x,y);
For n:= 0 to 32 do
begin
if ColorArray[n]=TestColor then result:=result+1;
end;
end;

Function FindDoorColor:integer;
var a,b,i,j,n:integer;
begin
a:=MMX1;
b:=MMY1;
repeat;
a:=a+1;
repeat;
b:=b+1;
if FindColorTolerance(x,y,255,a,b,a,MMY2,10) then //Finds all similar DoorColors
begin
b:=y;
SetArrayLength(ColorArray,32);
n:=0;
for i:= 0 to 3 do
begin
for j:= 0 to 7 do
begin
ColorArray[n]:=GetColor(a+i,b-3+j); //Will get the colors around the found color to count the pixels
n:=n+1;
end;
end;
if CountArray=4 then //if there are exactly 4 pixels it's probably a door =]
begin
Result:=GetColor(x,y);
exit;
end;
end else b:=MMY2;
until b>=MMY2;
until a>=MMX2;
end;

begin
SetupSRL;
ActivateClient;
Doorcolor:=FindDoorColor;
end.



I hope this has helped you on your way to autocolor. I'm sorry if I was hard to follow on some parts, but English isn't my main language (which you may have guessed :p)
It's upto you now to make some nice autocolor functions! :)

Thanks for reading,
Nielsie95

rkroxpunk
05-04-2007, 04:32 PM
Wow awesome TUT I didn't even know that Bruteforce thing existed! thx a lot! :D

tarajunky
05-04-2007, 10:18 PM
Excellent tutorial.

wobbii
05-04-2007, 10:22 PM
very nice tut

stampede10343
05-05-2007, 12:56 AM
I Love You!!

lol

ty!:cartman:

nielsie95
05-05-2007, 08:12 AM
Thanks for all the nice comments :)
Any suggestions about what I could add?

Lorax
05-05-2007, 08:33 AM
I think you have covered the most including newer functions..

Killerdou
05-05-2007, 08:42 AM
for the bruteforcing boreas made something nice(you can fill in the colors, and it calculates the highest and lowest R G B of those colors and it calculates if you can actually use bruteforcing... it was made in excel i believe

nielsie95
05-05-2007, 09:16 AM
Yes, I only found one link for that. And that one needs to be reuploaded. So I leave it like this untill that link is up again :)

Markus
05-05-2007, 09:54 AM
This is nice! I never knew about the unique facts method. I used bruteforcing, but I got too much false positives.
About the file:
http://uppit.com/d/0QNA1

Janilabo
05-05-2007, 09:54 AM
Very nice tutorial indeed, good job nielsie! :)

3Garrett3
05-05-2007, 09:58 PM
nice tut tyvm, i learned something today

lordsaturn
05-06-2007, 03:13 AM
Thx! This'll definitely help in my new script! =]

Smartzkid
05-07-2007, 11:31 PM
You should make more tut's! :p

Really nice!

the scar noob
05-08-2007, 06:12 PM
i want o use that script, to count how many times the color is on the screen, can you tell me how to use plz?

nielsie95
05-08-2007, 07:31 PM
const ReferenceColor = 1587244; // Refence color of the one we're looking for.
Tolerance = 15; // Tolerance added to the reference color.
Count = 30; // How much of these colors can be found on the MM.
Range = 15; // Range added to Count.

This pretty much explains it all :)

ShawnjohnSJ
05-08-2007, 08:57 PM
This was a nice tutorial. *Thumbs up*

Thanks.

the scar noob
05-09-2007, 12:22 PM
const ReferenceColor = 1587244; // Refence color of the one we're looking for.
Tolerance = 15; // Tolerance added to the reference color.
Count = 30; // How much of these colors can be found on the MM.
Range = 15; // Range added to Count.

This pretty much explains it all :)

If i could speak better englsih it should...

Jason2gs
05-19-2007, 02:37 AM
Dang, thanks!

Sure helped me :)

tarajunky
05-19-2007, 04:46 AM
I suppose this is a good place to put this...

I rewrote all my AutoColor functions using a new strategy based on FindColorsSpiralTolerance. It's MUCH, MUCH faster than the old way I was doing it.

It should be included in the next version of SRL that is released (hopefully), but if you want to use any of my autocolor stuff as a template, use this instead of the old one.

Jason2gs
05-19-2007, 04:57 AM
Oooh... *Finds download button*

Thanks, Tara ;)

Edit: Would you mind commenting part of it for me? I'm not sure where I'm supposed to put the high and lows of the RGB values.

tarajunky
05-19-2007, 07:15 AM
Sure, no prob...




function FindWaterColor: Integer;
var
GC, a, l, TestColor, Red, Green, Blue : integer;
var
P:array of Tpoint;
begin
GC := 12095356; { <--- You put the 'Generic Color' here (median color value)}
Flag;
FindColorsSpiralTolerance(x, y, P, GC, MMX1, MMY1, MMX2, MMY2, 50); { <--- This grabs ALL the colors
as TPoints on the minimap that are within 50 tolerance of the GC and puts them in an array.
(This can be thousands of points!)}
l:=GetArrayLength(P);
for a:= 0 to l-1 do { <--- Takes each TPoint position in the array. }
begin
TestColor := GetColor(P[a].x, P[a].y); { <--- Grabs the color at the TPoint}
red := (TestColor mod 256); { <-- Splits the color}
green := ((TestColor / 256) mod 256);
blue := ((TestColor / 256) / 256);
if Green - Red <= 22 then if Green - Red >= 18 then { //Unique criteria for your color goes in
the next few lines. Usually comparisons between color components work best.
(R-G or G-B or R-B) In this case Green-Red ranges between a lower limit of 18
and and upper limit of 22}
if Blue - Red >= 55 then if Blue - Red <= 72 then
if Blue - Green >= 35 then if Blue - Green <= 52 then
if GetColor(P[a].x + 2, P[a].y + 2) = TestColor then { <--- Checks if matching color appears as
a block of uniform color}
if GetColor(P[a].x + 1, P[a].y + 1) = TestColor then
if GetColor(P[a].x, P[a].y + 2) = TestColor then
if GetColor(P[a].x + 2, P[a].y) = TestColor then
if GetColor(P[a].x, P[a].y + 1) = TestColor then
if GetColor(P[a].x + 1, P[a].y) = TestColor then
if GetColor(P[a].x + 2, P[a].y + 1) = TestColor then
if GetColor(P[a].x + 1, P[a].y + 2) = TestColor then
begin
Result := TestColor; { <--- Yep, it matched ALL criteria! Must be the correct color}
WaterColor := TestColor;
WriteLn('WaterColor = ' + IntToStr(TestColor));
Exit;
end;
end; { <--- Oops, wasn't your color, goes back and tests the next TPoint in the array}
WriteLn('Could not find Water Color!'); { <--- NONE of the Tpoints matched!}
Result := 0;
end;

nielsie95
05-22-2007, 04:44 PM
Thanks :) I'll update a template when I get time (probably this weekend). :)

Lalaji
05-23-2007, 05:17 PM
Nice dude ty alot.

Dan Cardin
06-12-2007, 11:16 PM
wtf!!! i'm in fally and tried FindFallyRoadColor....and it wont work!!!!?

nielsie95
06-24-2007, 02:20 PM
small update!

Added Tara's explanation of the SRL method of AutoColoring :)
When I get more time, I'll add some more :)

crossback7
06-26-2007, 05:36 AM
Quite helpful. But say I wanted to automatically find the color of a chicken. Could I use a bitmap for that since they constantly turn and rotate and stuff?

Trying to make a chicken killer and having a few problems. . .

nielsie95
06-26-2007, 05:46 AM
Try to use colors.. Search some colors that all chickens have, but not too much. And then experiment. :)

crossback7
06-26-2007, 05:48 AM
Such as maybe the red gobbler thing they have? Since they have both the light beigh ones and the brown ones now. Thanks a lot for the quick reply too.

BobboHobbo
06-26-2007, 06:54 AM
Nice guide!

nielsie95
06-26-2007, 10:12 AM
Thanks Bobbo :)

@Cross: Yes, I think the red color (with some tolerence) will do :)

rkroxpunk
06-26-2007, 12:04 PM
I use DTM editor to pick a colour and then i get it to match the pixels around it. works with tolerance as well. I think yakman made a script for that as well. didn't read thread so hopefully wasn't mentioned already :p

nielsie95
06-26-2007, 12:30 PM
Wasn't mentioned :)
Thanks for the tip!

crossback7
06-26-2007, 03:52 PM
Thanks. I'll try that out.

Garrett
07-19-2007, 04:46 PM
Great tutorial, thanks!

ShowerThoughts
08-17-2007, 07:17 PM
nice tut helped me alot

HellBoyz
08-23-2007, 06:29 AM
what a great tuts help learn a lot in auto color feature will use it if possible

Bourdou!
08-25-2007, 03:38 AM
Oh ya this guide is great.

I B X R
09-01-2007, 04:05 PM
NIce dude