Very weird and interesting (X,Y) problem

A

AnotherDoor

Guest

(click to get the bigger version or press here)
(number in the left-up corner is the target location, middle one is X,Y of the red square, and the last one is the X,Y of the green square)

So, the red square has a code which moves it towards a random location (which is constant 4,7 because I have not randomized it). But there are 2 problems:

1) The starting grid coordinates for the red square are (8,8). But the code says (9,8) which is not logical, as the wall is drew in the X = 9, and it obviously is not inside the wall. Also the spawn coordinates are (320-64,320-64)(one grid square is 32x32)(The whole map is 320x320)
The grid coordinates are calculated by:
X = x/32;
Y = y/32;

One way to fix this is by
X = (x-32)/32
Y = y/32

But why is the X only one "broken" ?



2) Here it gets fascinating. If you pay attention to the pictures you see that in the 6th image (from left), the Y of the red square is not changing but instead the X is the one getting decreased ? But as we can see, it's the variable X that is broken, not the x because the x works just fine.

ALSO same with the next picture (7th from left), the box moves from left to right, so the X value should be increasing right ? But no, instead the Y value is decreased ?

And in the last pictures I just show with the green square the real coordinates of the "grid blocks" (in the last one the green one is on top of the red one thus the red one cannot be seen).


So, only thing what comes to my mind is that somewhere in my code I have a line of code which changes the X variable and the Y variable, but why doesn't it get fixed(by the step event which is more frequent than the timer, explained below):
The:
X = x/32;
Y = y/32;
Is located in step event, meanwhile rest of the moving code is self looping timer with 0,5s delay. (Timer stops looping when the X variable and Y variable of the red square equal to the X and Y of the target location)

foundgoal = 0;
finding = 0;
foundtile = 0;
ready = 0;
alarm[0] = room_speed*1;
global.Xe = 0;
global.Ye = 0;
global.Xc = x/32;
global.Yc = y/32;

//SOME OF THESE ARE NOT USED, BUT THE BOTTOM ONES ARE

global.Xc = Xc;
global.Yc = Yc;


array[1] = 0;
array[2] = 0;
array[3] = 0;
array[4] = 0;

array[5] = 51;
array[6] = 51;
array[7] = 51;
array[8] = 51;


//THIS FINDS EMPTY SLOT IN THE GRID

if(finding = 0)
{
repeat (100)
{

Y = irandom(9);
X = irandom(9);

global.Xe = X;
global.Ye = Y;

if (ds_grid_get(global.grid,X,Y) = 0)
{
//foundtile = 1;
//ready = 1;
finding = 1;
break;
}
}
}


//TILE = 1 = WALL
//TILE = 0 = EMPTY


array[1] = ds_grid_get(global.grid,Xc,Yc-1); //up
array[2] = ds_grid_get(global.grid,Xc-1,Yc); //left
array[3] = ds_grid_get(global.grid,Xc,Yc+1); //down
array[4] = ds_grid_get(global.grid,Xc+1,Yc); //right


//THIS IS LOCATING THE NEAREST 0 TILE CLOSEST TO THE TARGET BY CALCULATING FORMULA "DISTANCE OF TWO DOTS" WHERE Xc/Yc IS THE CORDS OF THE SQUARE AND WHERE X/Y IS THE TARGET

if (array[1] = 0) //up
{
array[5] = sqrt(abs(sqr(Xc-X))+abs(sqr((Yc-1)-Y)));
}
if (array[2] = 0) //left
{
array[6] = sqrt(abs(sqr((Xc-1)-X))+abs(sqr(Yc-Y)));
}
if (array[3] = 0) //down
{
array[7] = sqrt(abs(sqr(Xc-X))+abs(sqr((Yc+1)-Y)));
}
if (array[4] = 0) //right
{
array[8] = sqrt(abs(sqr((Xc+1)-X))+abs(sqr(Yc-Y)));
}

//show_message(string(array[6]))


//CALCULATES THE ARRAY WITH LOWEST VALUE

i = 8;
j = 50;
k = 0;
repeat(4)
{
if (array < j)
{
j = array;
k = i;
i -= 1;
//show_message(string(j));
}
else
{
i -= 1;
}

}

//THIS MOVES THE SQUARE TO THE DIRECTION OF NEAREST CORD TO THE TARGET

//up
if(k = 5)
{
y -= 32;
}

//left
if(k = 6)
{
x -= 32;
}

//down
if(k = 7)
{
y += 32;
}

//right
if(k = 8)
{
x += 32;
}

if(Xc == X && Yc == Y)
{
exit;
}


if(ready = 0)
{
alarm[0] = room_speed*1;
}
Xc = x/32;
Yc = y/32;


Every help is appreciated and please do ask and I will reply.
 
