Physics
Blitz3D Forums/Blitz3D Beginners Area/Physics
| ||
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. |
| ||
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. |
| ||
I remember your rope effect Rob. It was kinda cool. Did you ever manage to perfect it? |
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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 |
| ||
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. |
| ||
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) |
| ||
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. |
| ||
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. |
| ||
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 !!! |
| ||
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 |
| ||
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? |
| ||
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. |
| ||
ignore the comments at the start of the code.. Ive been playing with the parameteres since I wrote that :D |
| ||
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 |
| ||
Thanks. |
| ||
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) |
| ||
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 |
| ||
Oh, it's just the angle thing which is confusing me. not the hole thing. |
| ||
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. |
| ||
ok, thanks, maybe i should leave this for a time when i'm better at programing and understand physics better. |