Physics

Blitz3D Forums/Blitz3D Beginners Area/Physics

David819(Posted 2005) [#1]
Hi I'm currently mucking about trying to do some physics. I've dont a bit of coding but not much, I'm making rope physics at the moment, and was wandering how i am to go about making this, and how to get the functions to do what i want. I'm trying to keep this as simple as possible so that everyone can understand it when i release it. Can anyone help me with advise and possible help with coding. Thanks.


Rob Farley(Posted 2005) [#2]
OK, rope physics are pretty complex as you're talking about many segments of rope. Each segment needs to have forces acting upon it individually as well as each segment affecting the surrounding segments.

Personally I think you should start with bouncing balls or something similar.


Amon_old(Posted 2005) [#3]
I remember your rope effect Rob. It was kinda cool. Did you ever manage to perfect it?


David819(Posted 2005) [#4]
Ok, I'll take your advice and start with a bouncing ball, would you be able to sort of talk me through what i would have to do though so i can get the basic concept of programing physics, like not the code but how the balls velocity would respond and the formulas that are need. thanks.


NewtSoup(Posted 2005) [#5]
Right, start with a ground plane and gravity and make something fall under gravity.
Youre going to be working with point masses here. assume they have no volume for calculation purposes even if your graphic has volume you can tweak the collisions to work with that.

The key concept is that all your algorithms need to be incremental. That is you need to calculate how much something moved during the last program cycle

Use newtons laws
F=ma
S=ut+0.5*a*t*t
v=u+at
v*v=u*u+2*a*s

This is all GCSE/O-level/Highschool physiscs

heres an example to get you started. Its something I worked on a year or so ago and it accelerates a "rocket" upwards and then attempts to land it on the ground again by firing the engines at the right time.

It uses the concepts I mention above

;Include "key_constants.bb"
Const G#=-9.81 ;m/s/s
Const LANDED=1
Const BURNING=2
Const FLYING=3
Const CRASHED=4
Global friction#=-0.7
Global thrust#=1000 ;N
Global mass=25 ;Kg

Global thrust_time#=2 ;seconds
Global start_time=MilliSecs()
Global last_time=start_time
Global this_time=start_time
Global v#=0
Global u#=0
Global s#=0
Local df[5]
Local dft#[3]
df[0]=1
df[1]=5
df[2]=10
df[3]=50
df[4]=100
df[5]=1000
dft[0]=0.01
dft[1]=0.1
dft[2]=1
dft[3]=10
fi=4
ti=2
height#=0
f#=0
edit_m=0

auto = 0
thrust_height=0
Local status=LANDED
Graphics 800,600,32,2
SetBuffer BackBuffer()
SetFont LoadFont("verdana",15,1)
While Not KeyHit(k_escape)
Cls
last_time=this_time
this_time=MilliSecs()-start_time
u#=v#
If KeyHit(k_a) auto=1-auto
period#=Float(this_time-last_time)/1000
If (launch_time>0)
	If (this_time>launch_time+(thrust_time*1000)And status=BURNING)f#=0:status=FLYING
	If (Not auto) And (status=FLYING)
		f=0
		If KeyDown(k_z) f=thrust
		If KeyDown(k_x) f=thrust/2
		If KeyDown(k_c) f=thrust/4
	End If 
;	If auto And status=FLYING  And height<=thrust_height
;		If v<-height And  v<-1  Then
;			f=thrust
;		Else
;			f=-mass*g
;		End If
;	End If

	If auto And status=FLYING Then
		
		If v<0 Then
			h2# = (v^2)/(2*(mass*g-(v*friction)+thrust)/mass)
			If height <=h2 + Abs(v*period) Then f=thrust
		Else
			f=0
		End If
	End If
	
	a#=(f#+v*friction+mass*g)/mass
	v#=u#+a#*period
	s#=u*period+0.5*a*period*period
	height#=height#+(s)
	If height#>max# Then  max=height#
	If v>max_v# Then
		max_v=v
		If height>thrust_height thrust_height=height
	End If
	flight_time#=Float(this_time-launch_time)/1000
	If (height#<=0) And (status=flying)
		height=0
		s=0
		launch_time=0 
		f=0
		If Abs(v)<1 Then status=LANDED
		If Abs(v)>1 Then status=CRASHED	
		auto=0;	
		thrust_height=0
	End If
		
	
End If
	
Color 70,190,80
Rect 0,590,800,10,1
Color 220,90,80
Rect 398,584-height,5,6,1
Rect 399,581-height,3,3,1
Rect 400,579-height,1,2,1
If f>0
	Color 250,250,0
	Rect 399,588-height+2,3,3
	Color 400,200,0
	Rect 400,590-height+3,1,4
End If
Color 255,255,255
If KeyHit(K_L) And launch_time=0
	v=0:u=0
	launch_time=MilliSecs()-start_time
	f#=thrust
	max#=0
	max_v=0
	flight_time#=0
	status=BURNING
End If


If KeyHit(k_r) height=0:v=0:f=Int (0):auto=0
If KeyHit(K_SPACE) edit_m= edit_m+1 :If edit_m>3 edit_m=0

If edit_m=1
	If KeyHit(K_Up) mass=mass+df[fi]
	If KeyHit(k_down)mass=mass-df[fi]
	If KeyHit(k_right) fi=fi+1 :If fi>5 fi=5
	If KeyHit(k_left) fi=fi-1 :If fi<0 fi=0

End If

If edit_m=2
	If KeyHit(K_Up) thrust=thrust+df[fi]
	If KeyHit(k_down)thrust=thrust-df[fi]
	If KeyHit(k_right) fi=fi+1 :If fi>5 fi=5
	If KeyHit(k_left) fi=fi-1 :If fi<0 fi=0
End If

If  edit_m=3
	If KeyHit(K_Up)  thrust_time=thrust_time+dft[ti]
	If KeyHit(k_down)thrust_time=thrust_time-dft[ti]
	If KeyHit(k_right) ti=ti+1 :If ti>3 ti=3
	If KeyHit(k_left) ti=ti-1 :If ti<0 ti=0

End If
If edit_m=0
	If KeyHit(K_Up) friction=friction+0.1
	If KeyHit(k_down)friction=friction-0.1
	If Abs(friction)<0.1 friction=0
End If
Text 10,40,"a         = "+((f/mass)+g)+"m/s/s"
Text 10,60,"s         = "+height#+"m"
Text 10,80,"R         = "+(f+(v*friction)+(mass*g))+"N" 
Text 300,80,"("+(v*friction)+"N friction)"+ h2
If Abs(v)>1 Then 
	Color 255,0,0
Else 
	Color 0,255,0
End If
Text 10,100,"v         = "+v+"m/s"
Color 255,255,255
Text 10,120,"Launched ="+((launch_time)/1000)
Text 10,140,"Time     = "+((this_time)/1000)
Text 10,160,"Period   = "+period
Color 200,90,80
Text 10,180,"Max s    = "+max+"m"
Text 10,200,"Max v    = "+max_v+"m/s"
Text 10,220,"Flight t = "+flight_time+"s"
Color 255,255,255
If edit_m=0
	Color 70,190,80
	Text 10,0,"uf        = "+friction
	Color 255,255,255
	Text 10,240,"Thrust   ="+thrust+"N ("+df[fi]+" Newton adjust)"
	Text 10,260,"Burn     ="+thrust_time +"s ("+dft[ti]+" second adjust)"
	Text 10,20,"m         = "+mass+"kg ("+df[fi]+" Kg adjust)"
End If
If edit_m=2
	Text 10,0,"uf        = "+friction
	Color 70,190,80
	Text 10,240,"Thrust   ="+thrust+"N ("+df[fi]+" Newton adjust)"
	Color 255,255,255
	Text 10,260,"Burn     ="+thrust_time +"s ("+dft[ti]+" second adjust)"
	Text 10,20,"m         = "+mass+"kg ("+df[fi]+" Kg adjust)"

End If
If edit_m=3
	Text 10,0,"uf        = "+friction
	Text 10,240,"Thrust   ="+thrust+"N ("+df[fi]+" Newton adjust)"
	Color 70,190,80
	Text 10,260,"Burn     ="+thrust_time +"s ("+dft[ti]+" second adjust)"
	Color 255,255,255
	Text 10,20,"m         = "+mass+"kg ("+df[fi]+" Kg adjust)"

End If
If edit_m=1
	Text 10,0,"uf        = "+friction
	Text 10,240,"Thrust   ="+thrust+"N ("+df[fi]+" Newton adjust)"
	Text 10,260,"Burn     ="+thrust_time +"s ("+dft[ti]+" second adjust)"
	Color 70,190,80
	Text 10,20,"m         = "+mass+"kg ("+df[fi]+" Kg adjust)"

	Color 255,255,255
End If

Color 100,255,90
Text 10,400,"Z Thrust"
Text 10,420,"X Thrust/2"
Text 10,440,"C Thrust/4"
Text 10,460,"L to launch, Space And arrow "
Text 10,480,"keys to change parameters"
Text 10,500,"R to reset A to engage Autopilot"
Text 10,520, "Esc to quit."
If auto Then Text 10,300,"Auto pilot on"
If status=LANDED Color 0,255,0:Text 280,400,"Landed, well done!!"
If status=CRASHED Color 255,0,0:Text 280,400,"Crashed, bad luck!!"
Color 255,255,255
Flip(1)
Delay 10
Wend

End

;******************** COSNTANTS *************************
Const K_ESCAPE= 1   
Const K_1= 2   
Const K_2= 3   
Const K_3= 4   
Const K_4= 5   
Const K_5= 6   
Const K_6= 7   
Const K_7= 8   
Const K_8= 9   
Const K_9= 10   
Const K_0= 11   
Const K_Minus= 12; On Main Keyboard 
Const K_Equals= 13   
Const K_Backspace= 14; Backspace key 
Const K_Tab= 15   
Const K_Q= 16   
Const K_W= 17   
Const K_E= 18   
Const K_R= 19   
Const K_T= 20   
Const K_Y= 21   
Const K_U= 22   
Const K_I= 23   
Const K_O= 24   
Const K_P= 25   
Const K_Left_Bracket= 26   
Const K_Right_Bracket= 27   
Const K_Enter= 28; Return/Enter on Main Keyboard 
Const K_Left_Control= 29   
Const K_A= 30   
Const K_S= 31   
Const K_D= 32   
Const K_F= 33   
Const K_G= 34   
Const K_H= 35   
Const K_J= 36   
Const K_K= 37   
Const K_L= 38   
Const K_Semi_Colon= 39   
Const K_Apostrophe=40;'   
Const K_Grave= 41; Accent Grave `
Const K_Left_Shift= 42   
Const K_Backslash=43   
Const K_Z= 44   
Const K_X= 45   
Const K_C= 46   
Const K_V= 47   
Const K_B= 48   
Const K_N= 49   
Const K_M= 50   
Const K_Comma= 51   
Const K_Period= 52; On Main keyboard 
Const K_Slash= 53; On Main Keyboard 
Const K_Right_Shift= 54   
Const K_Multiply= 55; On Numeric Keypad 
Const K_Left_Alt= 56   
Const K_Space=57   
Const K_Capslock=58   
Const K_F1= 59   
Const K_F2 =60   
Const K_F3= 61   
Const K_F4= 62   
Const K_F5= 63   
Const K_F6= 64   
Const K_F7= 65   
Const K_F8= 66   
Const K_F9= 67   
Const K_F10= 68   
Const K_NumLock= 69   
Const K_ScrollLock= 70   
Const K_NumPad_7= 71   
Const K_NumPad_8= 72   
Const K_NumPad_9= 73   
Const K_Subtract= 74; On Numeric Keypad 
Const K_NumPad_4= 75   
Const K_NumPad_5= 76   
Const K_NumPad_6= 77   
Const K_Add=78; On Numeric Keypad 
Const K_NumPad_1= 79   
Const K_NumPad_2= 80   
Const K_NumPad_3= 81   
Const K_NumPad_0= 82   
Const K_Decimal= 83; On Numeric Keypad 
Const K_OEM_102= 86; On UK/Germany Keyboards 
Const K_F11= 87   
Const K_F12= 88   
Const K_F13= 100; (NEC PC98) 
Const K_F14= 101; (NEC PC98) 
Const K_F15= 102; (NEC PC98) 
Const K_Kana= 112; Japanese Keyboard 
Const K_ABNT_C1= 115; /? on Portugese (Brazilian) keyboards 
Const K_Convert= 121; Japanese Keyboard 
Const K_NoConvert= 123; Japanese Keyboard 
Const K_Yen= 125; Japanese Keyboard 
Const K_ABNT_C2= 126; Numpad . on Portugese (Brazilian) keyboards 
Const K_NUMPAD_Equals= 141; = on numeric keypad (NEC PC98) 
Const K_PrevTrack= 144; Previous Track (DIK_CIRCUMFLEX on Japanese keyboard) 
Const K_AT= 145; (NEC PC98) 
Const K_Colon= 146; (NEC PC98) 
Const K_Underline= 147; (NEC PC98) 
Const K_Kanji= 148; Japanese Keyboard 
Const K_Stop= 149; (NEC PC98) 
Const K_AX= 150; Japan AX 
Const K_Unlabeled= 151; (J3100) 
Const K_Next_Track= 153; Next Track 
Const K_NUMPAD_Enter= 156; ENTER on Numeric Keypad 
Const K_Right_Control= 157   
Const K_Mute= 160; Mute 
Const K_Calculator= 161; Calculator 
Const K_Play_Pause= 162; Play/Pause 
Const K_Media_Stop= 164; Media Stop 
Const K_Volume_Down= 174; Volume - 
Const K_Volume_Up =176; Volume + 
Const K_Web_Home =178; Web Home 
Const K_NUMPAD_Comma= 179; On Numeric Keypad (NEX PC98) 
Const K_Divide= 181; / On Numeric Keypad 
Const K_SysReq =183;   
Const K_Right_alt= 184; Right Alt 
Const K_Pause= 197; Pause 
Const K_Home= 199; Home on Arrow Pad 
Const K_Up= 200; Up Arrow on Arrow Keypad 
Const K_Page_Up= 201; Page Up on Arrow Keypad 
Const K_Left= 203; Left Arrow on Arrow Keypad 
Const K_Right= 205; Right Arrow on Arrow Keypad 
Const K_End =207; End Key on Arrow Keypad 
Const K_Down= 208; Down Key on Arrow Keypad 
Const K_Next= 209; Next Key on Arrow Keypad 
Const K_Insert= 210; Insert Key on Arrow Keypad 
Const K_Delete= 211; Delete Key on Arrow Keypad 
Const K_Left_Windows= 219; Left Windows Key 
Const K_Right_Windows= 220; Right Windows Key 
Const K_Apps= 221; Apps Menu Key 
Const K_Power= 222; System Power 
Const K_Sleep= 223; System Sleep 
Const K_Wake= 227 ;System Wake 
Const K_Web_Search= 229   
Const K_Web_Favorites= 230   
Const K_Web_Refresh= 231   
Const K_Web_Stop= 232   
Const K_Web_Forward= 233   
Const K_Web_Back= 234   
Const K_My_Computer= 235   
Const K_Mail=  236 



sorry for the lack of comments but Im sure you'll do fine


David819(Posted 2005) [#6]
Ok, i've set up a ground and collision, i've made a function to create a ball and know am at the physics part, i've been looking at the formula:
F=MA
A=F/M
But one thing that is puzzeling me is the other formulas cause i'm not sure how to put it into my coding, just so you know how i'm coding this i'll put the code below:

;--------------------Graphics---------------------
Graphics3D 1280,1024,32
SetBuffer BackBuffer()

;--------------------Constants--------------------
Const Ground_Type=1
Const Ball_Type=2
Gravity#=1

;--------------------SetUp------------------------
Camera=CreateCamera()
PositionEntity camera,0,5,-10
Light=CreateLight()

Texture=LoadTexture("Rope.jpg")
Surface=CreatePlane()
EntityTexture Surface,Texture
EntityType Surface,Ground_Type

CreateBall.Physics(0,5,0)

Collisions Ball_Type,Ground_Type,3,1

;--------------------Loop-------------------------
While Not KeyHit(1)


UpdateWorld
RenderWorld

frames=frames+1
If MilliSecs()-render_time=>1000 Then fps=frames : frames=0 : render_time=MilliSecs()
Text 0,0,fps

Flip
Wend
End

Type Physics
Field Entity
Field X#, Y#, Z#
Field VX#, VY#, VZ#
Field AX#, AY#, AZ#
Field Mass#, Weight#, Size#
End Type

Function CreateBall.Physics(X#,Y#,Z#)
Test.Physics=New Physics
Test\Entity=CreateSphere()
Test\X#=X#
Test\Y#=Y#
Test\Z#=Z#
PositionEntity Test\Entity,Test\X#,Test\Y#,Test\Z#
EntityColor Test\Entity,255,0,0
EntityShininess Test\Entity,2
EntityType Test\Entity,Ball_Type
End Function

;F=ma
;S=ut+0.5*a*t*t
;v=u+at
;v*v=u*u+2*a*s


Function Update_Ball.Physics(AX#,AY#,AZ#)
For Test.Physics=Each Physics

Next
End Function

I'm not at all sure what to do next. thanks.


NewtSoup(Posted 2005) [#7]
ahh dont worry about them too much they were just a reminder of what the laws were in case you wanted to make use of them because you need functions to also work in terms of time t (the period in the last program cycle)

however falling under gravity you know already what the acceleration is going to be. you need to work out F (the force working on the object) if you want to simulate friction (at a later date)

so given that the time that elapsed in the last program cycle is t and the acceleration is a (9.81 m/s/s in natural earth gravity) then the distance fallen by the ball in the last program cycle is given by
s=ut+/5at^2

the speed of the ball at the end of time t is given by

v= u + at
u in this case being 0 starting from time t=0

next program cycle u will be v as it is now and you will calculate the new v based on that.

perhaps thinking of the formula for the speed as

vnew = vlast + acceleration * programlooptime

and the distance travelled as

deltaYaxis = vlast*programlooptime + 0.5 * acceleration * programlooptime*programlooptime

dont be afraid to mess around with the formula to produce aesthetically pleasing results.. NO its not a true simulation then but so long as it looks right who's going to care? :D


David819(Posted 2005) [#8]
Sorry but i'm completely lost, I'm currently taking standard grade physics, What the problem is is that i dont understand how to program this stuff in the right sense. knowing the formulas help but i dont know how to apply this to the ball and get it to do what i want. :(, sorry for being a pain.


NewtSoup(Posted 2005) [#9]
not at all :)

lets consider an object moving along a straight line with constant speed
the object is moving at 10 meters per second for the sake of our simulation we will state that 1m = 1 screen pixel so on our screens the object is moving at 10 pixels per second

so lets have a line to represent the surface our object is moving on:

Graphics 800,600,32,2

SetBuffer BackBuffer()

While Not KeyHit (1)

Line 100,500,700,500

Flip
cls
Wend


now we need a graphic to represent the object. in this case I am going to use a circle with its y coord and diamter set so it looks like its on the ground.

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
xspeed#=10

While Not KeyHit (1)

Line 100,500,700,500
Oval ballx,bally,ballr,ballr

Flip
cls
Wend


at the moment the ball is just staying there but we want it to move from left to right at 10pixels per second

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
xspeed=10

While Not KeyHit (1)

Line 100,500,700,500
Oval ballx,bally,ballr,ballr
ballx=ballx+xspeed

Flip
Cls
Wend


whups the ball shot off and that didnt look like 10 pixels per second. this is because we added 10 to the balls x location every program loop and the program loop is far faster than 1 time per second

so lets add some code to work out the program loop time and apply that to the ammount we move the ball by each loop.

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
xspeed# = 10
time=MilliSecs()
While Not KeyHit (1)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"

Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;now we move the ball according to how much time has passed
ballx=ballx+10*t

Flip
Cls
Wend



There we go, the ball is moving at a nice sedate 10 pixels per second. lets make it do something more interesting.. lets give it some acceleration at ohhh 10m/s/s which translates to 10 pixels per second per second in our program

now we know that the new speed is the old speed + acceleration times time.
v=u+at (recognise this formula?)

crowbaring this into our program makes our code look like this:

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
xspeed# = 10
xacceleration = 10
time=MilliSecs()
While Not KeyHit (1)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
; v   =  u    +      a        * t
xspeed=xspeed + xacceleration * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t

Flip
Cls
Wend


tada, well still not _that_ interesting but its an intro to incremental algorithms using a single simple physics rule do work out the displacement (distance traveled) by an object under acceleration in program loop time based on its acceleration and initial velocity per unit time :)

everyone who has ever written a physics prog from scratch has probably started by doing something like this. dont worry if its confusing to start with because it _is_ confusing and we havent even mentioned 2d rigid body physics yet let alone 3d (hope Im not scaring you)

but anyway back to the lecture :) and on to 2d particle physics. give me a short while to extend my code and sort out how I want to explain :) basically Im going to do the old classic projectile where a ball is fired at an angle along a plain obeying newtons laws. the result will be a parabolic flight of the ball untill it hits the ground again. acceleration will be in the Y axis only and X velocity will be assumed to be constant (no friction)


NewtSoup(Posted 2005) [#10]
now we are onto the y axis, note that I use -yspeed when drawing the ball because the computer counts pixels left to right and top to bottom and we want the ball to travel up the screen not down it. so far the ball has no xspeed component.

we are assuming that upward speed has a +ve value and that downward speed is -ve

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
yspeed# = 10

;note the x speed and acceleration has now been set to 0
xspeed# = 0
xacceleration = 0

time=MilliSecs()
While Not KeyHit (1)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
xspeed=xspeed + xacceleration * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t
;we are using -yspeed because the computer counts lines from top to bottom and we want the ball to travel up the scren not down it. 

bally=bally-yspeed*t
Flip
Cls
Wend


now thats really boring again. it goes up. but what happened to what goes up must come down?

we must asses the gravity of the situation (bad pun)
now gravity always acts in a downward direction so the acceleration downards will be -10 m/s/s (-10 pixels)

this is exactly the same as we did for the x direction except that the ball is starting with a +ve speed (upward) and because the acceleration is downard (gravity) it will decelerate and then fall again.

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
yspeed# = 10

gravity# = -10

;note the x speed and acceleration has now been set to 0
xspeed# = 0
xacceleration = 0

time=MilliSecs()
While Not KeyHit (1)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Text 10,50,"yspeed = "+yspeed
Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
xspeed=xspeed + xacceleration * t

yspeed=yspeed + gravity * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t
;we are using -yspeed because the computer counts lines from top to bottom and we want the ball to travel up the scren not down it
bally=bally-yspeed*t
Flip
Cls
Wend


well it worked. it wasnt very exciting but it was more interesting than acceleration in the x direction because it fell through the floor. Im going to extend the while loop to drop out when the ball's height is less than the ground height and increase the ball's initial y velocity and put the x velocity back :)

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
;give us a decent upward speed to start with
yspeed# = 80

gravity# = -10

; and some speed along the ground
xspeed# = 30
xacceleration = 0

time=MilliSecs()
;stop the ball falling through the "floor"
While ((Not KeyHit (1)) And bally <= 480)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
xspeed=xspeed + xacceleration * t

yspeed=yspeed + gravity * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t
;we are using -yspeed because the computer counts lines from top to bottom and we want the ball to travel up the scren not down it
bally=bally-yspeed*t
Flip
Cls
Wend
WaitKey


and there we have it, a nice demonstration of the classic cannon ball shot.

but I said at an angle didnt I, even more I said it would be speed at an angle. Ok, Im a man of my word so lets now look at 2d resolution of velocity.

Assumption: an angle of 0 is HORIZONTAL

the physics term velocity is defined as speed with direction. IE its say 30 meters per second at an angle of 60 degrees to the ground plane.

Thats not a lot of use to us in its raw form but it does contain all the information we need to work out its vertical and horizontal velocities. Basically we are going to do some math. Trigonometry to be precise

if the speed is 80 m/s and the angle is 60 degrees then the horizontal component is given by speed * Cos(angle) and the vertical component is given by speed * sin (angle)

I have zeroed the xspeed and yspeed in the code, added 2 more variables for speed and angle and added 2 lines to calculate the x and y components of the velocity:


Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
;velocity
speed = 80
;angle
angle = 60

;we are going to calculate this shortly
yspeed# = 0

gravity# = -10

;we are going to calculate this shortly
xspeed# = 0
xacceleration = 0

;now to calculate the initial x and y speeds based on the firing angle and the speed/velocity

xspeed=speed * Cos(angle)
yspeed=speed * Sin(angle)


time=MilliSecs()
;stop the ball falling through the "floor"
While ((Not KeyHit (1)) And bally <= 480)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
xspeed=xspeed + xacceleration * t

yspeed=yspeed + gravity * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t
;we are using -yspeed because the computer counts lines from top to bottom and we want the ball to travel up the scren not down it
bally=bally-yspeed*t
Flip
Cls
Wend
WaitKey



much more like it :) we now have acceleration under gravity working properly. but what if the ball has mass. so far we've ignored that completely. well its not much different we are going to pretend our ball is a rocket (mostly because I dont want to make a rocket graphic) the rocket is going to have a mass of 5 kilos and some engines that will burn for a set time. these engines will do work on the mass accelerating it at an angle untill they stop burning. this is where F=ma comes in. the rocket will start with 0 velocity.


David819(Posted 2005) [#11]
Ok, Thanks for that, I've managed to get without functions the ball to go into the air and then back down :). I haven't added anything like mass yet though.


RepeatUntil(Posted 2005) [#12]
Why do you want to code your own physics engine?? There is already 3 physics engines available in Blitz!! Tokamak, and ODE 1 and 2 !!!


NewtSoup(Posted 2005) [#13]
What we need to do here is calculate the acceleration due to engine power and gravity in the x and y directions each program loop. to do this we use f=ma or rather a = f/m.

to resolve the thrust in the y direction we do exactly as we did with the speed in the above example using yforce = enginethrust * sin(angle). then we divide that by the mass of the ball (now a rocket) to give the acceleration due to engine thrust in the y direction. to this we add the acceleration due to gravity.

we do the same for the x direction

after the time engineburntime has elapsed we set enginethrust to 0 to simulate turning the engines off.

once we know the resultant acccelerations in the x and y axis we do exactly as we did before and add the acceleratin * t (program loop time) to work out the displacement since the last program cycle.

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
ballmass=5 ;this is in kg
enginethrust=250 ;this is in newtons
engineburntime = 2 ; this is in seconds
flighttime#=0 ;this is the flight time of the rocket so we can keep track of how long the engines have been burning for
;velocity
speed# = 0 ; this is not needed now
;angle
angle# = 70 ; this is the angle that the engines fire at

;we are going to calculate this shortly
yspeed# = 0
yacceleration# = 0

gravity# = -10 ; this is constant

;we are going to calculate this shortly
xspeed# = 0
xacceleration = 0

;now to calculate the initial x and y speeds based on the firing angle and the speed/velocity

xspeed=speed * Cos(angle)
yspeed=speed * Sin(angle)


time=MilliSecs()
;stop the ball falling through the "floor"
While ((Not KeyHit (1)) And bally <= 480)

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;add the looptime to flighttime so we know how long we have been flying
flighttime=flighttime+t


;first of all we need to resolve the force of the engines working on the ball in the x and y directions
xforce#=enginethrust * Cos (angle)
yforce#=enginethrust * Sin (angle)

;now we need to work out the accelerations in the x and y directions (F=ma therefore a=F/m)

xacceleration = xforce/ballmass
yacceleration = yforce/ballmass

;not forgetting gravity
yacceleration = yacceleration + gravity

;and finally lets not forget to turn the engines off after 5 seconds
If flighttime > engineburntime Then enginethrust=0

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Text 10,50,"yspeed = "+yspeed
Text 10,70,"Flight time = "+ flighttime
Text 10,90,"Engine thrust = " + enginethrust
Line 100,500,700,500
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
xspeed=xspeed + xacceleration * t

;changed this formula from gravity to acceleration because we worked out the actual acceleration in the y axis earlier
yspeed=yspeed + yacceleration * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t
;we are using -yspeed because the computer counts lines from top to bottom and we want the ball to travel up the scren not down it
bally=bally-yspeed*t
Flip
Cls
Wend
WaitKey



And that I think, conlcudes my intro to 2d particle physics. There's a hell of a lot more to it that what I have done but this should give complete beginners an insight into what you need to do.

I have tried to keep the code as simple as possible, as such theres a lot of hard coded information. Idealy if you were launching multiple rockets then you would create a type to hold the relevand information and use a for each loop to perfom the calculations needed on each rocket each program cycle. even as it is you could mess with the settings, allow player control of the angle via key presses, allow thrust control via a key press and you have a vectored thrust flying vehichle - Lunar lander anyone? :D


NewtSoup(Posted 2005) [#14]

Why do you want to code your own physics engine?? There is already 3 physics engines available in Blitz!! Tokamak, and ODE 1 and 2 !!!



perhaps he is interested in how these things work and values the learning experience of DIY?


NewtSoup(Posted 2005) [#15]
When you are ready heres some more code which demonstrates 2d gravitation in free space. its not entirely accurate as Ive played with the formulii to give pleasing results (IE it doesnt take half a year for a satelite to orbit a gravity well)

its based on the principle that the force on an object from a well varies inversely proportional to the distance of the object from the well. again its code ive posted before but a long time ago now.

;A simple program to demonstrate 2d gravitational physics
;the physics is not entirely accurate but more to the point
;it looks acceptable and produces nice patterns.
;incidentally this system also displays chaotic behaviour
;in that a small change in a satelites starting paramaters
;produces a large change in its path trail as you will see by the
;two demonstration satelites having a difference of 0.1 degree in their
;start angle and everything else identical
Type satelite
	Field x#;statelite position x and y coord
	Field y#
	Field dx#;speed of the satelite in x and y dir
	Field dy#
	Field fx#;forces acting on the satelite in x and y directions
	Field fy#
	Field mass; mass of the satelite
	Field pathStart.pathpoint
	Field colour ; colour of path
	Field crashed
End Type

Type well
	Field gravity#; gravitational force of the well
	Field x#; wells xy coords
	Field y#
End Type

Type pathpoint
	Field n.pathpoint
	Field x
	Field y
End Type

Graphics 800,600,32,2

Global period#
Global pathLength
Global maxLength = 1024
Global count = 0
Global maxmag#=0

Global this_time=MilliSecs()
Global Last_time=MilliSecs()


;make a satelite And set it with some initial values
a#=110
s.satelite =New satelite
s\x = 100
s\y = 150
s\dx=1*Sin (a)
s\dy=- 1* Cos (a)
s\mass = 5
s\colour=$FF0000

a2#=135
s2.satelite =New satelite
s2\x = 150
s2\y = 150
s2\dx=1* Sin (a2)
s2\dy=-1* Cos (a2)
s2\mass = 4
s2\colour=$00FF00

;create a gravity well
w.well= New well
w\x=400
w\y=300
w\gravity=90000

;And another For good measure
w2.well= New well
w2\x=200
w2\y=300
w2\gravity=90000


;And another For good measure
w3.well= New well
w3\x=350
w3\y=300-100*(Sqr(3)/2)
w3\gravity=90000

SetBuffer BackBuffer()

;this is the time passed in each program loop
;idealy you would set this each loop using some realtime clock code
;but for simplicity here we will hard code it to 10 milliseconds
period=0.01

While Not KeyHit(1)

	For s.satelite=Each satelite
	
		s\fx=0
		s\fy=0

		resolveForces(s,w)
		resolveForces(s,w2)
		resolveForces(s,w3)
		updateSatelite(s)
		;dampSatelite(s)
		drawSatelite(s)
		
	Next



	drawWell(w)
	drawWell(w2)
	drawWell(w3)


	makepath()
	drawpath()
	If crashed And (First satelite)=Null Then Exit
	count=count +1
	Text 10,10,period
	Flip
	Cls
	
	Last_time=this_time
	this_time=MilliSecs()
	;calc the period To the nearest 10 ms
	period=(this_time-Last_time)/(10)/Float(100.0)
	
Wend

End

Function dampSatelite(s.satelite)
	s\dx=0.999 * s\dx
	s\dy=0.999 * s\dy
	

End Function

Function resolveForces( s.satelite, w.well)
	;the force on the satelite always works towards the well
	;the force on the satelite is proportional to 1/r^2
	;where r is the distance between the satelite and the center of gravity

	;find the wells position relative to the satelite
	Local dx#=w\x-s\x
	Local dy#=w\y-s\y
	;calc r^2
	Local r2#=((dx)^2+(dy)^2)
	;calc r
	Local r#=Sqr(r2)
	;calc mag of force at the satelites position
	Local f#= w\gravity * r2^-1
	;resolve in the x and y
	s\fy=s\fy+f*(dy/r)
	s\fx=s\fx+f*(dx/r)
	

End Function


Function updateSatelite(s.satelite)
	If s\crashed=1 Then Return
	;apply newtons laws in x and y directions
	;incrementing the satelites position proportional to the period
	dx#=s\dx
	;newtons law f=ma re-arranged to be a=f/m
	ax#=s\fx/s\mass
	;newtons law v=u+at
	s\dx=dx+ax*period
	
	dy#=s\dy
	ay#=s\fy/s\mass
	s\dy=dy+ay*period
	s\x=s\x+s\dx
	s\y=s\y+s\dy


	
	
	For w.well=Each well
		Local x=s\x
		Local y=s\y
		Local x1=w\x
		Local y1=w\y
		If ((x-x1)^2+(y-y1)^2)<25 Then
			s\x=w\x
			s\y=w\y
			s\dx=0
			s\dy=0
			s\crashed=1
		End If
	Next
	
	
End Function



Function drawSatelite(s.satelite)
	;just a dot will do
	mag#=Sqr(s\fx^2+s\fy^2)
	Plot s\x,s\y
	Text s\x,s\y,"*",1,1
	l=50*(mag/80)
	;If Not s\crashed Then Line s\x,s\y,s\x+(l*(s\fx/mag)),s\y+(l*(s\fy/mag))
	
End Function

Function drawWell(w.well)

	;a nice + to mark the center of gravitation
	Line w\x-5,w\y,w\x+5,w\y
	Line w\x,w\y-5,w\x,w\y+5
	

End Function

Function makePath()

	If count = 3
		For s.satelite = Each satelite
			If Not s\crashed Then
				p.pathpoint=New pathpoint
				p\n=s\pathStart
				p\x=s\x
				p\y=s\y
				s\pathstart=p
				pathLength=pathLength+1
			End If
		Next
		count = 0
	
		
	End If
End Function

Function drawPath()
	LockBuffer BackBuffer()
	
	For s.satelite=Each satelite
		idx=0
		p.pathpoint=s\pathstart
		If p<> Null
			While p\n<> Null
				idx=idx+1
				If p\x>0 And p\x<800 And p\y>0 And p\y<600
					c=255*(maxlength-idx)/maxlength
					col=c Shl( 16) + c Shl(8) + c
					WritePixelFast p\x,p\y,s\colour And col
				End If
				p=p\n
			Wend
		End If
	
		If pathLength>maxLength Then
			Delete First pathPoint
		End If
		If pathlength>maxlength Then pathlength=pathlength -1	
	Next
	
	
	UnlockBuffer BackBuffer()
End Function





Interestingly enough this program also displays chaotic behaviour in that small changes to the satelites starting position/angle can create radical changes in its flight path. in the code I have given the 2 satellites do not interact with each other. they are only there so you can compare different settings. basically this is a toy.


NewtSoup(Posted 2005) [#16]
ignore the comments at the start of the code.. Ive been playing with the parameteres since I wrote that :D


NewtSoup(Posted 2005) [#17]
Just for the bouncing ball fans :) Ive added 5 lines of code to my prog to draw in 2 side walls and make the ball reflect of the ground and walls. Oh and I changed the force of gravity and the mass of the ball and the engine thrust to make the whole animation a bit quicker (I did NOT modify the phys routines at all)

Graphics 800,600,32,2

SetBuffer BackBuffer()

ballx#=100
bally#=480
ballr=20
ballmass=1;this is in kg
enginethrust=500 ;this is in newtons
engineburntime = 1 ; this is in seconds
flighttime#=0 ;this is the flight time of the rocket so we can keep track of how long the engines have been burning for
;velocity
speed# = 0 ;this is not needed now
;angle
angle# = 60 ; this is the angle that the engines fire at

;we are going to calculate this shortly
yspeed# = 0
yacceleration# = 0

gravity# = -200; this is constant

;we are going to calculate this shortly
xspeed# = 0
xacceleration = 0

;now to calculate the initial x and y speeds based on the firing angle and the speed/velocity

xspeed=speed * Cos(angle)
yspeed=speed * Sin(angle)


time=MilliSecs()
;stop the ball falling through the "floor"
While ((Not KeyHit (1)))

;this is our loop time calculator
oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

;add the looptime to flighttime so we know how long we have been flying
flighttime=flighttime+t


;first of all we need to resolve the force of the engines working on the ball in the x and y directions
xforce#=enginethrust * Cos (angle)
yforce#=enginethrust * Sin (angle)

;now we need to work out the accelerations in the x and y directions (F=ma therefore a=F/m)

xacceleration = xforce/ballmass
yacceleration = yforce/ballmass

;not forgetting gravity
yacceleration = yacceleration + gravity

;and finally lets not forget to turn the engines off after 5 seconds
If flighttime > engineburntime Then enginethrust=0

;this is just to show the time on the screen
Text 10,10,"Program loop time = "+t+" seconds"
Text 10,30,"xspeed = "+xspeed
Text 10,50,"yspeed = "+yspeed
Text 10,70,"Flight time = "+ flighttime
Text 10,90,"Engine thrust = " + enginethrust
Line 100,500,700,500
Line 100,500,100,100
Line 700,500,700,100
Oval ballx,bally,ballr,ballr

;we are going to accelerate the ball
xspeed=xspeed + xacceleration * t 

;changed this formula from gravity to acceleration because we worked out the actual acceleration in the y axis earlier
yspeed=yspeed + yacceleration * t

;now we move the ball according to how much time has passed
ballx=ballx+xspeed*t
;we are using -yspeed because the computer counts lines from top to bottom and we want the ball to travel up the scren not down it
bally=bally-yspeed*t

If bally>480 Then yspeed=-yspeed :bally=480
If ballx<100 Then xspeed=-xspeed :ballx=100 : angle=angle-180
If ballx>680 Then xspeed=-xspeed :ballx=680 : angle=angle-180
Flip
Cls
Wend
WaitKey





David819(Posted 2005) [#18]
Thanks.


NewtSoup(Posted 2005) [#19]
The way forward from here:
once you have the idea of what the newton laws do and how to use them I'd next go onto changing the program as it is to use vector calculation (loads of sources on the net) so that the speed of the ball, the gravity and the thrust force are represented as vectors. Its easier than you think because vectors just represent vertical and horizontal components in 2d (vertical horizontal and forward in 3d, x,y,x)


David819(Posted 2005) [#20]
Ok i've kinda got it to bound but am having some difficulties because i've never touched 2d and find it hard to understand: here is my code anyhow.

;--------------------Graphics---------------------
Graphics3D 1280,1024,32,1
SetBuffer BackBuffer()

;--------------------Constants--------------------
Const Ground_Type=1
Const Ball_Type=2
yspeed# = .022
gravity# = -.01
elasticity#=.9

;velocity
speed = 80
;angle
angle = 60

;we are going to calculate this shortly
xspeed# = .01
xacceleration = 0
yspeed# = .02
yacceleration = 0
zspeed# = .01
zacceleration = 0

;xspeed=speed * Cos(angle)
;yspeed=speed * Sin(angle)


time=MilliSecs()

;--------------------SetUp------------------------
Camera=CreateCamera()
PositionEntity camera,0,5,-30
CameraRange camera,.01,10000
Light=CreateLight()

;--
CameraClsMode camera,False,True

sprite=CreateCube()
EntityColor sprite,0,0,0
ScaleEntity sprite,10000,10000,10000
PositionEntity sprite,0,-5000,0
FlipMesh Sprite
EntityAlpha sprite,.01
;--

Texture=LoadTexture("Rope.jpg")
Surface=CreatePlane()
;Surface=LoadMesh("plane.3ds")
;RotateEntity surface,90,0,0
EntityTexture Surface,Texture
EntityType Surface,Ground_Type
EntityAlpha surface,1

surface2=CreateCube()
ScaleEntity surface2,1,15,1
EntityType surface2,ground_type
EntityAlpha surface2,1
EntityTexture surface2,texture
PositionEntity surface2,0,4,0

Entity=CreateSphere()
PositionEntity Entity,-20,4,0
EntityColor Entity,255,0,0
EntityShininess Entity,2
EntityType Entity,Ball_Type

Collisions Ball_Type,Ground_Type,2,2

;--------------------Loop-------------------------
While Not KeyHit(1)

oldtime=time
time=MilliSecs()
t#=Float((time-oldtime))/1000

xspeed=xspeed + xacceleration * t
yspeed=yspeed + gravity * t

If EntityY(entity)<2 Then YSpeed#=Abs(YSpeed#) * elasticity#

MoveEntity Entity,xspeed,yspeed,0

UpdateWorld
RenderWorld

frames=frames+1
If MilliSecs()-render_time=>1000 Then fps=frames : frames=0 : render_time=MilliSecs()
Text 0,0,fps

Flip
Wend
End


David819(Posted 2005) [#21]
Oh, it's just the angle thing which is confusing me. not the hole thing.


NewtSoup(Posted 2005) [#22]
Sorry Ive been away for a couple of days.. Just had a look at your code, dont worry too much, the gravity is working. Im guessing what you meant was for the ball to rebound when it hits the wall?

Think about what happens when a real ball hits the wall. Which components of the velocities will change? (we will assume a perfect collision where no energy is lost)


In the case of a vertical wall and the ball moving in the x direction only the x component will change, and in the case of the ground only the y component changes.

If your ball moved in the z direction and you had a back wall only the z component would change

If you are confused about the starting angle I gave the ball then think I will try to explain

y
^
|          /|
|     Hyp / |
|        /  |oposite
|       /   |
|______o_ __|________________---> x
\\\\\\ground\\\\\\\\\\\\\\\\\


The ball o is given an intial angle a and a speed s
a is the angle between the ground and the direction of the ball's travel.

In order to perform useful calculations on this we need to break the speed down into the x and y components. How much of the speed is in the x and y directions is determined by the angle.

The math involved is quite simply that of a right angle triangle. We take the speed to be the Hypoteneus and the x and y components to be the size of the Oposite side of the triangle and the adjacent ground plane
the rule is of course SOHCAHTOA

Sin(a)=Opposite/Hypoteneus
Cos(a)=Adjacent/Hyponeneus
Tan(a)=Opposite/Adjacent

We know a and we know the size of the hypoteneus (the speed of the ball) and what we want to know is the size of the Opposite (y component of the speed) and the adjacent (x component of the speed)

so given

Sin(a)=Opposite/Hypoteneus

then
Sin(a)=xspeed/speed
therefore
Sin(a)*speed=xspeed

xspeed=Sin(a)*speed

similarly the yspeed can be shown to be

yspeed=Cos(a)*speed

hope this helps.


David819(Posted 2005) [#23]
ok, thanks, maybe i should leave this for a time when i'm better at programing and understand physics better.