GetMouseAngle(X.f,Y.f)

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

GetMouseAngle(X.f,Y.f)

Post by DriakTravo »

I would like a command to find the mouse angle in relation to a pair of coordinates. If the 2 were 0 and 0 > GetMouseAngle(0,0) <. And the mouse was at 10,and 10, then the command would return 45, if the mouse was at 10,0 it would return 0, and if the mouse was at 0,10, it would return 90 and so on.
freedimension
Enthusiast
Enthusiast
Posts: 613
Joined: Tue May 06, 2003 2:50 pm
Location: Germany
Contact:

Post by freedimension »

A little too special, don't you think?
Try these (secret) commands:
Procedure
EndProcedure

You won't regret it ;-)

Edit:
A little helper:
Inside the procedure should go the function ATan2. As PB doesn't support this, you could go with ATan(Y/X).
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

here is my trouble:

Code: Select all

InitSprite()
InitMouse()

OpenScreen(800,600,32,"")

Structure bullet
  X.f
  Y.f
  XS.f
  YS.f
EndStructure

NewList bullets.bullet()

Procedure Addbullet(X.f,Y.f,XS.f,YS.f)
  AddElement(Bullets())
  Bullets()\X = X
  Bullets()\Y = Y
  Bullets()\XS = XS
  Bullets()\YS = YS
EndProcedure

Global mouseangle, BulletSpeed
BulletSpeed = 10

Procedure GetMouseAngle()
  ;Put code here that gets the angle in relation to the center of the screen
EndProcedure

Repeat
  ClearScreen(0,0,0)
  ExamineMouse()
  
  If CountList(bullets()) > 1
    ResetList(Bullets())
    While NextElement(Bullets())
      StartDrawing(ScreenOutput())
        Line(Bullets()\X,Bullets()\Y,Bullets()\XS,Bullets()\YS,RGB(Random(255),Random(255),0))
        Circle(MouseX(),MouseY(),2,RGB(0,255,255))
      StopDrawing()
      Bullets()\X + Bullets()\XS
      Bullets()\Y + Bullets()\YS
      If Bullets()\X > 800 + Bullets()\XS
        DeleteElement(Bullets())
      EndIf
      If Bullets()\X < 0 - Bullets()\XS
        DeleteElement(Bullets())
      EndIf
      If Bullets()\Y > 600 + Bullets()\YS
        DeleteElement(Bullets())
      EndIf
      If Bullets()\Y < 0 - Bullets()\YS
        DeleteElement(Bullets())
      EndIf
    Wend
  EndIf
  
  If MouseButton(2) = 1
    End
  ElseIf MouseButton(1) = 1
    Angle = GetMouseAngle()
    SpeedX.f = Sin(GetMouseAngle()*(3.14/180))*10
    SpeedY.f = Cos(GetMouseAngle()*(3.14/180))*10
    dudecounter + 1
    If dudecounter = 10
      dudecounter = 0
      Addbullet(400,300,SpeedX,SpeedY)
    EndIf 
  EndIf
  
  FlipBuffers()
ForEver
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: GetMouseAngle(X.f,Y.f)

Post by Danilo »

DriakTravo wrote:I would like a command to find the mouse angle in relation to a
pair of coordinates.
This is always needed for game programming.... would help alot
if Fred could implement it natively for use on all platforms and
in ASM (faster).

Code: Select all

;
; by Rob, 07.10.03 - german forum
;
; returns angle between 2 points and [0,0] in DEGREE
;
Procedure.f winkel(x1.f,y1.f,x2.f,y2.f)
  a.f = x2-x1 
  b.f = y2-y1 
  c.f = Sqr(a*a+b*b) 
  winkel.f = ACos(a/c)*57.29577 
  If y1 < y2 : winkel=360-winkel : EndIf 
  ProcedureReturn winkel 
EndProcedure

Code: Select all

;
; by Rob, 07.10.03 - german forum
;
; returns angle between 2 points and [0,0] in RADIANS
;
Procedure.f bwinkel(x1.f,y1.f,x2.f,y2.f) 
  a.f = x2-x1 
  b.f = y2-y1 
  c.f = Sqr(a*a+b*b) 
  winkel.f = ACos(a/c)*57.29577 
  If y1 < y2 : winkel=360-winkel : EndIf 
  winkel*0.017453 
  ProcedureReturn winkel 
EndProcedure

Simple example:

Code: Select all

;
; by Rob, 08.10.03 - german forum
;
; http://www.robsite.de/php/pureboard/viewtopic.php?t=2489
;
Procedure.f winkel(x1.f,y1.f,x2.f,y2.f)
  a.f = x2-x1 
  b.f = y2-y1 
  c.f = Sqr(a*a+b*b) 
  winkel.f = ACos(a/c)*57.29577 
  If y1 < y2 : winkel=360-winkel : EndIf 
  ProcedureReturn winkel 
