Home   Help Search Login Register  

Author Topic: Find the shortest way...  (Read 898 times)

0 Members and 1 Guest are viewing this topic.

Offline Blanco

  • Former Staff
  • ****
Find the shortest way...
« on: 10 Jun 2005, 02:45:47 »
Hello,

I hope I can explain this....

I have a script to make a object turn (via setdir) in a random direction between a maximum left & right arc.
Suppose my object's direction is 313 and the max step is 80 degrees, than the object can turn between  azimuth 33 & 233...

Because :
1)
313 - 80 = 233
2)
313 + 80 = 393, but I have to correct this so the result stay between 360 degrees. So 393 -360 = 33

So far so good, that works fine.
The problem is when the old heading is below 360 degrees and the new heading is above 360 degrees, the object turns counterclockwise, but the shortest way is clockwise.
How can I calculate this so the object always takes the shortest turn to get there?

Code: [Select]
_mg = _this select 0
_mainhdg = getdir _mg


_step = 80

;calculate the random heading the first time
_newhdg = (_mainhdg + ((random _step) - (random _step)))
? _newhdg < 0: _newhdg = _newhdg + 360
? _newhdg > 360: _newhdg = _newhdg - 360


#searchloop
? (getdir _mg - _newhdg) < 10 and (getdir _mg - _newhdg) > - 10: goto "pauze"
? (getdir _mg - _newhdg) > 0: _mg setdir ((getdir _mg) - 1)
? (getdir _mg - _newhdg) < 0: _mg setdir ((getdir _mg) + 1)

player globalchat format ["MH=%1   NH =%2  DIR= %3",_mainhdg,_newhdg,getdir _mg]
~0.09
goto "searchloop"

#pauze
_newhdg = (_mainhdg + ((random _step) - (random _step)))
?_newhdg > 360 : _newhdg = _newhdg - 360
?_newhdg < 0 : _newhdg = _newhdg + 360
~2 + random 2
goto "searchloop"

Actually, I think this is a shitty code, I'm sure this can be done easier, but I'm bad with math... :-\
Please help me out.


« Last Edit: 10 Jun 2005, 13:36:56 by Blanco »
Search or search or search before you ask.

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #1 on: 10 Jun 2005, 12:21:24 »
Blast... I got around this exact problem a while back, can't think what i did with the code... I'll have a think and see if i can remember what i did. It wasnt over difficult at any rate.

Offline THobson

  • OFPEC Patron
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #2 on: 10 Jun 2005, 12:31:04 »
try something like this (note: I have made up the names of some variables and see that I have used _step and so have you but for something else):



Code: [Select]
_change = _newDir - _oldDir

if (abs(_change) > (abs (_change + 360) % 360)) then {_change = (_change + 360) % 360}

_step = _change/abs(_change)


#loop

_mg setDir ((getDir _mg) + _step)

if (abs((getDir _mg) - _newDir) > abs(_step)) then {goto"loop"}

exit



EDIT:

Instead of the loop you could use a while:


Code: [Select]
_change = _newDir - _oldDir

if (abs(_change) > (abs (_change + 360) % 360)) then {_change = (_change + 360) % 360}

_step = _change/abs(_change)


while {abs((getDir _mg) - _newDir) > abs(_step)} do {_mg setDir ((getDir _mg) + _step)}

exit

« Last Edit: 10 Jun 2005, 13:51:15 by THobson »

Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #3 on: 10 Jun 2005, 13:25:09 »
Yes, I think THobson has got it there. Abs and the modulus stir vague memories...

This topic reminds me of a function I've been meaning to submit, ClockwiseOf.sqf. It doesn't seem directly applicable to your situation, but then again it's sort of related. Anyhow, it's in the funcs depot now.

And completely unrelated to this topic, i just found out that in a script, any variables you initialise within the curly braces of an 'if... then {}' clause (or a while, or anything else) are local to that clause only. I know that this is how it works in java, but it's interesting to see that it happens in FP script too. For example, try this:

if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]


Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re:Find the shortest way...
« Reply #4 on: 10 Jun 2005, 13:38:13 »
Um... correct me if I'm wrong but that snippet by THobson always returns a positive value for _step.
urp!

Offline THobson

  • OFPEC Patron
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #5 on: 10 Jun 2005, 13:47:15 »
Peanut - it shouldn't

Try putting

_newDir = 5
_oldDir = 10

_change = -5

5 is < 355 so _change stays as -5

-5/(abs(-5))  = -1
 
« Last Edit: 10 Jun 2005, 13:47:31 by THobson »

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re:Find the shortest way...
« Reply #6 on: 10 Jun 2005, 13:58:22 »
Okay, I was wrong about that, but try

_newDir = 340
_oldDir = 10


_change = 330

_step = 1,

which is the wrong way.




