public override void _IntegrateForces(Physics2DDirectBodyState state) { EmitSignal("_forces_integrated", new object[] { state }); if (jelly == null) { return; } float damping = jelly.damping; float stiffness = jelly.stiffness; Vector2 totalImpulse = Vector2.Zero; foreach (Neighbour n in neighbours) { JellyAtom neighbourAtom = n.jellyAtom; Vector2 posNeighbour = neighbourAtom.GlobalPosition; Vector2 selfPos = state.Transform.origin; float restLength = n.restLength; Vector2 diff = posNeighbour - selfPos; float distanceToNeighbour = diff.Length(); Vector2 diffNormalized = diff / distanceToNeighbour; Vector2 selfVelocity = state.LinearVelocity; Vector2 neighbourVelocity = neighbourAtom.LinearVelocity; float force = (distanceToNeighbour - restLength) * stiffness + (diffNormalized).Dot(neighbourVelocity - selfVelocity) * damping; totalImpulse += force * diff.Normalized() * state.Step; } ApplyCentralImpulse(totalImpulse); }
public Neighbour(JellyAtom jellyAtom, float restLength) { this.jellyAtom = jellyAtom; this.restLength = restLength; }
private async void UpdateRect() { edgeBodies = new Array <JellyAtom>(); if (jellyAtomPacked == null) { return; } Vector2 atomSeparation = new Vector2(atomW > 1 ? rect.Size.x / (atomW - 1) : 0, atomH > 1 ? rect.Size.y / (atomH - 1) : 0); Vector2 origin = rect.Position; foreach (Node n in GetChildren()) { n.QueueFree(); } mapAtoms = new Dictionary <Vector2, JellyAtom>(); for (int j = atomH - 1; j >= 0; j--) { for (int i = atomW - 1; i >= 0; i--) { JellyAtom jellyAtom = (JellyAtom)jellyAtomPacked.Instance(); Vector2 gridPos = new Vector2(i, j); jellyAtom.Position = origin + atomSeparation * gridPos; jellyAtom.jelly = this; jellyAtom.GravityScale = gravityScale; AddChild(jellyAtom); mapAtoms.Add(gridPos, jellyAtom); Vector2[] neighbours = new Vector2[] { new Vector2(i + 1, j), new Vector2(i, j + 1), new Vector2(i + 1, j + 1), new Vector2(i - 1, j + 1) }; if (i == 3 && j == 3) { foreach (Node n in GetTree().GetNodesInGroup("CameraOffset")) { Node2D cameraOffset = (Node2D)n; RemoteTransform2D rt = new RemoteTransform2D(); rt.UpdateRotation = false; rt.UpdateRotation = false; rt.RemotePath = cameraOffset.GetPath(); jellyAtom.AddChild(rt); } } foreach (Vector2 neighbour in neighbours) { JellyAtom neighbourBody; if (!mapAtoms.TryGetValue(neighbour, out neighbourBody)) { continue; } float dist = (neighbourBody.Position - jellyAtom.Position).Length(); neighbourBody.AddNeighbour(new Neighbour(jellyAtom, dist)); jellyAtom.AddNeighbour(new Neighbour(neighbourBody, dist)); } //await ToSignal(GetTree(), "idle_frame"); } } for (int i = 0; i < atomW; i++) { edgeBodies.Add(mapAtoms[new Vector2(i, 0)]); } for (int j = 1; j < atomH; j++) { edgeBodies.Add(mapAtoms[new Vector2(atomW - 1, j)]); } for (int i = atomW - 2; i >= 0; i--) { edgeBodies.Add(mapAtoms[new Vector2(i, atomH - 1)]); } for (int j = atomH - 2; j >= 1; j--) { edgeBodies.Add(mapAtoms[new Vector2(0, j)]); } }