public override void _Ready() { var size = GetViewportRect().Size; var physics = new VerletWorld(); AddChild(physics); // Attractor var attractor = physics.CreatePoint(size / 2, radius: 24, color: Colors.LightGoldenrod, mass: 1000); physics.AddBehavior(new AttractionBehavior(attractor, strength: 0.01f, radius: size.x)); // Create clusters var cluster1 = new VerletCluster( physics, size / 4, pointCount: 8, diameter: 50 ); var cluster2 = new VerletCluster( physics, size * 0.75f, pointCount: 8, diameter: 50 ); // Hidden link to simulate collisions physics.CreateLink(cluster1.Points[0], cluster2.Points[0], minimalDistance: 50, visible: false); }
public VerletTree(VerletWorld world, Vector2 rootPosition, float angle, float length, int generations) { var pointSize = 10f; var branchSize = 10f; var root = world.CreatePoint(rootPosition, radius: pointSize, color: Colors.LightPink); var rootTop = world.CreatePoint(rootPosition + new Vector2(0, -length), radius: pointSize, color: Colors.LightPink); var rootLink = world.CreateLink(root, rootTop, restingDistance: length, width: branchSize); // Fix tree root rootTop.PinToCurrentPosition(); root.PinToCurrentPosition(); var lastLevel = new List <VerletLink>(); lastLevel.Add(rootLink); for (var i = 0; i < generations; ++i) { var newLevel = new List <VerletLink>(); pointSize *= 0.66f; branchSize *= 0.66f; foreach (var link in lastLevel) { var newLength = (link.B.Position - link.A.Position) * 0.66f; var leftPointTarget = link.B.Position + newLength.Rotated(angle); var rightPointTarget = link.B.Position + newLength.Rotated(-angle); var leftPoint = world.CreatePoint(leftPointTarget, radius: pointSize, color: Colors.LightPink); var rightPoint = world.CreatePoint(rightPointTarget, radius: pointSize, color: Colors.LightPink); var leftLink = world.CreateLink(link.B, leftPoint, restingDistance: newLength.Length(), width: branchSize, tearSensitivityFactor: 2f); var rightLink = world.CreateLink(link.B, rightPoint, restingDistance: newLength.Length(), width: branchSize, tearSensitivityFactor: 2f); newLevel.Add(leftLink); newLevel.Add(rightLink); } lastLevel = newLevel; } }
public VerletClusterGraph(VerletWorld world, Vector2 centerPosition) { void linkClusters(VerletCluster cl1, VerletCluster cl2, float restingDistance, float minimalDistance, float linkStiffness) { for (int i = 0; i < cl1.Points.Count; ++i) { for (int j = 0; j < cl2.Points.Count; ++j) { var a = cl1.Points[i]; var b = cl2.Points[j]; var link = world.CreateLink(a, b); link.RestingDistance = restingDistance; link.MinimalDistance = minimalDistance; link.TearSensitivity = -1; link.Modulate = Colors.LightCyan.WithAlpha(64); link.Stiffness = linkStiffness; } } } const float stiffness = 0.01f; var clusters = new List <VerletCluster>() { new VerletCluster( world, centerPosition + MathUtils.RandVector2(-5, 5, -5, 5), pointCount: 8, diameter: 50, tearSensitivityFactor: -1, stiffness: stiffness ), new VerletCluster( world, centerPosition + MathUtils.RandVector2(-5, 5, -5, 5), pointCount: 12, diameter: 75, tearSensitivityFactor: -1, stiffness: stiffness ), new VerletCluster( world, centerPosition + MathUtils.RandVector2(-5, 5, -5, 5), pointCount: 6, diameter: 25, tearSensitivityFactor: -1, stiffness: stiffness ), new VerletCluster( world, centerPosition + MathUtils.RandVector2(-5, 5, -5, 5), pointCount: 4, diameter: 50, tearSensitivityFactor: -1, stiffness: stiffness ) }; for (int i = 0; i < clusters.Count - 1; ++i) { for (int j = i + 1; j < clusters.Count; ++j) { linkClusters( clusters[i], clusters[j], restingDistance: 200, minimalDistance: 10, linkStiffness: 0.1f ); } } }
public VerletCreature(VerletWorld world, Vector2 centerPosition, float height, float gravityScale = 1, float pointRadius = 10f, bool drawPoints = true, bool drawSupportLinks = false) { const float tearSensitivityFactor = -1; const float stiffness = 0.10f; Color supportLinkColor = Colors.LightCyan.WithAlpha(64); float sep = height / 4; VerletPoint createPoint() { return(world.CreatePoint(centerPosition + MathUtils.RandVector2(-5, 5, -5, 5), gravityScale: gravityScale, radius: pointRadius, visible: drawPoints)); } VerletLink createLink(VerletPoint a, VerletPoint b, float distance) { return(world.CreateLink(a, b, restingDistance: distance, tearSensitivityFactor: tearSensitivityFactor, stiffness: stiffness)); } VerletLink createSupportLink(VerletPoint a, VerletPoint b, float distance) { return(world.CreateLink(a, b, restingDistance: distance, tearSensitivityFactor: -1, stiffness: stiffness, color: supportLinkColor, visible: drawSupportLinks)); } // Head var topLeft = createPoint(); var topMiddle = createPoint(); var topRight = createPoint(); var topLeftSide = createPoint(); var topRightSide = createPoint(); var neckLeft = createPoint(); var neckRight = createPoint(); createLink(topMiddle, topRight, sep); createLink(topRight, topRightSide, sep); createLink(topRightSide, neckRight, sep); createLink(topMiddle, topLeft, sep); createLink(topLeft, topLeftSide, sep); createLink(topLeftSide, neckLeft, sep); createSupportLink(neckLeft, neckRight, sep * 2); // Body var bodyLeftSide = createPoint(); var bodyRightSide = createPoint(); var bottomLeft = createPoint(); var bottomMidLeft = createPoint(); var bottomMiddle = createPoint(); var bottomMidRight = createPoint(); var bottomRight = createPoint(); createLink(bodyRightSide, bottomRight, sep); createLink(bottomRight, bottomMidRight, sep); createLink(bottomMidRight, bottomMiddle, sep); createLink(bodyLeftSide, bottomLeft, sep); createLink(bottomLeft, bottomMidLeft, sep); createLink(bottomMidLeft, bottomMiddle, sep); createSupportLink(bodyLeftSide, bodyRightSide, sep * 3); // Attach createLink(neckLeft, bodyLeftSide, sep); createLink(neckRight, bodyRightSide, sep); createSupportLink(topMiddle, bottomMiddle, height); createSupportLink(topLeftSide, bottomMidRight, height * 1.1f); createSupportLink(topRightSide, bottomMidLeft, height * 1.1f); createSupportLink(topLeft, bottomRight, height * 1.1f); createSupportLink(topRight, bottomLeft, height * 1.1f); }