SRL Archive - Research & Development Lounge

FindMovement


Fizzi

2007-08-01 19:58:54

First of all, I'd like to thank Smartzkid for helping me with arrays :). Secondly, I wrote this script on a piece of paper when I was bored at work. I'm not really sure how much use it's gonna be, but I thought it was pretty cool. Here's what it does (I suggest you look at the script first before reading this, it might be confusing, I'm not sure):

Step 1: Saves the coordinates of pixels inside the boundaries specified in a checkerboard pattern to Points[].x and Points[].y
Example:
[ ][ ][ ]
[ ][ ][ ]
[ ][ ][ ]
Let these boxes represent pixels inside the boundaries specified by (x1 = 0, y1 = 0, x2 = 2, y2 = 2).
The script would record these coordinates:
Points[0].x := 0, Points[0].y := 0
Points[1].x := 2, Points[1].y := 0
Points[2].x := 1, Points[2].y := 1
Points[3].x := 0, Points[3].y := 2
Points[4].x := 2, Points[4].y := 2

Step 2: Records the color of all the pixels in Points[].Color[0] at time = 0. Then will record all the colors of the same coordinates at time = frequency. Then at time = 2 * frequency, and so on.
Example
[R][Y][R]
[R][Y][R]
[Y][R][R]
Let the pixels with R's in them represent red, and the pixels with Y's in them represent yellow.
At time = 0 the program would record the values:
Points[0].Color[0] := Red
Points[1].Color[0] := Red
Points[2].Color[0] := Yellow
Points[3].Color[0] := Yellow
Points[4].Color[0] := Red
Then after time specified in the variable Frequency, it will do the same thing but record the colors to Points[].Color[1], and so on until time specified in the variable TStop has gone.

Step 3: Compares all the color values recorded in each point. If some colors recorded in a point don't match, then the script knows there was movement. FindMovement would result as true at this point, but FindMovementColorTol has another step.
Example:
Points[0].Colors[0] = Red
Points[0].Colors[1] = Yellow
Points[0].Colors[2] = Red
This would mean that movement happened because the color at that pixel changes.

Step 4 (FindMovementColorTol only): Checks the Points[].Color[] array that resulted in movement being true for any colors that are similar to the color specified in the variable ColorMoving, checks colors with tolerance. This function results as true if movement is found and if one or more of the colors in the pixel that had changing colors is similar to the specified color. This is useful for finding moving colors.

Uses: Really the only thing I'm going to use it for is to detect gas, because the SRL one doesn't work too well for me. If anyone else can think of any other uses, please tell me, i'd love to know :-P.

Here it is:

type ColorPoints = record
x, y : integer;
Color : array of integer;
end;

var
Points: array of ColorPoints;

//Detects movement inside boundaries x1, y1, x2, y2
function FindMovement(TStop, Frequency: Integer; x1, y1, x2, y2 : Integer) : boolean;
var
TSearch, PCount, CCount, slength, sheight, i, k : Integer;
begin
slength := (x2 - x1);
sheight := (y2 - y1);
PCount := 0; CCount := 0;
for i := 0 to sheight do
begin
if (i = 0) or ((i mod 2) = 0) then
begin
for k := 0 to (slength/2) do
begin
setlength(Points, length(Points)+1);
Points[PCount].x := (x1 + (2*k));
Points[PCount].y := (y1 + i);
PCount := (PCount + 1);
end;
end else
begin
if((slength mod 2) = 0) then
begin
for k := 0 to ((slength/2) - 1) do
begin
setlength(Points, length(Points)+1);
Points[PCount].x := (x1 + 1 + (2*k));
Points[PCount].y := (y1 + i);
PCount := PCount + 1;
end;
end else
begin
for k := 0 to (slength/2) do
begin
setlength(Points, length(Points)+1);
Points[PCount].x := (x1 + 1 + (2*k));
Points[PCount].y := (y1 + i);
PCount := (PCount + 1);
end;
end;
end;
end;
MarkTime(TSearch);
repeat
for i := 0 to (PCount - 1) do
begin
setlength(Points[i].Color, length(Points[i].Color)+1);
Points[i].Color[CCount] := GetColor(Points[i].x, Points[i].y);
end;
CCount := CCount + 1;
Wait(Frequency);
until(TimeFromMark(TSearch) > TStop);
for i := 0 to (PCount - 1) do
begin
for k := 0 to (CCount - 2) do
begin
if(Points[i].Color[k] <> Points[i].Color[k+1]) then
begin
Result := True;
Exit;
end;
end;
end;
end;

//Detects movement of a certain color with tolerance
function FindMovementColorTol(TStop, Frequency : Integer; ColorMoving : Integer;
x1, y1, x2, y2 : Integer; Tolerance : Integer) : boolean;
var
TSearch, PCount, CCount, slength, sheight, i, k : Integer;
Movement : Boolean;
begin
slength := (x2 - x1);
sheight := (y2 - y1);
PCount := 0; CCount := 0;
for i := 0 to sheight do
begin
if (i = 0) or ((i mod 2) = 0) then
begin
for k := 0 to (slength/2) do
begin
setlength(Points, length(Points)+1);
Points[PCount].x := (x1 + (2*k));
Points[PCount].y := (y1 + i);
PCount := (PCount + 1);
end;
end else
begin
if((slength mod 2) = 0) then
begin
for k := 0 to ((slength/2) - 1) do
begin
setlength(Points, length(Points)+1);
Points[PCount].x := (x1 + 1 + (2*k));
Points[PCount].y := (y1 + i);
PCount := PCount + 1;
end;
end else
begin
for k := 0 to (slength/2) do
begin
setlength(Points, length(Points)+1);
Points[PCount].x := (x1 + 1 + (2*k));
Points[PCount].y := (y1 + i);
PCount := (PCount + 1);
end;
end;
end;
end;
MarkTime(TSearch);
repeat
for i := 0 to (PCount - 1) do
begin
setlength(Points[i].Color, length(Points[i].Color)+1);
Points[i].Color[CCount] := GetColor(Points[i].x, Points[i].y);
end;
CCount := CCount + 1;
Wait(Frequency);
until(TimeFromMark(TSearch) > TStop);
for i := 0 to (PCount - 1) do
begin
Movement := False;
for k := 0 to (CCount - 2) do
begin
if(Points[i].Color[k] <> Points[i].Color[k+1]) then Movement := True;
end;
if Movement then
begin
for k := 0 to (CCount - 1) do
begin
if(SimilarColors(Points[i].Color[k], ColorMoving, Tolerance)) then
begin
Result := True;
Exit;
end;
end;
end;
end;
end;

Sp0rky

2007-08-01 20:06:30

That is sexy!

Definately be using this in any future scripts I make (if thats ok with you :p)

Secet

2007-08-01 20:12:10

Pretty nice. Have you tought about SRL application? ;)

