@Override public Location<T> calculateSlotLocation (Location<T> outLocation, int slotNumber) { if (numberOfSlots > 1) { // Place the slot around the circle based on its slot number float angleAroundCircle = (MathUtils.PI2 * slotNumber) / numberOfSlots; // The radius depends on the radius of the member, // and the number of members in the circle: // we want there to be no gap between member's shoulders. float radius = memberRadius / (float)Math.sin(Math.PI / numberOfSlots); // Fill location components based on the angle around circle. outLocation.angleToVector(outLocation.getPosition(), angleAroundCircle).scl(radius); // The members should be facing out outLocation.setOrientation(angleAroundCircle); } else { outLocation.getPosition().setZero(); outLocation.setOrientation(MathUtils.PI2 * slotNumber); } // Return the slot location return outLocation; }
/** Calculates the drift offset when members are in the given set of slots for the specified pattern. * @param centerOfMass the output location set to the calculated drift offset * @param slotAssignments the set of slots * @param pattern the pattern * @return the given location for chaining. */ public Location<T> calculateDriftOffset (Location<T> centerOfMass, Array<SlotAssignment<T>> slotAssignments, FormationPattern<T> pattern) { // Clear the center of mass centerOfMass.getPosition().setZero(); float centerOfMassOrientation = 0; // Make sure tempLocation is instantiated if (tempLocation == null) tempLocation = centerOfMass.newLocation(); T centerOfMassPos = centerOfMass.getPosition(); T tempLocationPos = tempLocation.getPosition(); // Go through each assignment and add its contribution to the center float numberOfAssignments = slotAssignments.size; for (int i = 0; i < numberOfAssignments; i++) { pattern.calculateSlotLocation(tempLocation, slotAssignments.get(i).slotNumber); centerOfMassPos.add(tempLocationPos); centerOfMassOrientation += tempLocation.getOrientation(); } // Divide through to get the drift offset. centerOfMassPos.scl(1f / numberOfAssignments); centerOfMassOrientation /= numberOfAssignments; centerOfMass.setOrientation(centerOfMassOrientation); return centerOfMass; }
/** Creates a {@code Formation} for the specified {@code pattern}, {@code slotAssignmentStrategy} and {@code moderator}. * @param anchor the anchor point of this formation, usually a {@link Steerable}. Cannot be {@code null}. * @param pattern the pattern of this formation * @param slotAssignmentStrategy the strategy used to assign a member to his slot * @param motionModerator the motion moderator. Can be {@code null} if moderation is not needed * @throws IllegalArgumentException if the anchor point is {@code null} */ public Formation (Location<T> anchor, FormationPattern<T> pattern, SlotAssignmentStrategy<T> slotAssignmentStrategy, FormationMotionModerator<T> motionModerator) { if (anchor == null) throw new IllegalArgumentException("The anchor point cannot be null"); this.anchor = anchor; this.pattern = pattern; this.slotAssignmentStrategy = slotAssignmentStrategy; this.motionModerator = motionModerator; this.slotAssignments = new Array<SlotAssignment<T>>(); this.driftOffset = anchor.newLocation(); this.positionOffset = anchor.getPosition().cpy(); }
/** Creates a {@code Hide} behavior for the specified owner, target and proximity. * @param owner the owner of this behavior * @param target the target of this behavior * @param proximity the proximity to find nearby obstacles */ public Hide (Steerable<T> owner, Location<T> target, Proximity<T> proximity) { super(owner, target); this.proximity = proximity; this.bestHidingSpot = newVector(owner); this.toObstacle = null; // Set to null since we'll reuse steering.linear for this vector }
@Override public Location<Vector2> calculateSlotLocation(Location<Vector2> outLocation, int slotNumber) { float offset = memberRadius * (numberOfSlots - 1); outLocation.getPosition().set(0, slotNumber * (memberRadius + memberRadius) - offset); outLocation.setOrientation(0); return outLocation; }
@Override public Location<Vector2> calculateSlotLocation( Location<Vector2> outLocation, int slotNumber) { int row = calculateRow(slotNumber); float col = calculateColumn(slotNumber, row); float memberDiameter = memberRadius + memberRadius; outLocation.getPosition().set(-row * memberDiameter, -col * memberDiameter); outLocation.setOrientation(0); return outLocation; }
@Override public Location<Vector2> calculateSlotLocation (Location<Vector2> outLocation, int slotNumber) { int x = slotNumber / columns; int y = slotNumber % columns; float memberDiameter = memberRadius + memberRadius; float offset = memberRadius * (columns - 1); outLocation.getPosition().set(x * memberDiameter - offset, y * memberDiameter - offset); outLocation.setOrientation(0); return outLocation; }
@Override public Location<Vector2> calculateSlotLocation( Location<Vector2> outLocation, int slotNumber) { Vector2 side = ((slotNumber + 1) % 2) == 0 ? side1 : side2; float radius = ((slotNumber + 1) / 2) * (memberRadius + memberRadius); outLocation.getPosition().set(side).scl(radius); outLocation.setOrientation(0); return outLocation; }
@Override public Location<Vector2> newLocation () { return new Scene2dLocation(); }
@Override public Location<Vector2> newLocation () { return new SteerLocation(); }
@Override public Location<Vector2> newLocation() { return null; }
@Override public Location<T> calculateSlotLocation (Location<T> outLocation, int slotNumber) { super.calculateSlotLocation(outLocation, slotNumber); outLocation.setOrientation(outLocation.getOrientation() + MathUtils.PI); return outLocation; }
/** Returns the location of the given slot index. */ public Location<T> calculateSlotLocation (Location<T> outLocation, int slotNumber);
/** Returns the current anchor point of the formation. This can be the location (i.e. position and orientation) of a leader * member, a modified center of mass of the members in the formation, or an invisible but steered anchor point for a two-level * steering system. */ public Location<T> getAnchorPoint () { return anchor; }
/** Sets the anchor point of the formation. * @param anchor the anchor point to set */ public void setAnchorPoint (Location<T> anchor) { this.anchor = anchor; }
/** Returns the target location of this formation member. */ public Location<T> getTargetLocation ();
@Override public Interpose<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Creates a {@code Flee} behavior for the specified owner and target. * @param owner the owner of this behavior * @param target the target agent of this behavior. */ public Flee (Steerable<T> owner, Location<T> target) { super(owner, target); }
@Override public Flee<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Creates a {@code Seek} behavior for the specified owner and target. * @param owner the owner of this behavior * @param target the target agent of this behavior. */ public Seek (Steerable<T> owner, Location<T> target) { super(owner); this.target = target; }
/** Returns the target to seek. */ public Location<T> getTarget () { return target; }
/** Sets the target to seek. * @return this behavior for chaining. */ public Seek<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Creates an {@code Arrive} behavior for the specified owner and target. * @param owner the owner of this behavior * @param target the target of this behavior */ public Arrive (Steerable<T> owner, Location<T> target) { super(owner); this.target = target; }
/** Returns the target to arrive to. */ public Location<T> getTarget () { return target; }
/** Sets the target to arrive to. * @return this behavior for chaining. */ public Arrive<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Creates a {@code Face} behavior for the specified owner and target. * @param owner the owner of this behavior * @param target the target of this behavior. */ public Face (Steerable<T> owner, Location<T> target) { super(owner, target); }
@Override public Face<T> setTarget (Location<T> target) { this.target = target; return this; }
@Override public FollowPath<T, P> setTarget (Location<T> target) { this.target = target; return this; }
/** Sets the target to align to. Notice that this method is inherited from {@link ReachOrientation}, but is completely useless * for {@code LookWhereYouAreGoing} because the target orientation is determined by the velocity of the owner itself. * @return this behavior for chaining. */ @Override public LookWhereYouAreGoing<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Creates a {@code Hide} behavior for the specified owner and target. * @param owner the owner of this behavior * @param target the target of this behavior */ public Hide (Steerable<T> owner, Location<T> target) { this(owner, target, null); }
@Override public Hide<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Creates a {@code ReachOrientation} behavior for the specified owner and target. * @param owner the owner of this behavior * @param target the target. */ public ReachOrientation (Steerable<T> owner, Location<T> target) { super(owner); this.target = target; }
/** Returns the target to align to. */ public Location<T> getTarget () { return target; }
/** Sets the target to align to. * @return this behavior for chaining. */ public ReachOrientation<T> setTarget (Location<T> target) { this.target = target; return this; }
/** Sets the target to align to. Notice that this method is inherited from {@link ReachOrientation}, but is completely useless * for {@code Wander} because owner's orientation is determined by the internal target, which is moving on the wander circle. * @return this behavior for chaining. */ @Override public Wander<T> setTarget (Location<T> target) { this.target = target; return this; }