143 lines
4.9 KiB
Dart
143 lines
4.9 KiB
Dart
part of flutter_sprites;
|
|
|
|
/// A constraint limits or otherwise controls a [Node]'s properties, such as
|
|
/// position or rotation. Add a list of constraints by setting the [Node]'s
|
|
/// constraints property.
|
|
///
|
|
/// Constrains are applied after the update calls are
|
|
/// completed. They can also be applied at any time by calling a [Node]'s
|
|
/// [applyConstraints] method. It's possible to create custom constraints by
|
|
/// overriding this class and implementing the [constrain] method.
|
|
abstract class Constraint {
|
|
/// Called before the node's update method is called. This method can be
|
|
/// overridden to create setup work that needs to happen before the the
|
|
/// node is updated, e.g. to calculate the node's speed.
|
|
void preUpdate(Node node, double dt) {
|
|
}
|
|
|
|
/// Called after update is complete, if the constraint has been added to a
|
|
/// [Node]. Override this method to modify the node's property according to
|
|
/// the constraint.
|
|
void constrain(Node node, double dt);
|
|
}
|
|
|
|
double _dampenRotation(double src, double dst, double dampening) {
|
|
if (dampening == null)
|
|
return dst;
|
|
|
|
double delta = dst - src;
|
|
while (delta > 180.0) delta -= 360;
|
|
while (delta < -180) delta += 360;
|
|
delta *= dampening;
|
|
|
|
return src + delta;
|
|
}
|
|
|
|
/// A [Constraint] that aligns a nodes rotation to its movement.
|
|
class ConstraintRotationToMovement extends Constraint {
|
|
/// Creates a new constraint the aligns a nodes rotation to its movement
|
|
/// vector. A [baseRotation] and [dampening] can optionally be set.
|
|
ConstraintRotationToMovement({this.baseRotation: 0.0, this.dampening});
|
|
|
|
/// The filter factor used when constraining the rotation of the node. Valid
|
|
/// values are in the range 0.0 to 1.0
|
|
final double dampening;
|
|
|
|
/// The base rotation will be added to a the movement vectors rotation.
|
|
final double baseRotation;
|
|
|
|
Point _lastPosition;
|
|
|
|
void preUpdate(Node node, double dt) {
|
|
_lastPosition = node.position;
|
|
}
|
|
|
|
void constrain(Node node, double dt) {
|
|
if (_lastPosition == null) return;
|
|
if (_lastPosition == node.position) return;
|
|
|
|
// Get the target angle
|
|
Offset offset = node.position - _lastPosition;
|
|
double target = degrees(GameMath.atan2(offset.dy, offset.dx)) + baseRotation;
|
|
|
|
node.rotation = _dampenRotation(node.rotation, target, dampening);
|
|
}
|
|
}
|
|
|
|
/// A [Constraint] that rotates a node to point towards another node. The target
|
|
/// node is allowed to have a different parent, but they must be in the same
|
|
/// [SpriteBox].
|
|
class ConstraintRotationToNode extends Constraint {
|
|
/// Creates a new [Constraint] that rotates the node towards the [targetNode].
|
|
/// The [baseRotation] will be added to the nodes rotation, and [dampening]
|
|
/// can be used to ease the rotation.
|
|
ConstraintRotationToNode(this.targetNode, {this.baseRotation: 0.0, this.dampening});
|
|
|
|
/// The node to rotate towards.
|
|
final Node targetNode;
|
|
|
|
/// The base rotation will be added after the target rotation is calculated.
|
|
final double baseRotation;
|
|
|
|
/// The filter factor used when constraining the rotation of the node. Valid
|
|
/// values are in the range 0.0 to 1.0
|
|
final double dampening;
|
|
|
|
void constrain(Node node, double dt) {
|
|
Offset offset;
|
|
|
|
if (targetNode.spriteBox != node.spriteBox) {
|
|
// The target node is in another sprite box or has been removed
|
|
return;
|
|
}
|
|
|
|
if (targetNode.parent == node.parent) {
|
|
offset = targetNode.position - node.position;
|
|
} else {
|
|
offset = node.convertPointToBoxSpace(Point.origin)
|
|
- targetNode.convertPointToBoxSpace(Point.origin);
|
|
}
|
|
|
|
double target = degrees(GameMath.atan2(offset.dy, offset.dx)) + baseRotation;
|
|
|
|
node.rotation = _dampenRotation(node.rotation, target, dampening);
|
|
}
|
|
}
|
|
|
|
/// A [Constraint] that constrains the position of a node to equal the position
|
|
/// of another node, optionally with dampening.
|
|
class ConstraintPositionToNode extends Constraint {
|
|
/// Creates a new [Constraint] that constrains the poistion of a node to be
|
|
/// equal to the position of the [targetNode]. Optionally an [offset] can
|
|
/// be used and also [dampening]. The targetNode doesn't need to have the
|
|
/// same parent, but they need to be added to the same [SpriteBox].
|
|
ConstraintPositionToNode(this.targetNode, {this.dampening, this.offset: Offset.zero});
|
|
|
|
final Node targetNode;
|
|
final Offset offset;
|
|
final double dampening;
|
|
|
|
void constrain(Node node, double dt) {
|
|
Point targetPosition;
|
|
|
|
if (targetNode.spriteBox != node.spriteBox || node.parent == null) {
|
|
// The target node is in another sprite box or has been removed
|
|
return;
|
|
}
|
|
|
|
if (targetNode.parent == node.parent) {
|
|
targetPosition = targetNode.position;
|
|
} else {
|
|
targetPosition = node.parent.convertPointFromNode(Point.origin, targetNode);
|
|
}
|
|
|
|
if (offset != null)
|
|
targetPosition += offset;
|
|
|
|
if (dampening == null)
|
|
node.position = targetPosition;
|
|
else
|
|
node.position = GameMath.filterPoint(node.position, targetPosition, dampening);
|
|
}
|
|
}
|