directial movement
you mean a vector (angle + distance) to x / y components?
x = z * cos( a )
y = z * sin ( a )
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... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
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
To know it you need not only angle, but modulo too:
x speed=modulo*cos(angle)
y speed=modulo*sin(angle)
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
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.how do you convert a angle (0-360) into x speed and y speed ?
To know it you need not only angle, but modulo too:
x speed=modulo*cos(angle)
y speed=modulo*sin(angle)
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... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
-
DriakTravo
- Enthusiast

- Posts: 346
- Joined: Fri Oct 10, 2003 12:42 am
- Location: Tampa,FL,USA
- Contact:
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
It can be heavy going, but this guy knows what his talking about.
http://www.iancgbell.clara.net/maths/index.htm
-
dontmailme
- Enthusiast

- Posts: 537
- Joined: Wed Oct 29, 2003 10:35 am
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
-
DriakTravo
- Enthusiast

- Posts: 346
- Joined: Fri Oct 10, 2003 12:42 am
- Location: Tampa,FL,USA
- Contact:
-
dontmailme
- Enthusiast

- Posts: 537
- Joined: Wed Oct 29, 2003 10:35 am
-
DriakTravo
- Enthusiast

- Posts: 346
- Joined: Fri Oct 10, 2003 12:42 am
- Location: Tampa,FL,USA
- Contact:
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- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
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?
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?
2 examples by ChaOsKid (german forum):
Another example by Rob (german forum):
(Cursor Keys to move, space = shoot)
btw: Winkel in Grad (german) = Angle in Degree (english)
Maybe this helps a little bit with angle calculation.
Sometimes real examples are better than all the theorie...
especially for starters.
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 QuitCode: 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 QuitAnother 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)
EndIfbtw: Winkel in Grad (german) = Angle in Degree (english)
Maybe this helps a little bit with angle calculation.
Sometimes real examples are better than all the theorie...
especially for starters.

