private boolean checkAirborneTimeAndCalculateVelocity (T outVelocity, float time, JumpDescriptor<T> jumpDescriptor, float maxLinearSpeed) { // Calculate the planar velocity planarVelocity.set(jumpDescriptor.delta).scl(1f / time); gravityComponentHandler.setComponent(planarVelocity, 0f); // Check the planar linear speed if (planarVelocity.len2() < maxLinearSpeed * maxLinearSpeed) { // We have a valid solution, so store it by merging vertical and non-vertical axes float verticalValue = gravityComponentHandler.getComponent(outVelocity); gravityComponentHandler.setComponent(outVelocity.set(planarVelocity), verticalValue); if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "targetLinearVelocity = " + outVelocity + "; targetLinearSpeed = " + outVelocity.len()); return true; } return false; }
protected SteeringAcceleration<T> arrive (SteeringAcceleration<T> steering, T targetPosition) { // Get the direction and distance to the target T toTarget = steering.linear.set(targetPosition).sub(owner.getPosition()); float distance = toTarget.len(); // Check if we are there, return no steering if (distance <= arrivalTolerance) return steering.setZero(); Limiter actualLimiter = getActualLimiter(); // Go max speed float targetSpeed = actualLimiter.getMaxLinearSpeed(); // If we are inside the slow down radius calculate a scaled speed if (distance <= decelerationRadius) targetSpeed *= distance / decelerationRadius; // Target velocity combines speed and direction T targetVelocity = toTarget.scl(targetSpeed / distance); // Optimized code for: toTarget.nor().scl(targetSpeed) // Acceleration tries to get to the target velocity without exceeding max acceleration // Notice that steering.linear and targetVelocity are the same vector targetVelocity.sub(owner.getLinearVelocity()).scl(1f / timeToTarget).limit(actualLimiter.getMaxLinearAcceleration()); // No angular acceleration steering.angular = 0f; // Output the steering return steering; }
@Override public boolean reportNeighbor (Steerable<T> neighbor) { // Calculate the time to collision relativePosition.set(neighbor.getPosition()).sub(owner.getPosition()); relativeVelocity.set(neighbor.getLinearVelocity()).sub(owner.getLinearVelocity()); float relativeSpeed2 = relativeVelocity.len2(); // Collision can't happen when the agents have the same linear velocity. // Also, note that timeToCollision would be NaN due to the indeterminate form 0/0 and, // since any comparison involving NaN returns false, it would become the shortestTime, // so defeating the algorithm. if (relativeSpeed2 == 0) return false; float timeToCollision = -relativePosition.dot(relativeVelocity) / relativeSpeed2; // If timeToCollision is negative, i.e. the owner is already moving away from the the neighbor, // or it's not the most imminent collision then no action needs to be taken. if (timeToCollision <= 0 || timeToCollision >= shortestTime) return false; // Check if it is going to be a collision at all float distance = relativePosition.len(); float minSeparation = distance - (float)Math.sqrt(relativeSpeed2) * timeToCollision /* shortestTime */; if (minSeparation > owner.getBoundingRadius() + neighbor.getBoundingRadius()) return false; // Store most imminent collision data shortestTime = timeToCollision; firstNeighbor = neighbor; firstMinSeparation = minSeparation; firstDistance = distance; firstRelativePosition.set(relativePosition); firstRelativeVelocity.set(relativeVelocity); return true; }
@Override public SteeringAcceleration<T> calculateRealSteering (SteeringAcceleration<T> steering) { // Check if we have a trajectory, and create one if not. if (target == null) { target = calculateTarget(); callback.reportAchievability(isJumpAchievable); } // If the trajectory is zero, return no steering acceleration if (!isJumpAchievable) return steering.setZero(); // Check if the owner has reached target position and velocity with acceptable tolerance if (owner.getPosition().epsilonEquals(target.getPosition(), takeoffPositionTolerance)) { if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "Good position!!!"); if (owner.getLinearVelocity().epsilonEquals(target.getLinearVelocity(), takeoffVelocityTolerance)) { if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "Good Velocity!!!"); isJumpAchievable = false; // Perform the jump, and return no steering (the owner is airborne, no need to steer). callback.takeoff(maxVerticalVelocity, airborneTime); return steering.setZero(); } else { if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "Bad Velocity: Speed diff. = " + planarVelocity.set(target.getLinearVelocity()).sub(owner.getLinearVelocity()).len() + ", diff = (" + planarVelocity + ")"); } } // Delegate to MatchVelocity return super.calculateRealSteering(steering); }
private boolean checkAirborneTimeAndCalculateVelocity (T outVelocity, float time, JumpDescriptor<T> jumpDescriptor, float maxLinearSpeed) { // Calculate the planar velocity planarVelocity.set(jumpDescriptor.delta).scl(1f / time); gravityComponentHandler.setComponent(planarVelocity, 0f); // Check the planar linear speed if (planarVelocity.len2() < maxLinearSpeed * maxLinearSpeed) { // We have a valid solution, so store it by merging vertical and non-vertical axes float verticalValue = gravityComponentHandler.getComponent(outVelocity); gravityComponentHandler.setComponent(outVelocity.set(planarVelocity), verticalValue); if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "targetLinearVelocity = " + outVelocity + "; targetLinearSpeed = " + outVelocity.len()); return true; } return false; }
protected SteeringAcceleration<T> arrive (SteeringAcceleration<T> steering, T targetPosition) { // Get the direction and distance to the target T toTarget = steering.linear.set(targetPosition).sub(owner.getPosition()); float distance = toTarget.len(); // Check if we are there, return no steering if (distance <= arrivalTolerance) return steering.setZero(); Limiter actualLimiter = getActualLimiter(); // Go max speed float targetSpeed = actualLimiter.getMaxLinearSpeed(); // If we are inside the slow down radius calculate a scaled speed if (distance <= decelerationRadius) targetSpeed *= distance / decelerationRadius; // Target velocity combines speed and direction T targetVelocity = toTarget.scl(targetSpeed / distance); // Optimized code for: toTarget.nor().scl(targetSpeed) // Acceleration tries to get to the target velocity without exceeding max acceleration // Notice that steering.linear and targetVelocity are the same vector targetVelocity.sub(owner.getLinearVelocity()).scl(1f / timeToTarget).limit(actualLimiter.getMaxLinearAcceleration()); // No angular acceleration steering.angular = 0f; // Output the steering return steering; }
@Override public boolean reportNeighbor (Steerable<T> neighbor) { // Calculate the time to collision relativePosition.set(neighbor.getPosition()).sub(owner.getPosition()); relativeVelocity.set(neighbor.getLinearVelocity()).sub(owner.getLinearVelocity()); float relativeSpeed2 = relativeVelocity.len2(); // Collision can't happen when the agents have the same linear velocity. // Also, note that timeToCollision would be NaN due to the indeterminate form 0/0 and, // since any comparison involving NaN returns false, it would become the shortestTime, // so defeating the algorithm. if (relativeSpeed2 == 0) return false; float timeToCollision = -relativePosition.dot(relativeVelocity) / relativeSpeed2; // If timeToCollision is negative, i.e. the owner is already moving away from the the neighbor, // or it's not the most imminent collision then no action needs to be taken. if (timeToCollision <= 0 || timeToCollision >= shortestTime) return false; // Check if it is going to be a collision at all float distance = relativePosition.len(); float minSeparation = distance - (float)Math.sqrt(relativeSpeed2) * timeToCollision /* shortestTime */; if (minSeparation > owner.getBoundingRadius() + neighbor.getBoundingRadius()) return false; // Store most imminent collision data shortestTime = timeToCollision; firstNeighbor = neighbor; firstMinSeparation = minSeparation; firstDistance = distance; firstRelativePosition.set(relativePosition); firstRelativeVelocity.set(relativeVelocity); return true; }
@Override public SteeringAcceleration<T> calculateRealSteering (SteeringAcceleration<T> steering) { // Check if we have a trajectory, and create one if not. if (target == null) { target = calculateTarget(); callback.reportAchievability(isJumpAchievable); } // If the trajectory is zero, return no steering acceleration if (!isJumpAchievable) return steering.setZero(); // Check if the owner has reached target position and velocity with acceptable tolerance if (owner.getPosition().epsilonEquals(target.getPosition(), takeoffPositionTolerance)) { if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "Good position!!!"); if (owner.getLinearVelocity().epsilonEquals(target.getLinearVelocity(), takeoffVelocityTolerance)) { if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "Good Velocity!!!"); isJumpAchievable = false; // Perform the jump, and return no steering (the owner is airborne, no need to steer). callback.takeoff(maxVerticalVelocity, airborneTime); return steering.setZero(); } else { if (DEBUG_ENABLED) GdxAI.getLogger().info("Jump", "Bad Velocity: Speed diff. = " + planarVelocity.set(target.getLinearVelocity()).sub(owner.getLinearVelocity()).len() + ", diff = (" + planarVelocity + ")"); } } // Delegate to MatchVelocity return super.calculateRealSteering(steering); }