HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Angle problem for formations.

01-27-2005, 10:21 PM#1
iNfraNe
Im trying to make a squad system so you can move around footmen (or any other) in formations. However, the system I have made so far works, but only for angles close to 0 (90 if you count in the facing - 90 I have made)

Code:
function SquadPositionChild1 takes nothing returns nothing
  set udg_tempIndex = udg_tempIndex + 1
  set udg_tempX = ((udg_tempX * (udg_tempIndex - 1)) + GetUnitX(GetEnumUnit())) / udg_tempIndex
  set udg_tempY = ((udg_tempY * (udg_tempIndex - 1)) + GetUnitY(GetEnumUnit())) / udg_tempIndex
endfunction

function GetSquadPosition takes integer index returns location
  local location loc
  set udg_tempIndex = 0
  call ForGroup(udg_Squads[index],function SquadPositionChild1)
  set loc = Location(udg_tempX, udg_tempY)
  return loc
endfunction

function FormationChild1 takes nothing returns nothing
  local location loc
  local integer int = 0
  local real col = 0
  local real row = 0
  local real x = 0
  local real y = 0
  local real angle = 0
  local real s = 0
  set udg_tempIndex = udg_tempIndex + 1

  set int = udg_tempIndex
    loop
      exitwhen udg_tempInt >= int
      set int = int - udg_tempInt
      set row = row + 1
    endloop

  set col = int - ((I2R(udg_tempInt) + 1) / 2)
  set row = row - ((I2R(R2I(I2R(CountUnitsInGroup(udg_Squads[udg_tempGlobalIndex])) / I2R(udg_tempInt))) - 1) / 2)
  set x = (col * 120)
  set y = (row * 120)
  set s = SquareRoot(Pow(x,2) + Pow(y,2))
  set angle = Atan2BJ(y,x)
  set angle = angle + udg_tempReal

  if (x<0 and y<0) then
    set x = -CosBJ(angle) * s
    set y = -SinBJ(angle) * s
  endif
  if (x<0 and y>=0) then
    set x = -CosBJ(angle) * s
    set y = SinBJ(angle) * s
  endif
  if (x>=0 and y<0) then
    set x = CosBJ(angle) * s
    set y = -SinBJ(angle) * s
  endif
  if (x>=0 and y>=0) then
    set x = CosBJ(angle) * s
    set y = SinBJ(angle) * s
  endif

  set x = GetLocationX(udg_tempPoint) + x
  set y = GetLocationY(udg_tempPoint) + y 
  set loc = Location(x,y)

  call IssuePointOrderLoc(GetEnumUnit(),"move",loc)
  call RemoveLocation(loc)
  set loc = null
endfunction

function TakeFormation takes integer index, integer RowCs, real facing returns nothing
  set udg_tempPoint = GetSquadPosition(index)
  set udg_tempInt = RowCs
  set udg_tempReal = (facing - 90)
  set udg_tempIndex = 0
  set udg_tempGlobalIndex = index
  call ForGroup(udg_Squads[index],function FormationChild1)
  call RemoveLocation(udg_tempPoint)
endfunction
set udg_tempReal = (facing - 90) I made it this way cause always 90 degrees means UP , which it is now.

I have tested alot and I see the problem lies in:
Code:
  set angle = Atan2BJ(y,x)
  set angle = angle + udg_tempReal

  if (x<0 and y<0) then
    set x = -CosBJ(angle) * s
    set y = -SinBJ(angle) * s
  endif
  if (x<0 and y>=0) then
    set x = -CosBJ(angle) * s
    set y = SinBJ(angle) * s
  endif
  if (x>=0 and y<0) then
    set x = CosBJ(angle) * s
    set y = -SinBJ(angle) * s
  endif
  if (x>=0 and y>=0) then
    set x = CosBJ(angle) * s
    set y = SinBJ(angle) * s
  endif
The problem is that the footman start moving to weird positions as I further increase the angle.
Im quite puzzled on how to fix this annoying problem. Seeing -y/x gives the same answer as y/-x and y/x is same as -y/-x. Could anyone help me out a little with this?
01-27-2005, 11:10 PM#2
curi
oops i deleted my post by accident, meant to edit the other one. oh well.
01-27-2005, 11:19 PM#3
iNfraNe
Quote:
Originally Posted by curi
cos and sin can return negative numbers if they need to. so you shouldn't have 4 cases. just replace this with:

set x = CosBJ(angle) * s
set y = SinBJ(angle) * s

This is incorrect because:

if you have Atan (arctangens = invert tangens, gives angle from y/x). It can either be positive or negative. Now seeing, like I said, -y/x and y/-x gives the same value, you need my stupid if/then/elses.

if x<0 then
set x = -CosBJ(angle) * s
else
set x = CosBJ(angle) * s
endif

if y<0 then
set y = -SinBJ(angle) * s
else
set y = SinBJ(angle) * s
endif

would prolly do the trick aswell.

EDIT: found a stupid mistake ... I didnt link the if/then/elses , so when y or x changed from negative to positive or otherwise, it would be changed again. However, this just makes the footies move even more weird...

EDIT EDIT: I found a solution, and it seemed you were abit right after all. I replaced the lines with:
set x = -CosBJ(angle) * s
set y = -SinBJ(angle) * s
and somehow it worked. I dont have any idea why tho, someone cares to explain?
01-28-2005, 04:36 AM#4
curi
Facing angles work correctly. 0 degrees is east/right. 90 is up/north. So you shouldn't adjust that.

I've tested and atan2 works the same way, and works in all directions. atan only returns values in a 180 degree range like you say, but atan2 is fancy.

I don't understand how your code works..
01-28-2005, 10:32 AM#5
iNfraNe
I know facing angles work correctly, but my code has a front at the top instead of a front at the right side, so I had to turn it. It works yay, but why the -Cos and -Sin ... I just cant see why... (it does look alot better than if/then/elses btw ^_^)
01-28-2005, 11:38 AM#6
curi
If you want the front to be up, then shouldn't you *add* 90? so that 0 will get turned into 90.

I think by subtracting 90 instead of adding, you end up 180 degrees away from where you wanted. Then the negatives fix that.
01-28-2005, 02:14 PM#7
iNfraNe
nope. Look:

0 = up, but normally 90 = up...
so when I enter 90 it will make front left, but it must be up, so substracting 90 works. Not that it matters 2 much, it only matters when units die and the formation is not complete. But thats np anyway, I really wanna understand this. My problem is:

lets say x = -1 and y=1

Sqrt = Square Root

atan2 returns: -45
cos returns: Sqrt(1/2) so -cos returns -Sqrt(1/2)
sin returns: -Sqrt(1/2) so -sin returns Sqrt(1/2)

This is valid with the starting points, HOWEVER:

lets say x=1 and y=-1

atan2 returns: -45
cos returns: Sqrt(1/2) so -cos returns -Sqrt(1/2)
sin returns: -Sqrt(1/2) so -sin returns Sqrt(1/2)

BUT THIS IS NOT THE CASE!!! I DONT UNDERSTAND... WHY DOES IT WORK (yes, weird question :P)
01-28-2005, 04:36 PM#8
curi
doesn't it work like this:

the user who calls your function (you) gives an angle that he wants the group to face. 0 is supposed to mean up, cause you wanted it that way. so say you tell the group to face 0 and you want it to face up. now, to adjust this to normal angles, you must add 90.
01-28-2005, 05:04 PM#9
iNfraNe
nono :P its the other way around. I made the function the way that the front is up at 0 angle (thats just the way it is;) cant help it) but I want the front to be right at angle 0, so I decrease with 90.