SRL Archive - SRL Archives

Detect Motion In Abstract Points | Function AbstractMotion: Boolean;


Nadeem

2009-05-11 06:10:10

Hi,

Well I kind of made this feature for the fun of it :P I will now explain how to use and the uses for this. Keep in mind, this is not always the best thing to depend on though, because of angles (high, low). Works best when its in the angle whilst the abstract points were taken. (Obviously…) I will try and create a small built in block in the function to get the closest possible angle. (Won't promise it though)

[HOW TO USE:]

while AbstractMotion(0, 25, 100, 0, 80, 100, 25, 50, TRUE) do Wait(100);
{Will give you result similar to IMG1: Super Accurate}

while AbstractMotion(0, 25, 100, 0, 80, 100, 25, 50, FALSE) do Wait(100);
{Will give you result similar to IMG1: Super Fast}

[USING EFFECTIVELY:]
IMPORTANT LOGIC: Make sure you keep a TimeFromMark set when calling the procedure. An effective TimeFromMark would be between the average time in ms it take the player to travel that distance, and the max time it would take walking.

Walking/Running
- For best effect result, try and keep the abstract near the center of your player, overlapping his/her legs. This way, it catches movement of your player's legs, and not finish up based on rs grass.

Skills (Woodcutting, Mining, etc…)
- Would be more effect if you keep the abstract around the upper head/should of the player, to catch hand movement.


[MY SPECIAL FUNCTION TO SEARCH FOR POINT IN ABSTRACT:]
{×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
× Function : PointInAbstr: Boolean; | v1.0
× Author : Nadeem
× Desc. : Checks if defined points are inside an abstract.
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××}
function PointInAbstr(const TPA: TPointArray; X, Y: Integer): Boolean;
var
H, K: Integer;
C: TIntegerArray;
begin
Result := False;
H := Length(TPA) - 1;
for K := 0 to H do
begin
if ((TPA[K].Y <= Y) and (Y < TPA[H].Y)) or
((TPA[H].Y <= Y) and (Y < TPA[K].Y)) then
begin
SetLength(C, 3);
C := [(TPA[H].X - TPA[K].X), (y - TPA[K].Y), (TPA[H].Y - TPA[K].Y)];
if (x < C[0] * C[1] / C[2] + TPA[K].X) then
Result := (not(Result));
end;
H := K;
end;
end;

[THE FUNCTION:]
{×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
× Function : AbstractMotion: Boolean; | v1.5
× Author : Nadeem
× Desc. : Checks for motion in a box or in defined abstract.
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××}
function AbstractMotion(x1,y1,x2,y2,x3,y3,x4,y4:Integer; P:Boolean): Boolean;
var
tx, ty, bmpClient, bmpClient2, Width, Height, I, J: Integer;
TPA: TPointArray;
X, Y, W, H: TIntegerArray;
D: HDC;
begin
D := GetTargetDC;
SetLength(X, 4);
SetLength(Y, 4);
X := [x1, x2, x3, x4];
Y := [y1, y2, y3, y4];
try
W := [AMin(X), AMax(X)];
H := [AMin(Y), AMax(Y)];
X := [X[0] - W[0], X[1] - W[0], X[2] - W[0], X[3] - W[0]];
Y := [Y[0] - H[0], Y[1] - H[0], Y[2] - H[0], Y[3] - H[0]];
Width := W[1] - W[0];
Height := H[1] - H[0];
bmpClient := BitmapFromString(Width, Height, '');
bmpClient2 := BitmapFromString(Width, Height, '');
CopyClientToBitmap(bmpClient, W[0], H[0], W[1], H[1]);
TPA := [IntToPoint(X[0], Y[0]), IntToPoint(X[1], Y[1]),
IntToPoint(X[2], Y[2]), IntToPoint(X[3], Y[3])];
if P then
begin
for J := 0 to Height do
for I := 0 to Width do
if(not(PointInAbstr(TPA, I, J)))then
FastSetPixel(bmpClient, I, J, 0);
end;
Wait(100);
CopyClientToBitmap(bmpClient2, W[0], H[0], W[1], H[1]);
SetTargetDC(GetBitmapDC(bmpClient2));
Result := (not(FindBitmapIn(bmpClient, tx, ty, 0, 0, Width, Height)));
finally
FreeBitmap(bmpClient);
FreeBitmap(bmpClient2);
SetTargetDC(D);
except end;
end;



~NS

Da 0wner

2009-05-11 06:19:15

I understand what it does but have no idea how it works lol. Niiiice :).
Add to SRL pl0x Devs?

Nadeem

2009-05-11 06:21:35

xD It's not hard… Thats why I took 10 minutes of my life to make a eye attractive image so you see and learn!

senrath

2009-05-11 06:21:57

Um, one question. Why do you have the except and finally blocks doing the exact same thing? Won't that cause an error if the except block is called, because it will free the bitmaps, and then the finally block will attempt to free the bitmaps again and fail?

Da 0wner

2009-05-11 06:30:15

Freeing a bitmap twice does not cause an error.

senrath

2009-05-11 06:51:50

From: Da 0wner
Freeing a bitmap twice does not cause an error.


Right, my bad. It'll only cause an error if a bitmap was never assigned to that variable.

However, the code is still redundant. That except block really isn't doing anything.

