from visual import * # this function does the actual movement # of an object, given the force on it # and time it acts # it also moves fake shadows around def mover ( obj, force, dt, shadow ): # find acceleration acc = vector (0,0,0) acc = force / obj.mass # move object obj.velocity = obj.velocity + acc * dt obj.pos = obj.pos + obj.velocity * dt # check limits on movement # the floor if ( obj.pos.y < 0.0 + obj.radius ): # next line prevents obj digging in on bounces obj.pos.y = - (obj.pos.y - obj.radius ) + obj.radius obj.velocity.y = - obj.velocity.y # left wall if ( obj.pos.x < -10.0 + obj.radius ): obj.velocity.x = - obj.velocity.x # right wall if ( obj.pos.x > 10.0 - obj.radius ): obj.velocity.x = - obj.velocity.x # back wall if ( obj.pos.z < -10.0 + obj.radius ): obj.velocity.z = - obj.velocity.z # front wall if ( obj.pos.z > 10.0 - obj.radius ): obj.velocity.z = - obj.velocity.z # move shadows shadow.pos.x = obj.pos.x shadow.pos.z = obj.pos.z return # make two balls bounce around and collide # set up balls ballRad = 1.5 ball1 = sphere ( pos=( 3,ballRad+5,0 ), radius = ballRad, color= color.red ) ball2 = sphere ( pos=(-2,ballRad+2,2 ), radius = ballRad, color=color.yellow ) # initial velocities, masses ball1.velocity = vector( -1, 6, 1.5 ) ball2.velocity = vector( 1, -4, 3 ) ball1.mass = 5.0 ball2.mass = 3.0 # ball shadows shadow1 = cylinder ( pos=( ball1.pos.x,0,ball1.pos.z ), radius=ballRad, length= 0.05, color=color.black, axis= (0,0.05,0) ) shadow2 = cylinder ( pos=( ball2.pos.x,0,ball2.pos.z ), radius=ballRad, length= 0.05, color=color.black, axis= (0,0.05,0) ) # make world floor = box ( size = (20, 0.5, 20 )) floor.pos.y = -0.25 backwall = box ( size = ( 20,20, 0.5 ), pos= ( 0,10,-10.25 )) scene.autoscale = 0 #collision epsilon- fraction of velocity conserved after collision epsilon = 0.9 # world vars g = -2 dt =0.04 drag = 0.01 # big loop while 1: rate(100) # move balls- find forces and move them f1 = vector( 0,1,0 ) * ball1.mass * g mover ( ball1, f1, dt, shadow1 ) f2 = vector( 0,1,0 ) * ball2.mass * g mover ( ball2, f2, dt, shadow2 ) #check for collisions n = ball2.pos - ball1.pos if ( mag(n) < (ball1.radius + ball2.radius) ): # they collided print "collision!" # figure out collision # set up some variables for collision # analyze collision in tiny time steps dt2 = dt/100 nhat = norm(n) # closing velocities v1n = dot ( ball1.velocity, nhat ) v2n = dot ( ball2.velocity, nhat ) # force applied at each time step- a guess dF = nhat * (ball1.mass + ball2.mass)*(v1n-v2n)*10.0 # number of time steps nHits = 0 # have forces work on balls, then see if velocities are still # closing, or are they moving apart yet while ( v2n-v1n ) < 0: # apply dF to each ball for dt2 time mover ( ball1, -dF, dt2, shadow1 ) mover ( ball2, dF, dt2, shadow2 ) # find new closing velocities v1n = dot ( ball1.velocity, nhat ) v2n = dot ( ball2.velocity, nhat ) nHits = nHits + 1 # balls have now stopped closing on each other # now they do forces as they spread apart print " collision took ", nHits, " steps" while ( nHits > 0 ): mover ( ball1, -dF*epsilon, dt2, shadow1 ) mover ( ball2, dF*epsilon, dt2, shadow2 ) nHits = nHits -1