EndProcedure 

x_window = 200 
y_window = 200 

OpenWindow(0,0,0,x_window,y_window,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Rotation") 
bgcolor = GetSysColor_(#COLOR_BTNFACE) 

CreateGadgetList(WindowID()) 
TrackBarGadget(0,0,y_window-18,x_window,18,0,200) 

x_mitte = x_window/2 
y_mitte = y_window/2 
punktzahl = 1000 
speed.f = 1 
SetGadgetState(0,150) 

Dim x.f(punktzahl) ; x 
Dim y.f(punktzahl) ; y 
Dim w.f(punktzahl) ; winkel 
Dim r.f(punktzahl) ; radius 
For i = 1 To punktzahl ; Werte zuweisen 
  x(i) = Random(x_window) 
  y(i) = Random(y_window) 
  w(i) = winkel(x(i),y(i),x_mitte,y_mitte) 
  r(i) = Sqr(Pow(x(i)-x_mitte,2)+Pow(y(i)-y_mitte,2)) 
Next 


Repeat 

  StartDrawing(WindowOutput()) 
  For i = 1 To punktzahl 
    If x(i) < x_window And x(i) > 0 And y(i) < y_window-20 And y(i) > 0 
      Plot(x(i),y(i),bgcolor)    
    EndIf 
    
    w(i) = (w(i)+speed) ; Winkel ändern 
    If w(i) >= 360 : w(i) = 0 : EndIf 
    x(i) = r(i) * Cos(w(i)*0.017453) + x_mitte ; Drehen 
    y(i) = r(i) * Sin(w(i)*0.017453) + y_mitte    
    
    If x(i) < x_window And x(i) > 0 And y(i) < y_window-20 And y(i) > 0 
      Plot(x(i),y(i),RGB(0,0,0))    
    EndIf 
  Next 
  StopDrawing() 
  
  eventid = WindowEvent() 
  If eventid = #PB_Event_Gadget 
    If EventGadgetID() = 0 
      speed = (GetGadgetState(0)-100)/50 
    EndIf 
  EndIf 
    
  Delay(1) 
Until eventid = #PB_Event_CloseWindow
cya,
...Danilo
...:-=< http://codedan.net/work >=-:...
-= FaceBook.com/DaniloKrahn =-
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Post by Danilo »

Another thing you always need in game programming:
Sinus and Cosinus of an angle in DEGREE, not radians!

Fred wanted to implement this some time ago, so here
we go again to remeber:

Code: Select all

Procedure.f DSin(angle_in_degree.f)
  ; returns Sinus of 'angle in degree'
  ProcedureReturn Sin(angle_in_degree*(2*3.14159265/360))
EndProcedure 


Procedure.f DCos(angle_in_degree.f) 
  ; returns CoSinus of 'angle in degree'
  ProcedureReturn Cos(angle_in_degree*(2*3.14159265/360))
EndProcedure
Shouldnt be too hard to implement in ASM/FPU for all
platforms... :D


Example of use:

Code: Select all

;>------------------------------------
;
; by Danilo, 20.11.2003 - german forum
;
;>------------------------------------

;#Width  = 1600
;#Height = 1200
#Width  = 1280
#Height = 1024
;#Width  = 1024
;#Height = 768
;#Width  = 800
;#Height = 600

#rotator_speed.f = 3

#max_objects = 10

Structure _OBJ
  x.l
  y.l
  Transparency.l
  Degree.f
EndStructure

Dim Objects._OBJ(#max_objects)


Procedure.f DSin(angle_in_degree.f)
  ; returns Sinus of 'angle in degree'
  ProcedureReturn Sin(angle_in_degree*(2*3.14159265/360))
EndProcedure 


Procedure.f DCos(angle_in_degree.f) 
  ; returns CoSinus of 'angle in degree'
  ProcedureReturn Cos(angle_in_degree*(2*3.14159265/360))
EndProcedure


Procedure ObjectSound(x)
  Beep_(800,50)
EndProcedure


Procedure MakeSprites()

  h = #Height-100

  If CreateSprite(1,512,512,#PB_Sprite_Texture)=0 Or CreateSprite(2,256,256,#PB_Sprite_Texture)=0 Or CreateSprite(3,h,h)=0
    CloseScreen()
    MessageRequester("ERROR","Cant create Sprites !",#MB_ICONERROR)
    End
  EndIf

  If CreateSprite3D(1,1)=0 Or CreateSprite3D(2,2)=0
    CloseScreen()
    MessageRequester("ERROR","Cant create 3D Sprites !",#MB_ICONERROR)
    End
  EndIf

  ; Radar rotator (green > black)
  StartDrawing(SpriteOutput(1))
    angle.f=90
    Repeat
      Line(255,255,DSin(angle)*255.0,DCos(angle)*255,RGB(0,Int(angle*2.8),0))
      angle.f - 0.001
    Until angle <=0
  StopDrawing()

  ; Radar objects
  StartDrawing(SpriteOutput(2))
    For a = 127 To 0 Step -1
      Circle(127,127,a,RGB(255-2*a,255-2*a,255-2*a))
    Next a
  StopDrawing()
  ZoomSprite3D(2,32,32)

  ; Radar chassis
  StartDrawing(SpriteOutput(3))
    Circle(h/2,h/2,h/2,RGB($40,$40,$40))
    Circle(h/2,h/2,h/2-10,RGB($00,$00,$00))
    DrawingMode(4)
    For a = 0 To 5
      Circle(h/2,h/2,h/10*a,RGB($40,$40,$40))
    Next a
    For a = -2 To 2
      Line(0,h/2+a,h,0,RGB($40,$40,$40))
    Next a
    For a = -2 To 2
      Line(h/2+a,0,0,h,RGB($40,$40,$40))
    Next a
    For a = 30 To 330 Step 30
      Line(h/2,h/2,DSin(a)*h/2,DCos(a)*h/2,RGB($40,$40,$40))
    Next a
  StopDrawing()

EndProcedure


;- Start
If InitKeyboard()=0 Or InitSprite()=0 Or InitSprite3D()=0
  MessageRequester("ERROR","Cant init DirectX !",#MB_ICONERROR)
EndIf

If OpenScreen(#Width,#Height,32,"Radar")=0
  If OpenScreen(#Width,#Height,24,"Radar")=0
    If OpenScreen(#Width,#Height,16,"Radar")=0
      MessageRequester("ERROR","Cant open screen !",#MB_ICONERROR)
EndIf:EndIf:EndIf


MakeSprites()


;- Init objects
Objects(1)\x      = (#Width/2-16)  -50
Objects(1)\y      = (#Height/2-16) -20
Objects(1)\Degree = 110

Objects(2)\x      = (#Width/2-16)  +100
Objects(2)\y      = (#Height/2-16) -80
Objects(2)\Degree = 230

Objects(3)\x      = (#Width/2-16)  +50
Objects(3)\y      = (#Height/2-16) +#Height/4
Objects(3)\Degree = 350

Objects(4)\x      = (#Width/2-16)  -#Height/4+50
Objects(4)\y      = (#Height/2-16) +#Height/4+50
Objects(4)\Degree = 30

Objects(5)\x      = (#Width/2-16)  -20
Objects(5)\y      = (#Height/2-16) -#Height/2+150
Objects(5)\Degree = 170

;- Main loop
Repeat
  time = TimeGetTime_()
  ExamineKeyboard()
  If IsScreenActive() And ScreenDeactivated = #FALSE
    Angle.f - #rotator_speed
    If Angle < 0:Angle+360:EndIf    
    ClearScreen(0,0,0)
    Start3D()
      Sprite3DQuality(1)
      ZoomSprite3D(1,#Height-100,#Height-100)
      RotateSprite3D(1,Angle,1)
      DisplaySprite3D(1,(#Width-#Height)/2+50,50)

      Sprite3DBlendingMode(5,2)
      ; Objects
      For a = 0 To #max_objects
        If Objects(a)\x Or Objects(a)\y
          DisplaySprite3D(2,Objects(a)\x,Objects(a)\y,Objects(a)\Transparency)
        EndIf
      Next a
    Stop3D()
    
    DisplayTransparentSprite(3,(#Width-#Height)/2+50,50)

    For a = 0 To #max_objects
      If Objects(a)\x Or Objects(a)\y
        If Angle < Objects(a)\Degree And Angle > Objects(a)\Degree-#rotator_speed-2 And Objects(a)\Transparency<200
          Objects(a)\Transparency=255
          CreateThread(@ObjectSound(),0)
        EndIf
      EndIf
    Next a

    For a = 0 To #max_objects
      If Objects(a)>0
        Objects(a)\Transparency-#rotator_speed
        If Objects(a)\Transparency<0
          Objects(a)\Transparency=0
        EndIf
      EndIf
    Next a

  ElseIf ScreenDeactivated = #FALSE
    ScreenDeactivated = #TRUE
  ElseIf IsScreenActive() And ScreenDeactivated = #TRUE
      ScreenDeactivated = #FALSE
      FlipBuffers()
      MakeSprites()
  EndIf
  FlipBuffers()
  Repeat:Delay(1):Until TimeGetTime_()-20>=time
Until KeyboardPushed(#PB_Key_Escape)
;- End
cya,
...Danilo
...:-=< http://codedan.net/work >=-:...
-= FaceBook.com/DaniloKrahn =-
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

Thank you SOOOO much!

here is yet another example:

Code: Select all

InitSprite()
InitMouse()

OpenScreen(800,600,32,"")

Structure bullet
  X.f
  Y.f
  XS.f
  YS.f
EndStructure

NewList bullets.bullet()

Procedure Addbullet(X.f,Y.f,XS.f,YS.f)
  AddElement(Bullets())
  Bullets()\X = X
  Bullets()\Y = Y
  Bullets()\XS = XS
  Bullets()\YS = YS
EndProcedure

Global mouseangle, BulletSpeed
BulletSpeed = 20

Procedure.f GetMouseAngle() 
  ExamineMouse()
  x1 = 400
  y1 = 300
  x2 = MouseX()
  y2 = MouseY()
  a.f = x2-x1 
  b.f = y2-y1 
  c.f = Sqr(a*a+b*b) 
  winkel.f = ACos(a/c)*57.29577 
  If y1 < y2 : winkel=360-winkel : EndIf 
  ProcedureReturn winkel+90
EndProcedure

Repeat
  ClearScreen(0,0,0)
  ExamineMouse()
  
  If CountList(bullets()) > 1
    ResetList(Bullets())
    While NextElement(Bullets())
      StartDrawing(ScreenOutput())
        Line(Bullets()\X,Bullets()\Y,Bullets()\XS,Bullets()\YS,RGB(Random(150),Random(255),0))
      StopDrawing()
      Bullets()\X + Bullets()\XS
      Bullets()\Y + Bullets()\YS
      If Bullets()\X > 800 + Bullets()\XS
        DeleteElement(Bullets())
      EndIf
      If Bullets()\X < 0 - Bullets()\XS
        DeleteElement(Bullets())
      EndIf
      If Bullets()\Y > 600 + Bullets()\YS
        DeleteElement(Bullets())
      EndIf
      If Bullets()\Y < 0 - Bullets()\YS
        DeleteElement(Bullets())
      EndIf
    Wend
  EndIf
  
  StartDrawing(ScreenOutput())
    Circle(MouseX(),MouseY(),2,RGB(0,255,255))
  StopDrawing()
  
  If MouseButton(2) = 1
    End
  ElseIf MouseButton(1) = 1
    Angle.f = GetMouseAngle()
    SpeedX.f = Sin(Angle*(3.14/180))*Bulletspeed
    SpeedY.f = Cos(Angle*(3.14/180))*Bulletspeed
    dudecounter + 1
    If dudecounter = 10
      dudecounter = 0
      Addbullet(400,300,SpeedX,SpeedY)
      Angle.f = GetMouseAngle()+10
      SpeedX.f = Sin(Angle*(3.14/180))*Bulletspeed
      SpeedY.f = Cos(Angle*(3.14/180))*Bulletspeed
      Addbullet(400,300,SpeedX,SpeedY)
      Angle.f = GetMouseAngle()+350
      SpeedX.f = Sin(Angle*(3.14/180))*Bulletspeed
      SpeedY.f = Cos(Angle*(3.14/180))*Bulletspeed
      Addbullet(400,300,SpeedX,SpeedY)
      beep_(500,1)
    EndIf 
  EndIf
  
  FlipBuffers()
ForEve
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

ForEve
The apple was ForAdam :P

For any reason do you have trigonometric-mania?

I wrote small tutorial to do without trigonometric funcs, easier, faster, etc. I hope it is easy to understand, at viewtopic.php?t=8776

DriakTravo says:
I would like a command to find the mouse angle in relation to a pair of coordinates.
Mmmh! some day someone will tell Fred about PB to have all the desired programs included :P .
Last edited by Psychophanta on Sat Dec 20, 2003 5:14 pm, edited 1 time in total.
freedimension
Enthusiast
Enthusiast
Posts: 613
Joined: Tue May 06, 2003 2:50 pm
Location: Germany
Contact:

Post by freedimension »

Psychophanta wrote::P
ForEve
For any reason do you have trigonometric-mania?

DriakTravo say:
I would like a command to find the mouse angle in relation to a pair of coordinates.
Mmmh! some day someone will tell Fred about PB to have all the desired programs included :P .
My words, that a command like ATan2 is useful is obvious, but not such a special function like asked for. Everyone should be able to subtract a few coordinates to make them ATan2-Ready.
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

freedimension wrote
My words, that a command like ATan2 is useful is obvious, but not such a special function like asked for.
I understand you, sorry but i knew why DriakTravo requested for it. :)
However, whatever is the requested command should be useful.... :arrow:
Post Reply