Help with angles please!

BlitzMax Forums/BlitzMax Beginners Area/Help with angles please!

alanc5(Posted 2007) [#1]
I have a randomly placed number of points on screen and a player. What I am trying to do is move the player to the closest point depending on what key they press, so down would look for all the points closest to 90degrees then sort them by distance and then move the player to the closest point.

The problem is I dont know how to work out the distance between two angles. The problem is that 360 is also 0, so although a point at 350 degress would actually be the closest point to zero, my crappy function would return a distance of 350, instead of 10..and it would break.

Is there a function that will give you the distance between two angles?

So that the distance between a point at 1 degree and a point at 359 degress would actually be 2?

Angles confuse me, well, its the fact that 360 is also zero thats hurting ma brain!

Thanks if anyone can help!

P.S. What I am actually writing is a menu system, it can have any amount of randomly placed options that are selected by pressing up/down/left/right. I need to find the closest option based on the direction of the key press. I've got them all sorted by distance, now I need to arrange them by the angle closest to the target direction. Anyone seen any source similar to this? Ta.


LarsG(Posted 2007) [#2]
first you can check to see if the points are located in the correct "region" of the screen..
ie. if the user presses down, then check for point with a "y" value higher than the players.

then you do pythagoras to get the distance...
(hyp^2 = kat^2 + kat^2)
which would translate into something like this, codewise..
length = sqr(((playerX - pointX)^2) + ((playerY - pointY)^2))


(someone correct me if I'm way off here...)


René(Posted 2007) [#3]
Hm, maybe a sketch would be helpfull?

As far as I understood: I have a selected option (op1). Then I press up. Then it should select the next closest option (op2) with a y-value smaller than the one of the current selected option (op1). Now what do you do with the angles?


tonyg(Posted 2007) [#4]
I'd do what LarsG suggests although doesn't need the sqr as we're going for closest rather than actual distance.
You'd then need atan2 and 'homing' missile code to move from your target to destination point.


Paposo(Posted 2007) [#5]
Hello.

This code help you. Sorry is not tested



The position is modelled in a user type with comments in spanish.
The angle between two positions is obtained with getAngulo()
The distance is obtained with getDistancia()

Bye,
Paposo


Paposo(Posted 2007) [#6]
Edited
Sorry. I create two post equals


alanc5(Posted 2007) [#7]
Hi guys thanks for all the replies, I suppose it was hard to explain what I'm trying to do. Here's what I have so far, you will see what I mean, it's just trying to move to the closest point on screen depending on the direction the user presses. It's nearly there (thanks for the tips) but its just not working right.

If anyone can see what I'm trying to do and can point out where I'm going wrong that would be great.
Thanks again,AL.

	Function FindAngle#( x1#,y1#,x2#,y2# )
		
		a#=ATan2(x2-x1,y2-y1)
		Return 180-a#
		
	End Function
	
	Function Distance#(x#,y#,z#,x2#,y2#,z2#)
		
		value#=Sqr((x#-x2#)*(x#-x2#)+(y#-y2#)*(y#-y2#)+(z#-z2#)*(z#-z2#))
		Return value#
		
	End Function

	Function TurnDirection(facing#,pivot#)
		
		diff = facing#-pivot
		While diff>180 
			diff=diff-360
		Wend
		While diff<-180
			diff=diff+360
		Wend
		If diff<0 Then Return -1 Else Return 1
		Return 0
		
	End Function
	
	Type LocationBox
		
		Field x:Float
		Field y:Float
		Field width:Int
		Field height:Int
		Field angle:Float
		Field distance:Float
		
		Method Compare(otherObject:Object)
		
			l:LocationBox = LocationBox(otherObject)
			Return distance - l.distance
			
		End Method
	
		
	End Type

	Type Scaler
		'
		'  The scalerbox is a cursor type object that also holds a list of on screen targets
		'
		'	
		Field x:Float ' current x position
		Field y:Float ' current y position
		
		Field targetX:Float
		Field targetY:Float
		
		Field newx1# , newy1# , plong# , phigh# , dist# , highv# , longv#		
			
		Field list:TList=CreateList()
		
		Field closest:LocationBox=Null
		Field minang#=999'
		Field mindist#=9999'

		
		Method SetTarget(x,y)
			'
			'  Sets the initial x,y coordinates of the target
			'
			targetX=x
			targetY=y
				
		End Method
		
		Method FindTarget(direction)
			'
			' Pass this a direction and it will setup new target coordinates by
			' parsing the target list and finding the closest object with an angle
			' closest to the required direction
			'
			' 0: Up(0)
			' 1: Right(90)
			' 2: Down(180)
			' 3: Left(270)
			'
			'
			'
			For a:LocationBox=EachIn list
				
				a.angle=FindAngle( x, y, a.x, a.y )
				a.distance=Distance( a.x, a.y, 0, x, y, 0)
				'Print a.angle
				'Print a.distance+", "+a.angle		
			Next
			
			'Print ""
			
			'SortList list ' list is now sorted with the closest nodes at the top
			
			' now we need to find the node with the angle closest to the supplied angle
			
			
			minang#=999'
			mindist#=9999'
			closest=Null
			For a:LocationBox=EachIn list
	
			'		
			'      360/0
			'
			'  270	 x	  90
			'
			'		180
			'				
			'   Print a.angle
			'	Print a.distance+", "+a.angle
			'
				If direction=1
					If a.x>x
						If Abs(a.angle-90)>10 And Abs(a.angle-90)<50 And a.distance>10 And a.distance<mindist
							mingang=Abs(a.angle-90)
							mindist=a.distance
							closest=a
						End If		
					End If
				End If
				
				If direction=2
					If a.y>y
						If Abs(a.angle-180)>10 And Abs(a.angle-180)<50 And a.distance>10 And a.distance<mindist
							mingang=Abs(a.angle-180)
							mindist=a.distance
							closest=a
						End If		
					End If
				End If
				
				If direction=3
					If a.x<x
						If Abs(a.angle-270)>10 And Abs(a.angle-270)<50 And a.distance>10 And a.distance<mindist
							mingang=Abs(a.angle-270)
							mindist=a.distance
							closest=a
						End If		
					End If
				End If
				
				If direction=4
					If a.y<y
						If a.angle>270 Then
							If Abs(a.angle-360)>10 And Abs(a.angle-360)<50 And a.distance>10 And a.distance<mindist
								mingang=Abs(a.angle-360)
								mindist=a.distance
								closest=a
							End If
						Else
							If a.angle>10 And a.angle<50 And a.distance>10 And a.distance<mindist
								mingang=a.angle
								mindist=a.distance
								closest=a
							End If
						End If		
					End If
				End If

				
				If closest<>Null
				targetX=closest.x
				targetY=closest.y
				End If
				
			Next
		
		End Method
		
		Method AddTarget(x, y, width, height)
			'
			'  Adds a new target for the cursor
			'				
			locations:LocationBox = New LocationBox
			locations.x = x
			locations.y = y
			locations.width = width
			locations.height = height
			
			ListAddLast list,locations
			
		End Method
		
		Method Update()
			'
			'  Called every frame, moves the cursor to the current target coordinates.
			'		
			plong=x-(adjustx#+targetX)
			phigh=y-(adjusty#+targetY)
				
			If phigh<0 Then highv=-1 Else highv=1
			If plong<0 Then longv=-1 Else longv=1
			
			dist=0+Sqr((plong*longv)+(phigh*highv))
			
			adjustx:+(plong/dist)	
			adjusty:+(phigh/dist)	
		
			x:-adjustx	
			y:-adjusty
			
			For a:LocationBox=EachIn list
				DrawRect a.x, a.y, a.width, a.height
				DrawText Abs(a.angle-90), a.x, a.y+20		
			Next
			
For a:LocationBox=EachIn list
				
				a.angle=FindAngle( x, y, a.x, a.y )
				a.distance=Distance( a.x, a.y, 0, x, y, 0)
				'Print a.angle
				'Print a.distance+", "+a.angle	
				
DrawText mingang+","+mindist,200,200
			Next	
						
		End Method
	
	End Type

	Type hbox Extends Scaler
	
		Field image:TImage
		
		Method New()' constructor
			
			'DrawText "Initialised" , 0 , 0
			ImageName:String="http::www.2dgamecreators.com/tutorials/gameprogramming/basic/blobship_1-1.png"
			image:TImage=LoadImage(LoadBank(ImageName))
	
			If image=Null
	  			Print "Not able to load image file. Program aborting"
	  			End
			EndIf
		
		End Method
			
		Method Delete() 'destructor
		
			'DrawText "Terminated" , 0 , 20
			
		End Method
		
		Method Render()
					
			Update()
			Update()
			
			'DrawText x+" "+y, 100,100		
			'DrawText x , 100 , 100
			
			SetBlend(ALPHABLEND)
			SetAlpha(.75)
			DrawImage image, x-ImageWidth(image)/2, y-ImageHeight(image)/2
			SetAlpha(1)
			SetBlend(SOLIDBLEND)
			
		End Method
		
	End Type

	Graphics 1024,768,32
	
	SetColor 255,0,255
	
	test:hbox = New hbox
	
	test.AddTarget(50, 50,  10, 10)
	test.AddTarget(150, 100, 10, 10)
	test.AddTarget(250, 200, 10, 10)
	test.AddTarget(650, 100, 10, 10)
	test.AddTarget(50, 400, 10, 10)
	test.AddTarget(450, 500, 10, 10)
	test.AddTarget(750, 600, 10, 10)
	
	'test.SetTarget(10, 10)
	
	test.FindTarget(1)

	
	
	While Not KeyHit(KEY_ESCAPE)
		
		test.Render()
		'test.FindTarget(2)
		
		'If KeyHit(KEY_RIGHT) test.SetTarget(900, 20)

		If KeyHit(KEY_RIGHT) test.FindTarget(1)

If KeyHit(KEY_DOWN) test.FindTarget(2)
If KeyHit(KEY_LEFT) test.FindTarget(3)
If KeyHit(KEY_UP) test.FindTarget(4)

		
		'x1#=0
		'y1#=0
		'x2#=MouseX()
		'y2#=MouseY()
		'z1#=0
		'z2#=0
		
		'DrawText Sqr((x1#-x2#)*(x1#-x2#)+(y1#-y2#)*(y1#-y2#)+(z1#-z2#)*(z1#-z2#)),0,0
		'DrawText FindAngle( 1024/2,768/2,MouseX(),MouseY() ),500,500
		
		Flip 1
		Cls
		
	Wend

'WaitKey