Help with angles please!
BlitzMax Forums/BlitzMax Beginners Area/Help with angles please!
| ||
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. |
| ||
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...) |
| ||
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? |
| ||
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. |
| ||
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 |
| ||
Edited Sorry. I create two post equals |
| ||
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 |