directial movement

Advanced game related topics
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

directial movement

Post by Dreglor »

how do you convert a angle (0-360) into x speed and y speed ?
~Dreglor
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6172
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

you mean a vector (angle + distance) to x / y components?

x = z * cos( a )
y = z * sin ( a )
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB - upgrade incoming...)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Hi Deglor. Without any sort of doubts, for me the best way to work with movement in 2D or 3D is using "director vectors".

Listen: in 2D with 2 only parameters (v0,v1) ("director vector" is how i call it) you have the instant direction and real speed (which is hipotenuse of both paramaters) of the object. And of course: x speed=v0 ; y speed=v1
how do you convert a angle (0-360) into x speed and y speed ?
there are several methods to convert polar coordenates to rectangular ones. Trigonometrical method should be fastest using FPU, but if you have not FPU, the best could be geometrical method.
To know it you need not only angle, but modulo too:
x speed=modulo*cos(angle)
y speed=modulo*sin(angle)
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6172
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

hey psycho, i should have said that i used 'z' for the speed :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB - upgrade incoming...)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Sorry, i began writting it before you finished 8)
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

ok thanks
i haven't learn trig yet :roll:
~Dreglor
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

I am trying to do the same thing. How do you find the angle of elevation?
User avatar
GedB
Addict
Addict
Posts: 1313
Joined: Fri May 16, 2003 3:47 pm
Location: England
Contact:

Post by GedB »

Ian Bell, co-author of the legendary Elite, has provided a shareware Maths for Programmers tutorial.

It can be heavy going, but this guy knows what his talking about.

http://www.iancgbell.clara.net/maths/index.htm
dontmailme
Enthusiast
Enthusiast
Posts: 537
Joined: Wed Oct 29, 2003 10:35 am

Post by dontmailme »

Thats a great site :)

I didn't know about the maths bit although I regularly visited the site about a year ago 8O
Paid up PB User !
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Ouffh! That is hardly explained, and poorly focused to computers and microprocessors.
Surely there are better sites. :)
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

WOW! 8O That looks really complicated. Im only in 10th grade and just wanted to know how to find the angle of a right triangle konwing the lengths of the 2 sides. (the mouse x and y coordinants in relation to a point on the screen.)

Any easy answer?!
dontmailme
Enthusiast
Enthusiast
Posts: 537
Joined: Wed Oct 29, 2003 10:35 am

Post by dontmailme »

Go here http://aleph0.clarku.edu/~djoyce/java/trig/sines.html

It's seems to all be explained there :)
Paid up PB User !
DriakTravo
Enthusiast
Enthusiast
Posts: 346
Joined: Fri Oct 10, 2003 12:42 am
Location: Tampa,FL,USA
Contact:

Post by DriakTravo »

here is an example of what I am tring to do:

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()
  ;add code here to determine the angle in relation between the mouse coords and the center of the screen.
  ProcedureReturn MouseAngle.f
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
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

DriakTravo; you dont need to work with angles nor with any kind of trigonometry to do that (neither for almost anything to make a game, even very complex game or anything).
However; if you have two point coords in screen, for example A(a1,a2) and B(b1,b2) the angle formed by the vector (A,B) respect the horizontal is:
ACos((b1-a1)/Sqr(Pow((b1-a1),2)+Pow((b2-a2),2)))

If you want in degrees then add *180/3.14592
and be careful, because if A=B (this is: a1=b1 and a2=b2) then division by zero will happen.


MORE:
I can't understand why everybody is obstinated (big game software companies too) in imitating physics and naturals (for example pinball ball movements, sport games, 3D racing, etc, etc).
A computer offers much more than just physic events phenomenon, or nature. :!:
Where are the genius and creativity :?:
Aren't today creators? Real Artists? Only merchants? :cry:
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Post by Danilo »

2 examples by ChaOsKid (german forum):

Code: Select all

;
; by ChaOsKid, 27.06.03  - german forum
;
; http://www.robsite.de/php/pureboard/viewtopic.php?t=1518
;
Procedure.w gATan(a.w, b.w) 
  winkel.w = ATan(a/b)*57.2957795 
  If b < 0 
    winkel + 180 
  EndIf 
  If winkel < 0 : winkel + 360 : EndIf 
  If winkel > 359 : winkel - 360 : EndIf 
  ProcedureReturn winkel 
