/** Produces a steering that tries to align the owner to the target orientation. This method is called by subclasses that want * to align to a certain orientation. * @param steering the steering to be calculated. * @param targetOrientation the target orientation you want to align to. * @return the calculated steering for chaining. */ protected SteeringAcceleration<T> reachOrientation (SteeringAcceleration<T> steering, float targetOrientation) { // Get the rotation direction to the target wrapped to the range [-PI, PI] float rotation = ArithmeticUtils.wrapAngleAroundZero(targetOrientation - owner.getOrientation()); // Absolute rotation float rotationSize = rotation < 0f ? -rotation : rotation; // Check if we are there, return no steering if (rotationSize <= alignTolerance) return steering.setZero(); Limiter actualLimiter = getActualLimiter(); // Use maximum rotation float targetRotation = actualLimiter.getMaxAngularSpeed(); // If we are inside the slow down radius, then calculate a scaled rotation if (rotationSize <= decelerationRadius) targetRotation *= rotationSize / decelerationRadius; // The final target rotation combines // speed (already in the variable) and direction targetRotation *= rotation / rotationSize; // Acceleration tries to get to the target rotation steering.angular = (targetRotation - owner.getAngularVelocity()) / timeToTarget; // Check if the absolute acceleration is too great float angularAcceleration = steering.angular < 0f ? -steering.angular : steering.angular; if (angularAcceleration > actualLimiter.getMaxAngularAcceleration()) steering.angular *= actualLimiter.getMaxAngularAcceleration() / angularAcceleration; // No linear acceleration steering.linear.setZero(); // Output the steering return steering; }
@Override public AnimationDesc startAnimation(DogCharacter dog) { AnimationDesc animationDesc = super.startAnimation(dog); if (dog.currentTaskAnimation == getTaskAnimation()) { // Calculate target orientation to make the dog face human targetOrientation = ArithmeticUtils.wrapAngleAroundZero(dog.human.getOrientation() + Constants.PI); } return animationDesc; }
@Override public Status execute () { if (facingHuman) { return Status.SUCCEEDED; } DogCharacter dog = getObject(); updateAnimation(dog); if (dog.currentTaskAnimation == getTaskAnimation()) { // Get current model orientation float currentDogOrientation = dog.getBoneOrientation(DogCharacter.DogArmature.FRONT_SPINE.id); // Calculate the difference between current and target orientation float orientationDiff = ArithmeticUtils.wrapAngleAroundZero(currentDogOrientation - targetOrientation); // Is dog facing human with enough precision? if (MathUtils.isZero(orientationDiff, ORIENTATION_TOLERANCE)) { // Make the task succeed on the next frame facingHuman = true; // Bark GameScreen.screen.sounds.bark.play(); // Finish the animation truncateAnimationCleanly(dog, currentDogOrientation); } } return Status.RUNNING; }
@Override public void processEntity(Entity entity, float deltaTime) { TransformComponent transform = pm.get(entity); VelocityComponent velocity = vm.get(entity); PathComponent path = pathM.get(entity); MinionComponent minionComponent = minionM.get(entity); if (path.nextPoint == null) { velocity.linear.setZero(); velocity.angular = 0; return; } // calc dir and len Vector2 toTarget = temp.set(path.nextPoint).sub(transform.position); float distance = toTarget.len(); // don't go too far! if (distance <= 0.05) { velocity.linear.setZero(); velocity.angular = 0; path.nextPoint = null; return; } float maxSpeed = minionComponent.speed; System.out.println("speed " + maxSpeed); // Target velocity combines speed and direction Vector2 targetVelocity = toTarget.scl(maxSpeed / distance); // Optimized code for: // toTarget.nor().scl(maxSpeed) // Acceleration tries to get to the nextPoint velocity without exceeding max acceleration targetVelocity.sub(velocity.linear).scl(1f / linearAccelerationTime).limit(maxLinearAcceleration); // set it velocity.linear.set(toTarget); // angular // Check for a zero direction, and set to 0 is so if (velocity.linear.isZero(zeroThreshold)) { velocity.angular = 0; return; } // Calculate the orientation based on the velocity of the owner float targetOrientation = VectorUtil.vectorToAngle(velocity.linear); // Get the rotation direction to the nextPoint wrapped to the range [-PI, PI] float rotation = ArithmeticUtils.wrapAngleAroundZero(targetOrientation - (transform.rotation - 90) * MathUtils.degreesToRadians); // Absolute rotation float rotationSize = rotation < 0f ? -rotation : rotation; // Check if we are there, set velocity to 0 and return if so if (rotationSize <= 0.1) { velocity.angular = 0; return; } // Use maximum rotation float targetRotation = maxAngularSpeed; // The final nextPoint rotation combines // speed (already in the variable) and direction targetRotation *= rotation / rotationSize; // Acceleration tries to get to the nextPoint rotation velocity.angular = (targetRotation - velocity.angular) / angularAccelerationTime; // Check if the absolute acceleration is too great float angularAcceleration = velocity.angular < 0f ? -velocity.angular : velocity.angular; if (angularAcceleration > maxAngularAcceleration) { velocity.angular *= maxAngularAcceleration / angularAcceleration; } }