Small problem with Ball physics code...
Blitz3D Forums/Blitz3D Programming/Small problem with Ball physics code...
| ||
Can someone please help me with this Ball physics code, I adapted it from the Ball rolling physics example by Jeppe Nielsen. I made it directional control using the arrow keys. The problem is that at first pressing up,down,left,right works fine but after bouncing around the board for awhile the directions start to act as if the ball is turned, but I can't find in the code what does this, can someone please take a look and help me find whats causing this. Thanks in advance. Press space to jump, do this a few times while moving around and the problem surfaces when you try to roll around. Graphics3D 800,600,32 SetBuffer BackBuffer() WBuffer False HidePointer SeedRnd MilliSecs() ;frametweening Global gameFPS = 60 Global framePeriod = 1000 / gameFPS Global frameTime = MilliSecs () - framePeriod framePeriod = 1000 / gameFPS frameTime = MilliSecs () - framePeriod Const gravity#=-0.06 arena=CreatePlane() EntityColor arena,Rnd(0,200),Rnd(0,200),Rnd(0,200) PositionEntity arena,0,-5,0 EntityType arena,world_col obj_1=CreateCube() EntityType obj_1,world_col PositionEntity obj_1,-10,-10,15 ScaleEntity obj_1,10,10,10 RotateEntity obj_1,45,90,0 EntityColor obj_1,Rnd(0,200),Rnd(0,200),Rnd(0,200) obj_2=CreateSphere() EntityType obj_2,world_col PositionEntity obj_2,25,-1,-17 ScaleEntity obj_2,15,5,15 EntityColor obj_2,Rnd(0,200),Rnd(0,200),Rnd(0,200) obj_3=CreateCube();walls EntityType obj_3,world_col PositionEntity obj_3,0,-10,0 ScaleEntity obj_3,70,70,70 EntityColor obj_3,Rnd(0,200),Rnd(0,200),Rnd(0,200) FlipMesh obj_3 light=CreateLight(1) RotateEntity light,30,20,0 camera=CreateCamera() CameraClsColor camera,0,100,155 PositionEntity camera,0,600,-420 RotateEntity camera,55,0,0 CameraZoom Camera,10 ball.ball=ballnew(0,4,-40,2,.8,1) ball.ball=ballnew(-10,4,-40,2,.8,2) ball.ball=ballnew(10,100,-30,1.75,.8,3) Const ball_col=1 Const world_col=3 Collisions ball_col,world_col,2,2 Collisions ball_col,ball_col,1,2 Type ball Field Ball_Type Field e ;entity Field sphere Field pivot Field x#,y#,z# ; position in 3d-space Field vx#,vy#,vz# ; velocity Field ax#,ay#,az# ; acceleration Field size# Field bounce# ; bounce factor Field vel# Field vx2#,vy2#,vz2# ; temp velocity Field xSpd#,xSpdMax#,xSpdMin# Field zSpd#,zSpdMax#,zSpdMin# End Type Function ballnew.ball(x#,y#,z#,size#=1,bounce#=0.9,Ball_Type) c.ball=New ball c\x#=x# c\y#=y# c\z#=z# c\size=size c\bounce#=bounce# c\e=CreatePivot() c\sphere=CreateSphere(16) c\pivot=CreatePivot() EntityType c\e,ball_col EntityRadius c\e,c\size PositionEntity c\e,c\x,c\y,c\z ScaleEntity c\sphere,c\size,c\size,c\size EntityColor c\sphere,Rnd(0,255),Rnd(0,255),Rnd(0,255) c\Ball_Type=Ball_Type c\xSpdMin#=-.02 c\xSpdMax#=.02 c\zSpdMin#=-.02 c\zSpdMax#=.02 Return c End Function Function ballupdate() For c.ball=Each ball c\vy#=c\vy#+gravity# c\vx#=c\vx#+c\ax# c\vy#=c\vy#+c\ay# c\vz#=c\vz#+c\az# c\x#=EntityX(c\e) c\y#=EntityY(c\e) c\z#=EntityZ(c\e) TranslateEntity c\e,c\vx,c\vy,c\vz Next UpdateWorld() For c.ball=Each ball ;correct velocity if collided c\vx2=(EntityX(c\e)-c\x) c\vy2=(EntityY(c\e)-c\y) c\vz2=(EntityZ(c\e)-c\z) c\x#=EntityX(c\e) c\y#=EntityY(c\e) c\z#=EntityZ(c\e) PositionEntity c\sphere,c\x,c\y,c\z PositionEntity c\pivot,c\x,c\y,c\z If EntityCollided(c\e,world_col) For i = 1 To CountCollisions(c\e) Ent=CollisionEntity (c\e, i) ; Get the normal of the surface which the entity collided with. Nx# = CollisionNX(c\e, i) Ny# = CollisionNY(c\e, i) Nz# = CollisionNZ(c\e, i) ; Compute the dot product of the entity's motion vector and the normal of the surface collided with. VdotN# = c\vx#*Nx# + c\vy#*Ny# + c\vz#*Nz# ; Calculate the normal force. NFx# = -2.0 * Nx# * VdotN# NFy# = -2.0 * Ny# * VdotN# NFz# = -2.0 * Nz# * VdotN# ; Add the normal force to the direction vector. c\vx# = c\vx# + NFx# * c\bounce# c\vy# = c\vy# + NFy# * c\bounce# c\vz# = c\vz# + NFz# * c\bounce# avx#=EntityPitch(c\sphere) avy#=EntityYaw(c\sphere) avz#=EntityRoll(c\sphere) ;Rotate stuff ;Get vector from center to collision dx1#=(CollisionX(c\e,i)-c\x) dy1#=(CollisionY(c\e,i)-c\y) dz1#=(CollisionZ(c\e,i)-c\z) dx2#=c\vx dy2#=c\vy dz2#=c\vz ;Cross product cx# = ( dy1 * dz2 ) - ( dz1 * dy2 ) cy# = ( dz1 * dx2 ) - ( dx1 * dz2 ) cz# = ( dx1 * dy2 ) - ( dy1 * dx2 ) AlignToVector c\pivot,cx,cy,cz,1 ;Add Force to other Ball For Hit.Ball = Each Ball If Hit\E = Ent Then If Hit\Ball_Type=2 div=2 If Hit\Ball_Type=3 div=1.5 Hit\vx# = Hit\vx# - NFx#/div Hit\vy# = Hit\vy# - NFy#/div ;Force /2 assumes balls equal in mass Hit\vz# = Hit\vz# - NFz#/div End If Next Next Nx# = CollisionNX(c\e, 1) Ny# = CollisionNY(c\e, 1) Nz# = CollisionNZ(c\e, 1) AlignToVector c\e,Nx#,Ny#,Nz#,2,0.5 c\vel#=Sqr(c\vx2*c\vx2+c\vy2*c\vy2+c\vz2*c\vz2) ;slow down due to friction c\vx#=c\vx*0.99 c\vy#=c\vy*0.99 c\vz#=c\vz*0.99 EndIf EntityParent c\sphere,c\pivot TurnEntity c\pivot,-c\vel#*(180/Pi)/c\size#,0,0 EntityParent c\sphere,0 c\ax#=0 c\ay#=0 c\az#=0 Next End Function Function ballcontrol(Ball_Type) For c.ball=Each ball If Ball_Type=c\Ball_Type ;**** Add Directional Speed **** If KeyDown(203) And c\xSpd#>c\xSpdMin# c\xSpd#=c\xSpd#-.001;Left EndIf If KeyDown(205) And c\xSpd#<c\xSpdMax# c\xSpd#=c\xSpd#+.001;Right EndIf If KeyDown(200) And c\zSpd#>c\zSpdMin# c\zSpd#=c\zSpd#+.001;Up EndIf If KeyDown(208) And c\zSpd#<c\zSpdMax# c\zSpd#=c\zSpd#-.001;Down EndIf ;**** Subtract Directional Speed **** If Not KeyDown(203) And KeyDown(205) If c\xSpd#<0 c\xSpd#=c\xSpd#*.96 If c\xSpd#>0 c\xSpd#=c\xSpd#*.96 If c\xSpd#<.0001 And c\xSpd#>-.0001 Then c\xSpd#=0 EndIf If Not KeyDown(200) And KeyDown(208) If c\zSpd#<0c\zSpd#=c\zSpd#*.96 If c\zSpd#>0 c\zSpd#=c\zSpd#*.96 If c\zSpd#<.0001 And c\zSpd#>-.0001 Then c\zSpd#=0 EndIf TFormVector c\xSpd#,0,c\zSpd#,c\e,0 c\ax#=TFormedX() c\ay#=TFormedY() c\az#=TFormedZ() If KeyHit(57);jump TFormVector 0,2,0,c\e,0 c\ax#=c\ax+TFormedX() c\ay#=c\ay+TFormedY() c\az#=c\az+TFormedZ() EndIf EndIf Next End Function Function In_Action() While Not KeyDown(1) ; Frame limiting Repeat frameElapsed = MilliSecs () - frameTime Until frameElapsed frameTicks = frameElapsed / framePeriod frameTween# = Float (frameElapsed Mod framePeriod) / Float (framePeriod) ; Update game and world state For frameLimit = 1 To frameTicks If frameLimit = frameTicks Then CaptureWorld frameTime = frameTime + framePeriod ; ---------------------------------- ballcontrol(1) ballupdate() Next RenderWorld frameTween Text 10,10,"Rendered Tris : "+ TrisRendered() Text 10,30,"Use the Arrow Keys to Move" Text 10,40,"Use the Spacebar to jump" Flip Wend End Function While Not KeyDown(1) In_Action() Wend |
| ||
Well I think I know why it is doing it. You are tforming a vector from the entity to the world. All well and good but you are also aligning this entity to the normals of the collision with another ball. The two combined are causing the problem. Now I am not sure you need that aligntovector at all, and as for the ball control impulses I would apply them based on the camera yaw, which may be more useful. (Tform from a pivot which just yaws the camera). Something else to bear in mind with colliding balls is that you can from memory get anywhere from 1 to 3 collisions per impact. (There is some code posted somewhere that demonstrates this - here it is http://www.blitzbasic.co.nz/Community/posts.php?topic=27138 ). You might want to account for this, but at the end of the day as long as the thing behaves as you want I would not worry too much. |
| ||
YOU ARE MY NEW FAVORITE PERSON. |
| ||
Taking out the aligntovector worked great |
| ||
I'm afraid I've found a problem. I tried pushing the system a little further by creating several objects. Try this in place of the three lines to create the balls...For MakinBalls = 1 To 40 ball.ball=ballnew(10+Rnd(0,5),100+Rnd(0,5),-30-Rnd(0,20), Rnd(1,2), 0.8, (MakinBalls Mod 3)+1) Next I find that they gradually get stuck in space. Looks to me like they're getting caught up in a perpetual loop reacting to collisions-- except that they aren't vibrating at all. So I don't know. I'll keep looking. |
| ||
Well as it stands it's only processing collisions when there is a world contact. But it is a work in progress. |
| ||
Barliesque-Thanks for pointing that out, fortunatly for me I don't need that many balls on the screen during the game. |
| ||
Well it's a great little piece of code. Would be nice to sort out that problem so it's usable for other projects as well---either new projects of your own, or others in the community. Actually... I don't think it's the number of balls that causes the problem. It's just that having so many in there at once makes it more likely for the problem to occur. If that's true, then it could happen infrequently even with only three balls. |