« Last Edit: 10 Jun 2005, 14:30:39 by Mr.Peanut »
urp!

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re:Find the shortest way...
« Reply #7 on: 10 Jun 2005, 14:22:58 »
Blanco: here's my own crappy, inelegant code:

Code: [Select]
_mg = _this select 0
_mainhdg = getdir _mg

;search parameters
_step = 80
_twostep = _step * 2
_tol = 10
_inc = 1

;calculate the random heading the first time
_newhdg = (_mainhdg + _step - (random _twostep))
;convert heading to 0-360
_newhdg = (_newhdg mod 360)
? _newhdg < 0:_newhdg = _newhdg + 360

#searchloop
_mgdir = getdir _mg
? (abs(_mgdir - _newhdg) < _tol): goto "pauze"
if (_mgdir > _newhdg) then {goto "skip1"}
_rturn = _mgdir - newhdg
_lturn = (_mgdir + 360) - _newhdg
goto "skip2"
#skip1
_rturn = (_newhdg + 360) - _mgdir
_lturn = _newhdg - _mgdir
#skip2
if (abs(_lturn) < abs(_rturn)) then {_mgdir = _mgdir - _inc} else {_mgdir = _mgdir + _inc}
;convert heading to 0-360
_mgdir = (_mgdir mod 360)
? _mgdir < 0:_mgdir = _mgdir + 360
;done
_obj setdir _mgdir
player globalchat format ["MH=%1  NH =%2  DIR= %3",_mainhdg,_newhdg,getdir _obj]
~0.09
goto "searchloop"

#pauze
_newhdg = (_mainhdg + _step - (random _twostep))
_newhdg = (_newhdg mod 360)
?_newhdg < 0:_newhdg = _newhdg + 360
~2 + random 2
goto "searchloop"
« Last Edit: 10 Jun 2005, 15:01:03 by Mr.Peanut »
urp!

Offline Mr.Peanut

  • Former Staff
  • ****
  • urp!
Re:Find the shortest way...
« Reply #8 on: 10 Jun 2005, 14:24:35 »
So Fragorl,

As long as you declare the variable first, then you are safe?
i.e.:

myVar = 0
if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]



if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]
urp!

Offline Blanco

  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #9 on: 10 Jun 2005, 14:25:36 »
Thx, it seems to work but I have to use the loop method because I need the delay and don't know how I can implement that delay in the while-do thingy. (it's chinese 4 me)

I need it for a scripted searchlight script (based on Mgspot.sqs from Sui) using the light of a machinegun. When the player runs through the lightbeam, the gunner sounds the alarm and try to kill you. Once spotted, the light follows whereever you go.
Not really fullproof because it still follows you when you hide behind an obstacle or when you are far away,... I need a LOS script for that.  :-\
I have an idea to solve this without a LOS script, but it requires lots of testing.

Thx alot all of you.


 

« Last Edit: 10 Jun 2005, 14:29:43 by Blanco »
Search or search or search before you ask.

Offline THobson

  • OFPEC Patron
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #10 on: 10 Jun 2005, 17:33:53 »
Well spotted Mr. Peanut.  That will teach me not to just dash off a script.  Here is a better version:

Code: [Select]
_change = _newDir - _oldDir

if (abs(_change) > (abs (_change + 360) % 360)) then {_change = (_change + 360) % 360}
if (_change > 180) then {_change = _change - 360}
if (_change < -180) then {_change = _change + 360}

_step = _change/abs(_change)


#loop

_mg setDir ((getDir _mg) + _step)

if (abs((getDir _mg) - _newDir) > abs(_step)) then {goto"loop"}

exit




Offline Fragorl

  • Coding Team
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #11 on: 11 Jun 2005, 00:44:52 »
So Fragorl,

As long as you declare the variable first, then you are safe?
i.e.:

myVar = 0
if (true) then {myVar = 5; hint format["%1",myVar];}
~1
hint format["%1",myVar]

Exactly. In that situation, you are safe. For both hints, you get out the value '5'. This works identically to java, and is a sensible way to do it when you think about it.

I will make a note in the command reference.
« Last Edit: 11 Jun 2005, 00:45:27 by Fragorl »

Offline THobson

  • OFPEC Patron
  • Former Staff
  • ****
Re:Find the shortest way...
« Reply #12 on: 11 Jun 2005, 08:46:06 »
A good additon to the knowledge base.  I don't know java, but I had come across what I then saw as the problem of not being able to initialise a new variable in an if statement.  I had not realised the variable was being created, but only with a very limited scope.  I just knew that it didn't exist after the statement so I now intialise them before the if statement, which often has a side effect of not requiring an else caluse.  What I started writing as:

if (condition) then {_var = a} else {_var = b}

I now write as:

_var = b
if (condition) then {_var = a}