public void LoosenRope(Rope rope) { if (rope.PhysicsSegments.Count * Rope.SegmentLength >= Rope.MaxLength) { // Maximum length reached, rope cannot be made any longer return; } var lastSegment = rope.PhysicsSegments.Last(); var ropeSegmentVector = Vector2.Normalize(rope.AttachedEntity.Position - lastSegment.Position) * Rope.SegmentLength; PhysicsWorld.RemoveJoint(rope.PhysicsEntityJoint); //var newSegment = BodyFactory.CreateCircle(PhysicsWorld, Rope.SegmentWidth, Rope.SegmentDensity);// BodyFactory.CreateRectangle(PhysicsWorld, 0.05f, Rope.SegmentLength, 0.5f); var newSegment = BodyFactory.CreateRectangle(PhysicsWorld, Rope.Diameter, Rope.SegmentLength, Rope.SegmentDensity); newSegment.BodyType = BodyType.Dynamic; newSegment.AngularDamping = 0.1f; newSegment.LinearDamping = 0.1f; newSegment.Friction = 0.5f; newSegment.Restitution = 0.2f; newSegment.CollisionCategories = Category.Cat3; newSegment.Position = lastSegment.Position + ropeSegmentVector; rope.PhysicsSegments.Add(newSegment); var segmentJoint = JointFactory.CreateRevoluteJoint(PhysicsWorld, lastSegment, newSegment, new Vector2(0, Rope.SegmentLength / 2), new Vector2(0, -Rope.SegmentLength / 2)); segmentJoint.CollideConnected = false; rope.PhysicsSegmentJoints.Add(segmentJoint); var ballJoint = JointFactory.CreateRevoluteJoint(PhysicsWorld, rope.PhysicsSegments.Last(), rope.AttachedEntity.PhysicsBody, Vector2.Zero, Vector2.Zero); ballJoint.CollideConnected = false; rope.PhysicsEntityJoint = ballJoint; }
public void ShortenRope(Rope rope) { if (rope.PhysicsSegments.Count <= 2) { // Rope cannot be any shorter as 2 segments is minimum return; } // Only allow shortening rope if all joints are restful for (int i = 0; i < rope.PhysicsSegmentJoints.Count; ++i) { var joint = rope.PhysicsSegmentJoints[i]; if (Vector2.Distance(joint.WorldAnchorA, joint.WorldAnchorB) > 0.3f * Rope.SegmentLength) return; } PhysicsWorld.RemoveJoint(rope.PhysicsEntityJoint); PhysicsWorld.RemoveJoint(rope.PhysicsSegmentJoints.Last()); rope.PhysicsSegmentJoints.Remove(rope.PhysicsSegmentJoints.Last()); RemoveBody(rope.PhysicsSegments.Last()); rope.PhysicsSegments.Remove(rope.PhysicsSegments.Last()); var ballJoint = JointFactory.CreateRevoluteJoint(PhysicsWorld, rope.PhysicsSegments.Last(), rope.AttachedEntity.PhysicsBody, Vector2.Zero, Vector2.Zero); ballJoint.CollideConnected = false; rope.PhysicsEntityJoint = ballJoint; }
public void RemoveRope(Rope rope) { foreach (var joint in rope.PhysicsSegmentJoints) { PhysicsWorld.RemoveJoint(joint); } rope.PhysicsSegmentJoints.Clear(); foreach (var body in rope.PhysicsSegments) { RopesByPhysicsBody.Remove(body); RemoveBody(body); } rope.PhysicsSegments.Clear(); if (rope.AttachedEntity is Ball) { (rope.AttachedEntity as Ball).PhysicsBody.Mass = 10f; (rope.AttachedEntity as Ball).PhysicsBody.FixedRotation = true; } }
public void AddRope(Rope rope) { float ropeLength = (rope.AttachedEntity.Position - rope.AttachedPosition).Length(); int segmentCount = (int)Round(1 + (ropeLength / Rope.SegmentLength)); if (segmentCount < 2) segmentCount = 2; var ropeSegmentDir = Vector2.Normalize(rope.AttachedEntity.Position - rope.AttachedPosition); // TODO: fix the RotationFromDirection function! var ropeRotation = ropeSegmentDir.RotationFromDirection(); rope.PhysicsSegments.Clear(); for (int i = 0; i < segmentCount; i++) { var ropeSegmentLength = i > 0 ? Rope.SegmentLength : Rope.Diameter; var ropeSegmentVector = ropeSegmentDir * ropeSegmentLength; var segmentStart = rope.AttachedPosition + ropeSegmentVector * i; var segmentCenter = rope.AttachedPosition + ropeSegmentVector * (i + 0.5f); var boxWidth = Rope.Diameter; var boxHeight = i > 0 ? Rope.SegmentLength : Rope.Diameter; //var segment = BodyFactory.CreateCircle(PhysicsWorld, Rope.JointRadius, Rope.SegmentDensity);// BodyFactory.CreateRectangle(PhysicsWorld, 0.05f, Rope.SegmentLength, 0.5f); var segment = BodyFactory.CreateRectangle(PhysicsWorld, boxWidth, boxHeight, Rope.SegmentDensity); segment.BodyType = BodyType.Dynamic; segment.Friction = 0.5f; segment.Restitution = 0.2f; segment.AngularDamping = 0.2f;//1.1f; segment.LinearDamping = 0.2f;// 1.1f; segment.CollisionCategories = Category.Cat3; segment.SetTransform(segmentCenter, -ropeRotation - 0.5f * (float)Math.PI); rope.PhysicsSegments.Add(segment); if (i > 0) { var segmentJoint = JointFactory.CreateRevoluteJoint(PhysicsWorld, rope.PhysicsSegments[i - 1], segment, new Vector2(0, i == 1 ? Rope.Diameter / 2 : Rope.SegmentLength / 2), new Vector2(0, -Rope.SegmentLength / 2)); segmentJoint.CollideConnected = false; rope.PhysicsSegmentJoints.Add(segmentJoint); } else { segment.BodyType = BodyType.Static; } } //var ballAnchor = rope.AttachedEntity.Position + new Vector2(0, rope.AttachedEntity.Radius + 1f); var ballJoint = JointFactory.CreateRevoluteJoint(PhysicsWorld, rope.PhysicsSegments.Last(), rope.AttachedEntity.PhysicsBody, new Vector2(0, Rope.SegmentLength / 2), Vector2.Zero); ballJoint.CollideConnected = false; rope.PhysicsEntityJoint = ballJoint; rope.AttachedEntity.PhysicsBody.FixedRotation = false; //rope.AttachedEntity.PhysicsBody.Mass = 2f; }
public void DrawRope(Rope rope) { bool first = true; foreach(var segment in rope.PhysicsSegments) { //DrawSphere(segment.Position, segment.Rotation, Rope.JointRadius, true); DrawRectangle(segment.Position, Rope.Diameter, first ? Rope.Diameter : Rope.SegmentLength, segment.Rotation, true); first = false; } }
public void DrawRope(Rope rope) { //var segmentPositions = (from s in rope.PhysicsSegments select s.Position).ToArray(); //var segmentPositions = (from s in rope.PhysicsSegments select s.GetWorldPoint(new Vector2(0, 0.5f))).ToArray(); var segmentPositionsList = (from s in rope.PhysicsSegmentJoints select s.WorldAnchorA).ToList(); segmentPositionsList.Insert(0, rope.AttachedPosition); segmentPositionsList.Add(rope.AttachedEntity.Position); var segmentPositions = segmentPositionsList.ToArray(); var triangleCount = (segmentPositions.Length - 1) * 2; VertexPositionColorTexture[] vpc = new VertexPositionColorTexture[triangleCount * 3]; float u = 0; for(int i = 0; i < segmentPositions.Length - 1; i++) { var p0 = segmentPositions[i + 1]; var p1 = segmentPositions[i]; var d = Vector2.Normalize(p1 - p0); var n = new Vector2(d.Y, -d.X); var u0 = u - d.Length() * 0.05f; var u1 = u + (p1 - p0).Length() + d.Length() * 0.05f; p0 -= d * 0.05f; p1 += d * 0.05f; var t00 = p0 + n * RopeWidth; var t10 = p1 + n * RopeWidth; var t01 = p0 - n * RopeWidth; var t11 = p1 - n * RopeWidth; vpc[i * 6 + 0].Color = Color.White; vpc[i * 6 + 0].Position = new Vector3(t11, -1); vpc[i * 6 + 0].TextureCoordinate = new Vector2(1, u1 / (2f * RopeWidth)); vpc[i * 6 + 1].Color = Color.White; vpc[i * 6 + 1].Position = new Vector3(t10, -1); vpc[i * 6 + 1].TextureCoordinate = new Vector2(0, u1 / (2f * RopeWidth)); vpc[i * 6 + 2].Color = Color.White; vpc[i * 6 + 2].Position = new Vector3(t00, -1); vpc[i * 6 + 2].TextureCoordinate = new Vector2(0, u0 / (2f * RopeWidth)); vpc[i * 6 + 3].Color = Color.White; vpc[i * 6 + 3].Position = new Vector3(t01, -1); vpc[i * 6 + 3].TextureCoordinate = new Vector2(1, u0 / (2f * RopeWidth)); vpc[i * 6 + 4].Color = Color.White; vpc[i * 6 + 4].Position = new Vector3(t11, -1); vpc[i * 6 + 4].TextureCoordinate = new Vector2(1, u1 / (2f * RopeWidth)); vpc[i * 6 + 5].Color = Color.White; vpc[i * 6 + 5].Position = new Vector3(t00, -1); vpc[i * 6 + 5].TextureCoordinate = new Vector2(0, u0 / (2f * RopeWidth)); u = u1; } RopeEffect.World = Matrix.Identity; RopeEffect.View = Game.Camera.View; RopeEffect.Projection = Game.Camera.Projection; RopeEffect.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.SamplerStates[0] = new SamplerState { AddressU = TextureAddressMode.Wrap, AddressV = TextureAddressMode.Wrap }; GraphicsDevice.DrawUserPrimitives<VertexPositionColorTexture>(PrimitiveType.TriangleList, vpc, 0, triangleCount); }