Smartzkid

2009-05-11 06:52:36

From: Da 0wner
Freeing a bitmap twice does not cause an error.


You sure about that? I think it gives a memory access violation..

Da 0wner

2009-05-11 06:52:52

Yes, that is true ;).

senrath

2009-05-11 06:55:43

From: Smartzkid
You sure about that? I think it gives a memory access violation..


He's right, I just double checked it. It does, however, give a memory access violation if a bitmap was never assigned to begin with.

Da 0wner

2009-05-11 07:07:12

Lol, I was saying Yes, that is true to senrath but I did not know you had posted.

I am sure about that though.
But a memory access violation occurs if it was never declared/assigned just as if any other bitmap function was declared (FindBitmap, etc.).

Nadeem

2009-05-11 07:13:43

My bad, Did not notice that :/ Just that I never came across that error even after a few dozen tests with that. But, then again, isn't it that, If the try block gets executed correctly, only the finally block is activated after that, not the except. And when the try block gives off an error, only the except block is executed not the finally? Because i've tested it while the try block gave an error once, and the memory access violation still never came across. To avoid this situation at all cost, I added something to check for it, that should be ok IMO, but let me know if its not possible.



~NS

senrath

2009-05-11 07:18:00

Finally will always be executed. It goes like this:
try
iff try fails, except
finally

Just leave the except block empty, unless their is something specific you want to do when try fails.

(No, there aren't any misspellings in this post.)

Nadeem

2009-05-11 07:33:46

OK, Thank you! :) It has been corrected. Has anyone actually tested this yet? Or just commenting on the code for now… :P

Bobarkinator

2009-05-11 08:24:50

This will result true if just one pixel has shifted… You should add it so that you can set how many pixels you want it to see have shifted before it results true..

Da 0wner

2009-05-11 08:34:18

That's the point though :o.
I thought 1 pixel shift is still movement?

mormonman

2009-05-11 08:36:10

From: Da 0wner
That's the point though :o.
I thought 1 pixel shift is still movement?


If this is made for using in rs, then one pixel shift is nothing. Things is rs sway, such as your character, so this couldn't even be used for an 'ischopping' proc.

Nadeem

2009-05-11 08:57:25

I tested it with chopping trees, worked pretty good. (while chopping trees, if you use logic, your OBVIOUSLY WILL NOT, draw the abstract inside the tree! It will be place above your characters head to catch movement of your hatchet aswell :P)
It works 99.99% flawlessly on movement such as player movement. However TimeFromMarks, should always be implemented due to busy times

BobboHobbo

2009-05-11 10:27:19

Sweet function and nice picture to go with it, if i didnt see the picture then i wouldnt of understanded as well :).

Gu3st...

2009-05-11 15:08:52

Nice work! That picture did help alot

But sometimes the whole mainscreen (or the camera if you want) moves (around 1 degree or so) so if that happens when searching it would result true even if the object did not move?

Naum

2009-05-11 18:50:54

Did you do the piv technique :p

Nadeem

2009-05-11 20:14:48

From: BobboHobbo
Sweet function and nice picture to go with it, if i didnt see the picture then i wouldnt of understanded as well :).

Thank you! Glad it helped! :P

From: Zyt3x
Nice work! That picture did help alot

But sometimes the whole mainscreen (or the camera if you want) moves (around 1 degree or so) so if that happens when searching it would result true even if the object did not move?

Thanks! And It may do that, but then it searches quickly for the movement within 150ms with a 100ms between checktime, and even if it does move 1 deg, in the next 150ms it'll result false. Though you shouldn't use this to call a procedure on movement, it should be used as like a while moving do procedure. And btw, I do not think the 1 deg might make too much of a difference else if I am wrong, I can always add in FindBitmapToleranceIn :P

From: NaumanAkhlaQ
Did you do the piv technique :p

piv technique…? Whats that O.o…?



~NS

Naum

2009-05-11 20:24:30

Well its with piv's old gas check - he did the same as you, he would capture it on a canvas and check the difference to check for gas. Oldies know what I'm talking 'bout.

program pixelarray;
var
pic,x,y:integer;
color: integer;
piccanvas:tcanvas;
begin
Pic:= BitmapFromString(20,20,'');
PicCanvas:=GetBitmapCanvas(pic)
CopyCanvas(GetClientCanvas,PicCanvas,0,0,20,100,0,0,20,20)
for y:=0 to 19 do
for x:=0 to 19 do
begin
color:= piccanvas.pixels[x,y];
writeln('pixels : '+inttostr(x)+','+inttostr(y)+' = '+inttostr(color));
end
end.


the above program writes every pixel into the debug log

a practical use for this is in the SRL mining include {.include SRL\SRL\Skills\Mining.scar} it is for checking gas, Piv cleverly used this to check if a canvas copied from client is different from a canvas copied 100 milliseconds later, therefore meaning that gas is coming from the rock

Nadeem

2009-05-11 22:43:35

oh lol :P Nice to know I've followed something done by a great scripter :)

n3ss3s

2009-05-14 17:24:59

Nauman, the idea to check if points on a canvas differ has been used a gazillion times, what makes this one a little trickier is that it uses abstract shapes…

Nadeem

2009-05-15 02:58:21

n3ss3s, so your saying this is more unique? xP



~NS