Пример #1
0
  // -------------------------- Kick ----------------------------------------
  //
  // applys a force to the ball in the direction of heading. Truncates
  // the new velocity to make sure it doesn't exceed the max allowable.
  // ------------------------------------------------------------------------
  public void kick(Vector2D direction, double force) {
    // ensure direction is normalized
    Vector2D d = direction.cloneVec();
    d.Normalize();

    // calculate the acceleration
    Vector2D acceleration = d.multiply(force).divide(mass);

    // update the velocity
    velocity.cloneVec(acceleration);
  }
Пример #2
0
  // ----------------------- TestCollisionWithWalls -------------------------
  //
  public void testCollisionWithWalls(List<Wall2D> walls) {
    // test ball against each wall, find out which is closest
    int idxClosest = -1;

    // println ("Colision " +velocity)
    Vector2D velNormal = Vec2DNormalize(velocity);

    Vector2D intersectionPoint = new Vector2D();
    Vector2D collisionPoint = new Vector2D();

    double distToIntersection = Double.MAX_VALUE;

    // iterate through each wall and calculate if the ball intersects.
    // If it does then store the index into the closest intersecting wall
    for (int w = 0; w < walls.size(); ++w) {
      // assuming a collision if the ball continued on its current heading
      // calculate the point on the ball that would hit the wall. This is
      // simply the wall's normal(inversed) multiplied by the ball's radius
      // and added to the balls center (its position)
      Wall2D wallSegment = walls.get(w);
      Vector2D thisCollisionPoint = getPos().minus(wallSegment.Normal().multiply(getBRadius()));

      // calculate exactly where the collision point will hit the plane
      if (Geometry2DFunctions.whereIsPoint(
              thisCollisionPoint, wallSegment.From(), wallSegment.Normal())
          == Geometry2DFunctions.SpanType.plane_backside) {
        double distToWall =
            distanceToRayPlaneIntersection(
                thisCollisionPoint, wallSegment.Normal(), wallSegment.From(), wallSegment.Normal());

        intersectionPoint = thisCollisionPoint.plus(wallSegment.Normal().multiply(distToWall));

      } else {
        double distToWall =
            distanceToRayPlaneIntersection(
                thisCollisionPoint, velNormal, wallSegment.From(), wallSegment.Normal());

        intersectionPoint = thisCollisionPoint.plus(velNormal.multiply(distToWall));
      }

      // check to make sure the intersection point is actually on the line
      // segment
      boolean OnLineSegment = false;
      Vector2D wallNormal = wallSegment.Normal().multiply(20.0);
      if (LineIntersection2D(
          wallSegment.From(),
          wallSegment.To(),
          thisCollisionPoint.minus(wallNormal),
          thisCollisionPoint.plus(wallNormal))) {

        OnLineSegment = true;
      }

      // Note, there is no test for collision with the end of a line segment
      // now check to see if the collision point is within range of the
      // velocity vector. [work in distance squared to avoid Math.sqrt] and if it
      // is the closest hit found so far.
      // If it is that means the ball will collide with the wall sometime
      // between this time step and the next one.
      double distSq = vec2DDistanceSq(thisCollisionPoint, intersectionPoint);

      if ((distSq <= velocity.LengthSq()) && (distSq < distToIntersection) && OnLineSegment) {
        distToIntersection = distSq;
        idxClosest = w;
        collisionPoint = intersectionPoint;
      }
    } // next wall

    // to prevent having to calculate the exact time of collision we
    // can just check if the velocity is opposite to the wall normal
    // before reflecting it. This prevents the case where there is overshoot
    // and the ball gets reflected back over the line before it has completely
    // reentered the playing area.
    if ((idxClosest >= 0) && velNormal.dot(walls.get(idxClosest).Normal()) < 0) {
      velocity.Reflect(walls.get(idxClosest).Normal());
    }
  }