XcanadamanX

2007-08-01 20:49:27

wouldnt it be easier to do with canvases?
look at the gas check func.
function GasCheck(gx, gy: Integer): Boolean;
var
clientcanvas, gascanvas1, gascanvas2: TCanvas;
xG, yG, count: Integer;
pic1, pic2: Integer;
begin
if (FindColorTolerance(xG, yG, 8296866, gx - 20, gy - 20, gx + 20, gy + 20,
20)) then
begin
pic1 := BitmapFromString(40, 40, '');
pic2 := BitmapFromString(40, 40, '');
gascanvas1 := GetBitmapCanvas(pic1);
gascanvas2 := GetBitmapCanvas(pic2);
clientcanvas := getclientcanvas;
CopyCanvas(clientcanvas, gascanvas1, gx - 20, gy - 20, gx + 20, gy + 20, 0,
0, 40, 40);
Wait(100);
CopyCanvas(clientcanvas, gascanvas2, gx - 20, gy - 20, gx + 20, gy + 20, 0,
0, 40, 40);
count := 0;
for yG := 1 to 40 do
for xG := 1 to 40 do
if ((gascanvas1.pixels[xG, yG]) <> (gascanvas2.pixels[xG, yG])) then
count := count + 1;
WriteLn(IntToStr(Trunc(((count) / 1024) * 100)) + '% change.');
if (count > 150) then //if more than 15% change
Result := True;
FreeBitmap(pic1);
FreeBitmap(pic2);
end;
end;
its basically the same thing but it finds if the gas is moving.

but anyway good work.

Fizzi

2007-08-01 22:27:22

