Drawing a vector arrow
BlitzMax Forums/BlitzMax Beginners Area/Drawing a vector arrow
| ||
Hello, I would like to ask , how to create some vector arrows with drawline command. As I know the drawline command have 4 arguments. Drawline(x,y,x2,y2) Drawline(50,50,200,200) Drawing the line is easy , but how to draw the arrow head? :) |
| ||
Drawing a triangle on the top is one possibility. You can do this with DrawPoly(). Parameters are 6 values: the x and y values of three koordinates. The easy way, I would prefer, is to use a picture of an arrow, and position it with SetRotation() followed by DrawImage(). |
| ||
By creating an image as arrow and the rotate the image , I see the image correct but if I want dynamically to change the image size with the DrawImageRect() command the arrow stretch and it doesn't appears well. By drawing the line and at the end of the line draw only the head of the arrow , when I try to rotate the head the angle is not correct. I use head_rotate = ATan2(arrow_x - dest_arrow_x, arrow_x - dest_arrow_x) We assume I have one arrow with start at position arrow_x and arrow_y And at points at the position dest_arrow_x and dest_arrow_y Global arrow_x:float Global arrow_y:float Global dest_arrow_x:float Global dest_arrow_y:float Global Arrow_head1:TImage = LoadImage("Arrow_head2.png", MASKEDIMAGE) arrow_x = 50.0 arrow_y = 50.0 dest_arrow_x = 150.0 dest_arrow_y = 50.0 SetLineWidth(2) 'I just draw one line DrawLine(arrow_x, arrow_y, dest_arrow_x, dest_arrow_y) head_rotate = ATan2(arrow_x - dest_arrow_x, arrow_y - dest_arrow_y) 'I use ATan2() to calculate the angle of the line SetRotation(head_rotate) DrawImage(Arrow_head1, dest_arrow_x, dest_arrow_y, 0) SetRotation(0) SetLineWidth(0) The code above loads one arrow head for example one simple triangle The arrow_x and arrow_y are the starting points of the arrow And the dest_arrow_x and dest_arrow_y are the ending points of the arrow. The line commad draws the line correct. The arrow head offset of the position of dest_arrow_x and dest_arrow_y is not correct but we assume this can be corrected if I draw the head at the center of the image of the arrow head but the rotation is wrong. |
| ||
You could draw the arrow as vectors-- that's probably what I would do. If the arrow origin is x,y and the angle is angle, do drawline x,y, x+(cos(angle)*length),y+(cos(angle)*length) for the shaft then draw the head of the arrow at the end of that line using a similar method. Without knowing what exactly you want it's hard to know, but I don't really think setrotation is your friend here. You could also use a similar method to obtain vertices for drawpoly. |
| ||
I am trying to create one vector arrow which is dynamic and points to somewhere. In my level editor I am creating for example the map and in the map there are stairs which leads to somewhere , so this vector arrow will point to the destination. The above code I used it with my variables and I see only a DOT arrow_x = 50.0 arrow_y = 50.0 DrawLine arrow_x, arrow_y, (arrow_x + (Cos(head_rotate) * length)), (arrow_y + (Cos(head_rotate) * length)) [code] I tried this: [code] arrow_x = 50.0 arrow_y = 150.0 dest_arrow_x = 150.0 dest_arrow_y = 18.0 length = 50.0 SetLineWidth(2) SetColor(255, 0, 0) head_rotate = ATan2(arrow_x - dest_arrow_x, arrow_y - dest_arrow_y) SetColor(255, 255, 0) DrawLine(dest_arrow_x + (Cos(head_rotate) * length) , dest_arrow_y + (Cos(head_rotate) * length) , dest_arrow_x + (Cos(head_rotate) * length) - 20, dest_arrow_y + (Cos(head_rotate) * length) - 20) DrawLine(dest_arrow_x + (Cos(head_rotate) * length) , dest_arrow_y + (Cos(head_rotate) * length) , dest_arrow_x + (Cos(head_rotate) * length) - 20, dest_arrow_y + (Cos(head_rotate) * length) + 20) SetColor(255, 255, 255) But the head doesn't rotates correctly. Also the length variable doesn't do anything. |
| ||
ok, first off you can 2 cos. you need a sin and a cos in your drawline Here's some code with full explanation for you :) Graphics 800,600 arrow_x = 50.0 arrow_y = 50.0 length = 50.0 'where rotate is degrees head_rotate = 45 'draw just the line itself SetColor 255,255,255 DrawLine arrow_x, arrow_y, arrow_x + (sin(head_rotate) * length), arrow_y + (Cos(head_rotate) * length) 'draw the arrow arrow_x = 100 DrawArrow(arrow_x, arrow_y, arrow_x + (sin(head_rotate) * length), arrow_y + (Cos(head_rotate) * length) ) 'draw another arrow at a different angle head_rotate = 123 arrow_x = 300 DrawArrow(arrow_x, arrow_y, arrow_x + (sin(head_rotate) * length), arrow_y + (Cos(head_rotate) * length) ) Local k:Int For k = 0 To 360 Step 10 DrawArrowRotate(Rand(100,700), Rand(200,500), Rand(50,100), k) Next Flip WaitKey End Function DrawArrowRotate(xstart:Float, ystart:Float, length:Float, rotate:Float) DrawArrow(xstart, ystart, xstart + (sin(rotate) * length), ystart + (Cos(rotate) * length) ) End Function Function DrawArrow(xstart:Float, ystart:Float, xend:Float, yend:Float) DrawLine xstart, ystart, xend, yend Local xdiv:Float = (xend - xstart) / 100 Local ydiv:Float = (yend - ystart) / 100 'lets say your arrow head is 75% from the start Local headx:Float Local heady:float headx = xstart + xdiv * 75 heady = ystart + ydiv * 75 'draw from start of line to the head in red SetColor 255,0,0 DrawLine xstart, ystart, headx, heady 'And the head is 15% wide Local widex:Float = xdiv * 15 Local widey:Float = ydiv * 15 'draw from the head to the first arrow head point in green SetColor 0,255,0 DrawLine headx, heady, headx - widey, heady + widex 'now the second the other way in blue SetColor 0,0,255 DrawLine headx, heady, headx + widey, heady - widex 'we now have the endpoint and the two point of the arrow, we can draw them in magenta SetColor 255,0,255 DrawLine xend, yend, headx - widey, heady + widex DrawLine xend, yend, headx + widey, heady - widex End Function |
| ||
Here is my solution. The background: The X coordinates are normally based on COS(), the y-coordinates on SIN(). If you additional add a SIN()-value at the x-coordinates and a COS()-value on the y-coordinates, you will always get a offset left or right from your arrow. See the DrawLeft()-function to understand the principe: SuperStrict Graphics 800,600 SeedRnd MilliSecs() DrawText "Sample I: start-position, fixed length and an random angle",50,30 DrawText "Press any Key to change angle",50,50 DrawText "Press ESC Key to continue",50,70 Repeat Local r%=Rand(360) DrawArrow(500,300,150,r) DrawLeft(200,300,150,r) Flip Until WaitKey()=27 SetColor 222,222,222 Cls DrawText "sample II: start-position and free target position",50,30 DrawText "Click Mouse for target position",50,50 DrawText "Press ESC Key to quit",50,70 Flip Repeat Repeat Until MouseHit(1)=0 Repeat Until MouseHit(1) DrawArrowTo 400,300,MouseX(),MouseY() Flip Until KeyHit(Key_ESCAPE) Function DrawLeft(X%,Y%,L#,Angle%) SetColor 222,222,222 Local _Cos#=Cos(Angle) Local _Sin#=Sin(Angle) Local target_X#=_Cos*L Local target_Y#=_Sin*L DrawLine X,Y,X+target_X,Y+target_Y SetColor 0,222,0 DrawLine X+target_X , Y+target_Y , X+target_X - _Sin*20 , Y+ target_Y + _Cos*20 End Function Function DrawArrow(X%,Y%,L#,Angle%) SetColor 222,222,222 Local _Cos#=Cos(Angle) Local _Sin#=Sin(Angle) Local target_X#=_Cos*L Local target_Y#=_Sin*L DrawLine X,Y,X+target_X,Y+target_Y SetColor 0,222,0 DrawLine X+target_X , Y+target_Y , X+target_X- _Cos*20 - _Sin*20 , Y+ target_Y- _Sin*20 + _Cos*20 DrawLine X+target_X , Y+target_Y , X+target_X- _Cos*20 + _Sin*20 , Y+ target_Y- _Sin*20 - _Cos*20 End Function Function DrawArrowTo(X%,Y%,TargetX#,TargetY#) SetColor 222,0,0 DrawOval TargetX-1,TargetY-1,3,3 Local angle#= 270-ATan2(X-TargetX,Y-TargetY) Local l#= Sqr ((X-TargetX)^2+ (Y-TargetY)^2 ) DrawArrow X,Y,L,Angle End Function |
| ||
Yes both of the codes you sent me is what I am looking exactly. I didn't understand how to draw the head of the arrow and make it rotate correctly. Thank you very very much. |
| ||
Hello my friends, I refresh this topic asking a new question. I use your small functions and are the best. Work perfect and I have created nice things in my game. For example I use this one: Function DrawArrowTo(X:Int, Y:Int, TargetX:Float, TargetY:Float, a_red:Byte, a_green:Byte, a_blue:Byte) SetLineWidth(2) SetColor(a_red, a_green, a_blue) Local angle:Float = 270 - ATan2(X - TargetX, Y - TargetY) Local l:Float = Sqr ((X - TargetX) ^ 2 + (Y - TargetY) ^ 2) DrawArrow X, Y, l, angle, a_red, a_green, a_blue End Function Function DrawArrow(X:Int, Y:Int, L:Float, Angle:Int, a_red:Byte, a_green:Byte, a_blue:Byte) SetColor(a_red, a_green, a_blue) Local _Cos:Float = Cos(Angle) Local _Sin#=Sin(Angle) Local target_X#=_Cos*L Local target_Y#=_Sin*L SetLineWidth(2) DrawLine X,Y,X+target_X,Y+target_Y DrawLine X + target_X, Y + target_Y, X + target_X - _Cos * 12 - _Sin * 6, Y + target_Y - _Sin * 12 + _Cos * 6 DrawLine X + target_X, Y + target_Y, X + target_X - _Cos * 12 + _Sin * 6, Y + target_Y - _Sin * 12 - _Cos * 6 SetColor(255, 255, 255) SetLineWidth(1) End Function I have a new question. Is it possible the line which created become dotted or with other pattern for example not line but line with gaps. This is example what I mean. ![]() Thank you :) |
| ||
Hi, Take a look at this in the code archives. |