// ----------------------------- AddNoiseToKick -------------------------------- // // this can be used to vary the accuracy of a player's kick. Just call it // prior to kicking the ball using the ball's position and the ball target as // parameters. // ----------------------------------------------------------------------------- public static Vector2D addNoiseToKick(Vector2D BallPos, Vector2D BallTarget) { double Pi = Utils.Pi; double displacement = (Pi - Pi * Params.Instance().PlayerKickingAccuracy) * RandomClamped(); Vector2D toTarget = BallTarget.minus(BallPos); vec2DRotateAroundOrigin(toTarget, displacement); return toTarget.plus(BallPos); }
// ----------------------- 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()); } }