From: XcanadamanX
wouldnt it be easier to do with canvases?
look at the gas check func.
function GasCheck(gx, gy: Integer): Boolean;
var
clientcanvas, gascanvas1, gascanvas2: TCanvas;
xG, yG, count: Integer;
pic1, pic2: Integer;
begin
if (FindColorTolerance(xG, yG, 8296866, gx - 20, gy - 20, gx + 20, gy + 20,
20)) then
begin
pic1 := BitmapFromString(40, 40, '');
pic2 := BitmapFromString(40, 40, '');
gascanvas1 := GetBitmapCanvas(pic1);
gascanvas2 := GetBitmapCanvas(pic2);
clientcanvas := getclientcanvas;
CopyCanvas(clientcanvas, gascanvas1, gx - 20, gy - 20, gx + 20, gy + 20, 0,
0, 40, 40);
Wait(100);
CopyCanvas(clientcanvas, gascanvas2, gx - 20, gy - 20, gx + 20, gy + 20, 0,
0, 40, 40);
count := 0;
for yG := 1 to 40 do
for xG := 1 to 40 do
if ((gascanvas1.pixels[xG, yG]) <> (gascanvas2.pixels[xG, yG])) then
count := count + 1;
WriteLn(IntToStr(Trunc(((count) / 1024) * 100)) + '% change.');
if (count > 150) then //if more than 15% change
Result := True;
FreeBitmap(pic1);
FreeBitmap(pic2);
end;
end;
its basically the same thing but it finds if the gas is moving.

but anyway good work.


Well, I haven't really looked at canvases yet, so I don't really get them yet. Although, the SRL find gas doesn't seem to work too well for me, I'm hoping this one that I made will work better. The cool thing is that I make it select a 30 x 30 square over the rock, this means it will look at 450 pixels, if there is gas, one of them that will be moving is bound to contain the gas color at a low tolerance, since it will see many different colors of the gas.

This is the line I am using, fx and fy are where I found the rock color:
FindMovementColorTol(1050, 200, 8166047, fx-15, fy-30, fx+15, fy, 5)


From: Secet
Pretty nice. Have you tought about SRL application? ;)


Thank you :). I applied 12 days ago, currently waiting on a response.


From: Sp0rk-eh
That is sexy!

Definately be using this in any future scripts I make (if thats ok with you :p)


Sure thing, just credit me properly and tell me what you use it for, I'm curious on wether or not it has other uses besides gas =P.

Timothegreat

2007-08-01 22:57:31

From: Fizzi
I'm curious on wether or not it has other uses besides gas =P.


couldnt this be used as an ent finder??? (since the tree moves when its an ent *duh*) :p

Smartzkid

2007-08-01 23:06:46

Ent, gas, whirlpool if you did it with tolerance (both tolerance on each point's color, and tolerance on % of points changed), maybe more?


Definitely a lot of potential here.

Esteban

2007-08-02 00:15:11

Also like the ent finding idea I had, Smartz.

XcanadamanX

2007-08-02 08:52:50

findgas looks in 40 x 40 but anyway you should look into canvases.

WT-Fakawi

2007-08-02 09:24:57

Actually, the SRL gasfinder (made by piv) does work, but you need to take into consideration that once gas is detected, you are not allowed to move anymore, since the gascoords are not updated when moving.

I have made a similar kinda function that detects if we are moving, by comparing 8 pixels from the minimap.

Good work. Try it for gasfinding and see how well it does…

n3ss3s

2007-08-02 10:55:17

but you need to take into consideration that once gas is detected, you are not allowed to move anymore, since the gascoords are not updated when moving.


Make sum function thingy Coords per tile then GasColors(x - (CoordsPerTile * TilesMoved), y);

mastaraymond

2007-08-02 10:57:22

This sounds cool, but is a bit hard to really use it.. Personnaly i made something like this, i made it for the furnace, as a double check. It checks if the colors are moving, only its made with Canvas :p.
Good job anyway,
Btw, if you want to speed it up a bit, use GetClientBitmap & GetBitmapAreaColors, another way to detect it, just compare 2 CountColorTolerance's, if they got a big different, the color is changing\moving :).

~Raymond.

Timothegreat

2007-08-07 23:30:57

well anyways i am going to use this in a couple scripts thanx

SKy Scripter

2007-08-07 23:40:15

Canvas Arnt Very good… If Any Activity besides the gas.. is going on it can screw up the detection… finding the movement of someon else pick swinging or yours… numbers of things… (so Your Going to have to find all the gas pixels twice them compare them) :p

Boreas

2007-08-08 00:21:20

Plus the screen moves anyway.

Fizzi

2007-08-10 12:39:45

I modified it to count how many pixels it finds that has the gascolor moving. This way, it'll only return true if it find 15 different pixels where the gas color was moving. This is good because it avoids resulting true if a character is moving that has gas colored clothing and such…. I think it does work, but I have a couple questions:

1) Is it possible to test this at will? For example, by using mopariscape the make the rocks have the gas random? If this is possible in anyway it would help a lot.

2) How long does gas last? I need to put a wait procedure or some code that will check for a rock that is not being gased (I already have an idea for how I can make this work). I would like to know what the maximum amount of time it lasts though for a 100% avoid (as long as it detects it to begin with of course).