samples/04_physics_and_collisions/08_bouncing_on_collision/app/peg.rb
def collide args
    normalOfRCCollision = [                                                     #this is the normal of the collision in COMPONENT FORM
      {x: @center.x, y: @center.y},                                             #see https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.mathscard.co.uk%2Fonline%2Fcircle-coordinate-geometry%2F&psig=AOvVaw2GcD-e2-nJR_IUKpw3hO98&ust=1605731315521000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCMjBo7e1iu0CFQAAAAAdAAAAABAD
      {x: args.state.ball.center.x, y: args.state.ball.center.y},
    ]

    normalSlope = (                                                             #normalSlope is the slope of normalOfRCCollision
      (normalOfRCCollision[1].y - normalOfRCCollision[0].y) /
      (normalOfRCCollision[1].x - normalOfRCCollision[0].x)
    )
    slope = normalSlope**-1.0 * -1                                              # slope is the slope of the tangent
    # args.state.display_value = slope
    pointA = {                                                                  # pointA and pointB are using the var slope to tangent in COMPONENT FORM
      x: args.state.ball.center.x-1,
      y: -(slope-args.state.ball.center.y)
    }
    pointB = {
      x: args.state.ball.center.x+1,
      y: slope+args.state.ball.center.y
    }

    perpVect = {x: pointB.x - pointA.x, y:pointB.y - pointA.y}                  # perpVect is to be VECTOR of the perpendicular tangent
    mag  = (perpVect.x**2 + perpVect.y**2)**0.5                                 # find the magniude of the perpVect
    perpVect = {x: perpVect.x/(mag), y: perpVect.y/(mag)}                       # divide the perpVect by the magniude to make it a unit vector
    perpVect = {x: -perpVect.y, y: perpVect.x}                                  # swap the x and y and multiply by -1 to make the vector perpendicular
    args.state.display_value = perpVect
    if perpVect.y > 0                                                           #ensure perpVect points upward
      perpVect = {x: perpVect.x*-1, y: perpVect.y*-1}
    end

    previousPosition = {                                                        # calculate an ESTIMATE of the previousPosition of the ball
      x:args.state.ball.center.x-args.state.ball.velocity.x,
      y:args.state.ball.center.y-args.state.ball.velocity.y
    }

    yInterc = pointA.y + -slope*pointA.x
    if slope == INFINITY                                                        # the perpVect presently either points in the correct dirrection or it is 180 degrees off we need to correct this
      if previousPosition.x < pointA.x
        perpVect = {x: perpVect.x*-1, y: perpVect.y*-1}
        yInterc = -INFINITY
      end
    elsif previousPosition.y < slope*previousPosition.x + yInterc               # check if ball is bellow or above the collider to determine if perpVect is - or +
      perpVect = {x: perpVect.x*-1, y: perpVect.y*-1}
    end

    velocityMag =                                                               # the current velocity magnitude of the ball
      (args.state.ball.velocity.x**2 + args.state.ball.velocity.y**2)**0.5
    theta_ball=
      Math.atan2(args.state.ball.velocity.y,args.state.ball.velocity.x)         #the angle of the ball's velocity
    theta_repel=
      Math.atan2(args.state.ball.center.y,args.state.ball.center.x)             #the angle of the repelling force(perpVect)

    fbx = velocityMag * Math.cos(theta_ball)                                    #the x component of the ball's velocity
    fby = velocityMag * Math.sin(theta_ball)                                    #the y component of the ball's velocity
    repelMag = getRepelMagnitude(                                               # the magniude of the collision vector
      args,
      fbx,
      fby,
      perpVect.x,
      perpVect.y,
      (args.state.ball.velocity.x**2 + args.state.ball.velocity.y**2)**0.5
    )
    frx = repelMag* Math.cos(theta_repel)                                       #the x component of the repel's velocity | magnitude is set to twice of fbx
    fry = repelMag* Math.sin(theta_repel)                                       #the y component of the repel's velocity | magnitude is set to twice of fby

    fsumx = fbx+frx                            # sum of x forces
    fsumy = fby+fry                            # sum of y forces
    fr = velocityMag                           # fr is the resulting magnitude
    thetaNew = Math.atan2(fsumy, fsumx)        # thetaNew is the resulting angle
    xnew = fr*Math.cos(thetaNew)               # resulting x velocity
    ynew = fr*Math.sin(thetaNew)               # resulting y velocity
    if (args.state.ball.center.x >= @center.x) # this is necessary for the ball colliding on the right side of the peg
      xnew=xnew.abs
    end

    args.state.ball.velocity.x = xnew                                           # set the x-velocity to the new velocity
    if args.state.ball.center.y > @center.y                                     # if the ball is above the middle of the peg we need to temporarily ignore some of the gravity
      args.state.ball.velocity.y = ynew + GRAVITY * 0.01
    else
      args.state.ball.velocity.y = ynew - GRAVITY * 0.01                        # if the ball is bellow the middle of the peg we need to temporarily increase the power of the gravity
    end

    args.state.ball.center.x+= args.state.ball.velocity.x                       # update the position of the ball so it never looks like the ball is intersecting the circle
    args.state.ball.center.y+= args.state.ball.velocity.y
  end