EndProcedure 

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 
  MessageRequester("Error", "DirectX 7 Fehler!", 0) 
  End 
EndIf 

Breite = 800 
Hoehe = 600 

If OpenScreen ( Breite, Hoehe,32,"Standard") = 0 
  MessageRequester("Error", "Es konnte kein Bildschirm aufgebaut werden", 0) 
  End 
EndIf 

If InitSprite3D() = 0 
  MessageRequester("DirectX fehler !", "Fehler", #PB_MessageRequester_Ok) 
  End 
EndIf 


CreateSprite(0, 50, 50, #PB_Sprite_Texture) 
StartDrawing(SpriteOutput(0)) 
  Box(0, 0, 50, 50, RGB(55, 55, 55)) 
  FrontColor(100, 100, 100) 
  DrawingMode(1) 
  Locate(10, 10) 
  DrawText("CK") 
StopDrawing() 

Sprite3DQuality(1) 

CreateSprite3D(0, 0) 

Repeat 
  ClearScreen(0, 0, 0) 
  ExamineMouse() 
  ; a = grün 
  a.w = MouseY() - Hoehe/2 
  ; b = rot 
  b.w = MouseX() - Breite/2 
  winkel.w = gATan(a, b) 

  Start3D() 
    RotateSprite3D(0, Winkel, 0) 
    DisplaySprite3D(0, Breite/2 - 25, Hoehe/2 - 25) 
  Stop3D() 
  
  StartDrawing(ScreenOutput()) 
    ; a = grün 
    LineXY(MouseX(), MouseY(), MouseX(), Hoehe/2, $00F000) 
    ; b = rot 
    LineXY(MouseX(), Hoehe/2, Breite/2, Hoehe/2, $0000F0) 
    ; c = blau 
    LineXY(Breite/2, Hoehe/2, MouseX(), MouseY(),$500000) 
    DrawingMode(1) 
    FrontColor(255, 0, 0) 
    Locate(MouseX(), Hoehe/2 + 1) 
    DrawText("b: " + Str(b)) 
    FrontColor(0, 255, 0) 
    Locate(MouseX() + 1, MouseY()) 
    DrawText("a: " + Str(a)) 
    FrontColor(255, 255, 255) 
    Locate(Breite/2, Hoehe/2 + 25) 
    DrawText(Str(winkel) + " Grad") 
  StopDrawing() 
  FlipBuffers() 
  
  If ExamineKeyboard() 
    If KeyboardPushed(#PB_Key_Escape) 
      Quit = 1 
    EndIf 
  EndIf 
  Delay(10) 
Until Quit


Code: Select all

;
; by ChaOsKid, 07.07.03 - german forum
;
; http://www.robsite.de/php/pureboard/viewtopic.php?t=1518
;
Structure Spieler 
  x.f 
  y.f 
  hGroesse.l 
  Geschwindigkeit.l 
  DrehGeschwindigkeit.l 
  Winkel.l 
  ZielWinkel.l 
EndStructure 

Structure Geschoss 
  x.f 
  y.f 
  GeschwindigkeitX.f 
  GeschwindigkeitY.f 
EndStructure 

NewList Geschoss.Geschoss() 

Procedure.l gATan(a.l, b.l) 
  winkel.l = Int(ATan(a/b)*57.2957795) 
  If b < 0 
    winkel + 180 
  EndIf 
  If winkel < 0 : winkel + 360 : EndIf 
  If winkel > 359 : winkel - 360 : EndIf 
  ProcedureReturn winkel 
EndProcedure 

Procedure.f gSin(winkel.l) 
   ; Eingabe: Winkel ( 0 - 360 ) 
   ; Ausgabe: Sinus vom Winkel 
   ProcedureReturn Sin(winkel*0.01745329) 
EndProcedure 

Procedure.f gCos(winkel.l) 
   ; Eingabe: Winkel ( 0 - 360 ) 
   ; Ausgabe: Cosinus vom Winkel 
   ProcedureReturn Cos(winkel*0.01745329) 
EndProcedure 

Procedure neuesGeschoss(x.f, y.f, GeschwindigkeitX.f, GeschwindigkeitY.f) 
  AddElement(Geschoss()) 
  Geschoss()\x = x 
  Geschoss()\y = y 
  Geschoss()\GeschwindigkeitX = GeschwindigkeitX 
  Geschoss()\GeschwindigkeitY = GeschwindigkeitY 
EndProcedure 

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 
  MessageRequester("Error", "DirectX 7 Fehler!", 0) 
  End 
EndIf 

Breite = 800 
Hoehe = 600 

If OpenScreen ( Breite, Hoehe,32,"Standard") = 0 
  MessageRequester("Error", "Es konnte kein Bildschirm aufgebaut werden", 0) 
  End 
EndIf 

If InitSprite3D() = 0 
  MessageRequester("DirectX fehler !", "Fehler", #PB_MessageRequester_Ok) 
  End 
EndIf 

CreateSprite(0, Breite, Hoehe) 

CreateSprite(1, 32, 32, #PB_Sprite_Texture) 
StartDrawing(SpriteOutput(1)) 
  Box(0, 0, 32, 32, RGB(55, 55, 55)) 
;  Circle(16, 16, 15, RGB(55, 55, 55)) 
  FrontColor(100, 100, 100) 
  DrawingMode(1) 
  Locate(7, 8) 
  DrawText("CK") 
StopDrawing() 

CreateSprite(2, 32, 32, #PB_Sprite_Texture) 
StartDrawing(SpriteOutput(2)) 
  LineXY(1, 17, 16, 1, RGB(255, 255, 255)) 
  LineXY(16, 1, 31, 17, RGB(255, 255, 255)) 
  LineXY(20, 17, 31, 17, RGB(255, 255, 255)) 
  LineXY(10, 17, 1, 17, RGB(255, 255, 255)) 
  LineXY(10, 31, 10, 17, RGB(255, 255, 255)) 
  LineXY(20, 31, 20, 17, RGB(255, 255, 255)) 
  LineXY(10, 31, 20, 31, RGB(255, 255, 255)) 
  LineXY(10, 31, 10, 17, RGB(255, 255, 255)) 
  FillArea(16, 17, RGB(255, 255, 255), RGB(255, 255, 255)) 
StopDrawing() 

Sprite3DQuality(1) 
CreateSprite3D(1, 1) 
CreateSprite3D(2, 2) 

CreateSprite(10, 32, 32) 
StartDrawing(SpriteOutput(10)) 
  DrawingMode(4) 
  Circle(16, 16, 16, RGB(255, 255, 255)) 
  Plot(16, 16,RGB(200, 200, 200)) 
StopDrawing() 


Spieler1.Spieler 
Spieler1\hGroesse = 16 
Spieler1\x = Breite/2 - Spieler1\hGroesse 
Spieler1\y = Hoehe/2 - Spieler1\hGroesse 
Spieler1\Geschwindigkeit = 2 
Spieler1\Drehgeschwindigkeit = 2 
Spieler1\Winkel = 270 

Maus.Point 

Repeat 
  ExamineMouse() 
  ExamineKeyboard() 

  Maus\x = MouseX() - 16 
  Maus\y = MouseY() - 16 
  a.l = Maus\y - Spieler1\y 
  b.l = Maus\x - Spieler1\x 
  Spieler1\ZielWinkel = gATan(a, b) 
  
  If KeyboardPushed(#PB_Key_Left) Or KeyboardPushed(#PB_Key_A) 
    Spieler1\Winkel - Spieler1\Drehgeschwindigkeit 
  EndIf 
  If KeyboardPushed(#PB_Key_Right) Or KeyboardPushed(#PB_Key_D) 
    Spieler1\Winkel + Spieler1\Drehgeschwindigkeit 
  EndIf 
  ; 
  If KeyboardPushed(#PB_Key_Up) Or KeyboardPushed(#PB_Key_W) 
    Spieler1\x + (gCos(Spieler1\Winkel) * Spieler1\Geschwindigkeit) 
    Spieler1\y + (gSin(Spieler1\Winkel) * Spieler1\Geschwindigkeit) 
  EndIf 
  If KeyboardPushed(#PB_Key_Down) Or KeyboardPushed(#PB_Key_S) 
    Spieler1\x - (gCos(Spieler1\Winkel) * Spieler1\Geschwindigkeit) 
    Spieler1\y - (gSin(Spieler1\Winkel) * Spieler1\Geschwindigkeit) 
  EndIf 
  If Spieler1\x > Breite - 32 
    Spieler1\x = Breite - 32 
  EndIf 
  If Spieler1\x < 0 
    Spieler1\x = 0 
  EndIf 
  If Spieler1\y > Hoehe - 32 
    Spieler1\y = Hoehe - 32 
  EndIf 
  If Spieler1\y < 0 
    Spieler1\y = 0 
  EndIf 
  
  If MouseButton(1) 
    If Verzoegerung < 1 
      Verzoegerung = 10 
      Geschwindigkeit.l = 8 
      Geschossabstand.l = 33 
      GeschwindigkeitX.f = gCos(Spieler1\ZielWinkel) 
      GeschwindigkeitY.f = gSin(Spieler1\ZielWinkel) 
      neuesGeschoss(Spieler1\x + Spieler1\hGroesse + GeschwindigkeitX * Geschossabstand, Spieler1\y + Spieler1\hGroesse + GeschwindigkeitY * Geschossabstand, GeschwindigkeitX * Geschwindigkeit, GeschwindigkeitY * Geschwindigkeit) 
      ;patronenhülse malen 
      StartDrawing(SpriteOutput(0)) ;Grafiken werden direkt auf dem Hintergrundbildsprite gerendert 
        Plot(Int(Spieler1\x) + Random(Spieler1\hGroesse) + Spieler1\hGroesse/2, Int(Spieler1\y) + Random(Spieler1\hGroesse) + Spieler1\hGroesse/2, RGB(200, 120, 55)) 
      StopDrawing() 
    EndIf 
  EndIf 
  If Verzoegerung > 0 
    Verzoegerung - 1 
  EndIf 
  
  ;ClearScreen(0, 0, 0) 
  
  DisplaySprite(0, 0, 0) 

  Start3D() 
    RotateSprite3D(1, Spieler1\Winkel, 0) 
    DisplaySprite3D(1, Int(Spieler1\x), Int(Spieler1\y)) 
    RotateSprite3D(2, Spieler1\ZielWinkel, 0) 
    DisplaySprite3D(2, Int(Spieler1\x), Int(Spieler1\y), 20) 
  Stop3D() 
  
  DisplayTransparentSprite(10, Maus\x, Maus\y) 

  ; Geschosse rendern 
  StartDrawing(ScreenOutput()) ;Grafiken werden direkt auf dem Bildschirm gerendert 
    
    ResetList(Geschoss()) 
    While NextElement(Geschoss()) 
      If Geschoss()\x < 0 Or Geschoss()\y < 0 Or Geschoss()\x > Breite Or Geschoss()\y > Hoehe 
        DeleteElement(Geschoss()) 
      Else 
        Plot(Int(Geschoss()\x), Int(Geschoss()\y), RGB(200, 200, 200)) 
        LineXY(Int(Geschoss()\x - Geschoss()\GeschwindigkeitX*2), Int(Geschoss()\y - Geschoss()\GeschwindigkeitY*2), Geschoss()\x, Geschoss()\y, RGB(120, 100, 100)) 
        Geschoss()\x + Geschoss()\GeschwindigkeitX 
        Geschoss()\y + Geschoss()\GeschwindigkeitY 
      EndIf 
    Wend 
  StopDrawing() 
  
  FlipBuffers() 
    
  If KeyboardPushed(#PB_Key_Escape) 
    Quit = 1 
  EndIf 

  Delay(3) 
Until Quit


Another example by Rob (german forum):
(Cursor Keys to move, space = shoot)

Code: Select all

;
; by Rob, 03.10.2003 - german forum
;
; http://www.robsite.de/php/pureboard/viewtopic.php?t=2449&start=11
;
; Screen 
xscreen = 640 
yscreen = 480 

; Kreis 
k_x.f = xscreen/2 
k_y.f = yscreen/2 
k_winkel.f = 180 
k_radius = 15 
k_speed.f = 2 

; Schüsse 
Structure kugel 
  x.f 
  y.f 
  winkel.f 
  speed.f 
EndStructure 

NewList schuss.kugel() 


InitKeyboard() 
InitSprite() 

If OpenScreen(xscreen,yscreen,16,"Schusstest") 
    
  Repeat 
    ExamineKeyboard() 
    
    ; Kreis bewegen 
    ; Drehen 
    If KeyboardPushed(#PB_Key_Left) : k_winkel - 4 :  If k_winkel <= 0 : k_winkel = 360 : EndIf : EndIf 
    If KeyboardPushed(#PB_Key_Right) : k_winkel + 4 : If k_winkel >= 360 : k_winkel = 0 : EndIf : EndIf 
    
    ; Vorwärts 
    If KeyboardPushed(#PB_Key_Up) 
      k_x + Cos(k_winkel *(2*3.1415/360)) * k_speed ; Grad zu Bogenmaß 
      k_y + Sin(k_winkel *(2*3.1415/360)) * k_speed 
    EndIf 
    
    ; Rückwärts 
    If KeyboardPushed(#PB_Key_Down) 
      k_x + Cos(k_winkel *(2*3.1415/360)) * -k_speed 
      k_y + Sin(k_winkel *(2*3.1415/360)) * -k_speed 
    EndIf    
    
    ; Schuss abfeuern 
    If KeyboardPushed(#PB_Key_Space) And geschossen = 0 
      AddElement(schuss()) 
      schuss()\x = k_radius * Cos(k_winkel *(2*3.1415/360)) + k_x ; Am Rand des Kreises 
      schuss()\y = k_radius * Sin(k_winkel *(2*3.1415/360)) + k_y 
      schuss()\winkel = k_winkel 
      schuss()\speed = 5 
      
      geschossen = 1 ; Erst die Taste wieder loslassen, kein Dauerfeuer 
    EndIf 
    
    If KeyboardReleased(#PB_Key_Space) : geschossen = 0 : EndIf 
    
    ; Schüsse bewegen 
    ResetList(schuss()) 
    While NextElement(schuss()) 
      schuss()\x + Cos(schuss()\winkel *(2*3.1415/360)) * schuss()\speed 
      schuss()\y + Sin(schuss()\winkel *(2*3.1415/360)) * schuss()\speed 
      
      ; Kommen sie am Rand an, löschen 
      If schuss()\x > xscreen Or schuss()\x < 0 Or schuss()\y > yscreen Or schuss()\y < 0 
        DeleteElement(schuss()) 
      EndIf 
      
    Wend 
    
    ; ------------------------------ 
    
    ; Zeichnen 
    StartDrawing(ScreenOutput()) 
    
    ; Kreis 
    DrawingMode(4) 
    Circle(k_x,k_y,k_radius,RGB(0,100,255)) 
    LineXY(k_x,k_y,k_radius * Cos(k_winkel *(2*3.1415/360)) + k_x,k_radius * Sin(k_winkel *(2*3.1415/360)) + k_y,RGB(0,255,255)) 
    
    ; Schüsse 
    ResetList(schuss()) 
    While NextElement(schuss()) 
      LineXY(schuss()\x,schuss()\y,8 * Cos(schuss()\winkel *(2*3.1415/360)) + schuss()\x,8 * Sin(schuss()\winkel *(2*3.1415/360)) + schuss()\y,RGB(255,100,0)) 
    Wend 
    
     ; Text 
    DrawingMode(1) 
    FrontColor(150,150,150) 
    Locate(1,1) 
    DrawText("Winkel: " + Str(k_winkel)) 
    Locate(1,16) 
    DrawText("Schüsse: " + Str(CountList(schuss())))    
      
    StopDrawing() 
    
    FlipBuffers() 
    ClearScreen(0,0,0) 
  Until KeyboardPushed(#PB_Key_Escape)
Else 
  MessageRequester("Error","Funzt nich",0) 
EndIf

btw: Winkel in Grad (german) = Angle in Degree (english) :D

Maybe this helps a little bit with angle calculation.
Sometimes real examples are better than all the theorie...
especially for starters.
cya,
...Danilo
...:-=< http://codedan.net/work >=-:...
-= FaceBook.com/DaniloKrahn =-
Post Reply