Last edited by a moderator:

Hyomoto

Member
Whew, I would have to say I can't say exactly what is wrong but I can say that your code may be unnecessarily complex. From reading your code I can't quite figure out what you are trying to accomplish.
Code:
array[5] = sqrt(abs(sqr(Xc-X))+abs(sqr((Yc-1)-Y)));
You are finding the square root of a square, so couldn't you just simplify this to:
Code:
array[5] = abs( Xc - X ) + abs( ( Yc - 1 ) - Y )
My advice would be instead of tracking an absolute X position, if you are just going to x += 32 anyways ( for example ), just do x += 1 and instead draw it differently:
Code:
draw_sprite( sprite_index, image_index, x * 32, y * 32 )
This would help simplify things GREATLY and might make it easier to figure out what's happening. This way you are always dealing with grid positions and avoid the problem of converting them back and forth.
 
A

AnotherDoor

Guest
@Hyomoto

Yes thanks, this seems pretty good draw_sprite( sprite_index, image_index, x * 32, y * 32 )

Also, yes it seems you can replace 2D pythagorean theorem with absolute values.. Interesting.. Never thought of that before.

if (array[1] = 0) //up Here it first asks if the upper tile is wall, if it is not it will calculate the distance to the target block
{
array[5] = sqrt(abs(sqr(Xc-X))+abs(sqr((Yc-1)-Y)));
}
if (array[2] = 0) //left Here is the same but with left tile
{
array[6] = sqrt(abs(sqr((Xc-1)-X))+abs(sqr(Yc-Y)));
}
if (array[3] = 0) //down Down tile
{
array[7] = sqrt(abs(sqr(Xc-X))+abs(sqr((Yc+1)-Y)));
}
if (array[4] = 0) //right Right tile
{
array[8] = sqrt(abs(sqr((Xc+1)-X))+abs(sqr(Yc-Y)));
}


So the distance values are stored in array[5] ... array[8]. And then they are compared to see which tile gives lowest value (lowest distance value = nearest).


But I will redo the code and try to make it more rational :p
 

Hyomoto

Member
Ah, that makes more sense. I can't say whether or not that is the best way to do it, but if I understand you correctly, the goal of this section is to figure out which direction provides the shortest route to the player that isn't a wall? Either way, I'd start by simplifying your overall structure since the more math you do, the easier it is to lose a 1 somewhere.
 
A

AnotherDoor

Guest
@Hyomoto Thanks for help again :p I got it to work again, I don't know what was the problem. But it now works just as planned.

//Xgoal & X
//Ygoal & Y





wall[1] = ds_grid_get(global.grid,X,Y-1); //up
wall[2] = ds_grid_get(global.grid,X-1,Y); //left
wall[3] = ds_grid_get(global.grid,X,Y+1); //down
wall[4] = ds_grid_get(global.grid,X+1,Y); //right

^Checks whether the block in (up,left,down,right) is a wall (wall = 1, empty = 0)



distance[1] = abs(X-Xgoal)+ abs((Y-1)-Ygoal); //up
distance[2] = abs((X-1)-Xgoal)+ abs(Y-Ygoal); //left
distance[3] = abs(X-Xgoal)+ abs((Y+1)-Ygoal); //down
distance[4] = abs((X+1)-Xgoal)+ abs(Y-Ygoal);; //right

^Distance calculation

var i = 4;
var j = 50;
nearest = 0;

while (i > 0)
{
if(wall = 0 && distance < j)
{
nearest = i;
j = distance;
i -= 1;
}
else
{
i -=1;
}

}

^Calculates lowest value got from distance, it does not calculate the value if the wall value is 1

switch (nearest)
{
case 1: //up
Y -= 1;
break;

case 2: //left
X -= 1;
break;

case 3: //down
Y += 1;
break;

case 4: //right
X += 1;
break;
}

^Uses the direction identifier (up=1,left=2,down=3,right=4) to decide what to do

x = 32*X;
y = 32*Y;

global.Xt = X;
global.Yt = Y;

^Just to give me the fresh coords of the square which are then drawn in draw event

if(X != Xgoal || Y != Ygoal)
{
alarm[0] = room_speed * 0.5;
^Checks if target x,y is equal to square's x,y
}
else
{
alarm[1] = 1;
^Sets alarm 1 to randomize next coord to go
}


So now my arrays are more organized and I used switch instead of pile of if statements, but the calculations are the same.. Weird problem but now fixed : D
 

Hyomoto

Member
Much better as well, that's far more legible code and by doing the conversion at the end, it makes it a lot easier to troubleshoot! Like I mentioned before, a lot of complexity could hide an issue and be hard to track down even if it's simple to solve. I'm glad to hear it's working out!
 
Top