#this sets the new velocity of the ball once it has collided with this peg
this sets the new velocity of the ball once it has collided with this peg
this sets the new velocity of the ball once it has collided with this peg
def collide args
    normalOfRCCollision = [                                                     
      {x: @center.x, y: @center.y},                                             
      {x: args.state.ball.center.x, y: args.state.ball.center.y},
    ]
    normalSlope = (                                                             
      (normalOfRCCollision[1].y - normalOfRCCollision[0].y) /
      (normalOfRCCollision[1].x - normalOfRCCollision[0].x)
    )
    slope = normalSlope**-1.0 * -1                                              
    pointA = {                                                                  
      x: args.state.ball.center.x-1,
      y: -(slope-args.state.ball.center.y)
    }
    pointB = {
      x: args.state.ball.center.x+1,
      y: slope+args.state.ball.center.y
    }
    perpVect = {x: pointB.x - pointA.x, y:pointB.y - pointA.y}                  
    mag  = (perpVect.x**2 + perpVect.y**2)**0.5                                 
    perpVect = {x: perpVect.x/(mag), y: perpVect.y/(mag)}                       
    perpVect = {x: -perpVect.y, y: perpVect.x}                                  
    args.state.display_value = perpVect
    if perpVect.y > 0                                                           
      perpVect = {x: perpVect.x*-1, y: perpVect.y*-1}
    end
    previousPosition = {                                                        
      x:args.state.ball.center.x-args.state.ball.velocity.x,
      y:args.state.ball.center.y-args.state.ball.velocity.y
    }
    yInterc = pointA.y + -slope*pointA.x
    if slope == INFINITY                                                        
      if previousPosition.x < pointA.x
        perpVect = {x: perpVect.x*-1, y: perpVect.y*-1}
        yInterc = -INFINITY
      end
    elsif previousPosition.y < slope*previousPosition.x + yInterc               
      perpVect = {x: perpVect.x*-1, y: perpVect.y*-1}
    end
    velocityMag =                                                               
      (args.state.ball.velocity.x**2 + args.state.ball.velocity.y**2)**0.5
    theta_ball=
      Math.atan2(args.state.ball.velocity.y,args.state.ball.velocity.x)         
    theta_repel=
      Math.atan2(args.state.ball.center.y,args.state.ball.center.x)             
    fbx = velocityMag * Math.cos(theta_ball)                                    
    fby = velocityMag * Math.sin(theta_ball)                                    
    repelMag = getRepelMagnitude(                                               
      args,
      fbx,
      fby,
      perpVect.x,
      perpVect.y,
      (args.state.ball.velocity.x**2 + args.state.ball.velocity.y**2)**0.5
    )
    frx = repelMag* Math.cos(theta_repel)                                       
    fry = repelMag* Math.sin(theta_repel)                                       
    fsumx = fbx+frx                            
    fsumy = fby+fry                            
    fr = velocityMag                           
    thetaNew = Math.atan2(fsumy, fsumx)        
    xnew = fr*Math.cos(thetaNew)               
    ynew = fr*Math.sin(thetaNew)               
    if (args.state.ball.center.x >= @center.x) 
      xnew=xnew.abs
    end
    args.state.ball.velocity.x = xnew                                           
    if args.state.ball.center.y > @center.y                                     
      args.state.ball.velocity.y = ynew + GRAVITY * 0.01
    else
      args.state.ball.velocity.y = ynew - GRAVITY * 0.01                        
    end
    args.state.ball.center.x+= args.state.ball.velocity.x                       
    args.state.ball.center.y+= args.state.ball.velocity.y
  end
def collide args normalOfRCCollision = [ { x : @center . x , y : @center . y } , { x : args . state . ball . center . x , y : args . state . ball . center . y } , ] normalSlope = ( ( normalOfRCCollision [ 1 ] . y - normalOfRCCollision [ 0 ] . y ) / ( normalOfRCCollision [ 1 ] . x - normalOfRCCollision [ 0 ] . x ) ) slope = normalSlope ** - 1.0 * - 1 pointA = { x : args . state . ball . center . x - 1 , y : - ( slope - args . state . ball . center . y ) } pointB = { x : args . state . ball . center . x + 1 , y : slope + args . state . ball . center . y } perpVect = { x : pointB . x - pointA . x , y : pointB . y - pointA . y } mag = ( perpVect . x ** 2 + perpVect . y ** 2 ) ** 0.5 perpVect = { x : perpVect . x / ( mag ) , y : perpVect . y / ( mag ) } perpVect = { x : - perpVect . y , y : perpVect . x } args . state . display_value = perpVect if perpVect . y > 0 perpVect = { x : perpVect . x * - 1 , y : perpVect . y * - 1 } end previousPosition = { x : args . state . ball . center . x - args . state . ball . velocity . x , y : args . state . ball . center . y - args . state . ball . velocity . y } yInterc = pointA . y + - slope * pointA . x if slope == INFINITY if previousPosition . x < pointA . x perpVect = { x : perpVect . x * - 1 , y : perpVect . y * - 1 } yInterc = - INFINITY end elsif previousPosition . y < slope * previousPosition . x + yInterc perpVect = { x : perpVect . x * - 1 , y : perpVect . y * - 1 } end velocityMag = ( args . state . ball . velocity . x ** 2 + args . state . ball . velocity . y ** 2 ) ** 0.5 theta_ball = Math . atan2 ( args . state . ball . velocity . y , args . state . ball . velocity . x ) theta_repel = Math . atan2 ( args . state . ball . center . y , args . state . ball . center . x ) fbx = velocityMag * Math . cos ( theta_ball ) fby = velocityMag * Math . sin ( theta_ball ) repelMag = getRepelMagnitude ( args , fbx , fby , perpVect . x , perpVect . y , ( args . state . ball . velocity . x ** 2 + args . state . ball . velocity . y ** 2 ) ** 0.5 ) frx = repelMag * Math . cos ( theta_repel ) fry = repelMag * Math . sin ( theta_repel ) fsumx = fbx + frx fsumy = fby + fry fr = velocityMag thetaNew = Math . atan2 ( fsumy , fsumx ) xnew = fr * Math . cos ( thetaNew ) ynew = fr * Math . sin ( thetaNew ) if ( args . state . ball . center . x >= @center . x ) xnew = xnew . abs end args . state . ball . velocity . x = xnew if args . state . ball . center . y > @center . y args . state . ball . velocity . y = ynew + GRAVITY * 0.01 else args . state . ball . velocity . y = ynew - GRAVITY * 0.01 end args . state . ball . center . x += args . state . ball . velocity . x args . state . ball . center . y += args . state . ball . velocity . y end
this sets the new velocity of the ball once it has collided with this peg
this sets the new velocity of the ball once it has collided with this peg
#this is the normal of the collision in COMPONENT FORM #see https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.mathscard.co.uk%2Fonline%2Fcircle-coordinate-geometry%2F&psig=AOvVaw2GcD-e2-nJR_IUKpw3hO98&ust=1605731315521000&source=images&cd=vfe&ved=0CAIQjRxqFwoTCMjBo7e1iu0CFQAAAAAdAAAAABAD #normalSlope is the slope of normalOfRCCollision # slope is the slope of the tangent # args.state.display_value = slope # pointA and pointB are using the var slope to tangent in COMPONENT FORM # perpVect is to be VECTOR of the perpendicular tangent # find the magniude of the perpVect # divide the perpVect by the magniude to make it a unit vector # swap the x and y and multiply by -1 to make the vector perpendicular #ensure perpVect points upward # calculate an ESTIMATE of the previousPosition of the ball # the perpVect presently either points in the correct dirrection or it is 180 degrees off we need to correct this # check if ball is bellow or above the collider to determine if perpVect is - or + # the current velocity magnitude of the ball #the angle of the ball's velocity #the angle of the repelling force(perpVect) #the x component of the ball's velocity #the y component of the ball's velocity # the magniude of the collision vector #the x component of the repel's velocity | magnitude is set to twice of fbx #the y component of the repel's velocity | magnitude is set to twice of fby # sum of x forces # sum of y forces # fr is the resulting magnitude # thetaNew is the resulting angle # resulting x velocity # resulting y velocity # this is necessary for the ball colliding on the right side of the peg # set the x-velocity to the new velocity # if the ball is above the middle of the peg we need to temporarily ignore some of the gravity # if the ball is bellow the middle of the peg we need to temporarily increase the power of the gravity # update the position of the ball so it never looks like the ball is intersecting the circle
args