[Test] public void CopyRemoveShapes() { // Create two bodies GameObject objA = new GameObject("ObjectA"); GameObject objB = new GameObject("ObjectB", objA); objA.AddComponent <Transform>(); objB.AddComponent <Transform>(); RigidBody bodyA = objA.AddComponent <RigidBody>(); RigidBody bodyB = objB.AddComponent <RigidBody>(); // Add a shape to the second one bodyB.AddShape(new CircleShapeInfo(128, Vector2.Zero, 1.0f)); // Is the first body empty and the second isn't? Assert.IsTrue(bodyA.Shapes == null || !bodyA.Shapes.Any()); Assert.IsFalse(bodyB.Shapes == null || !bodyB.Shapes.Any()); // Copy the first over to the second bodyA.CopyTo(bodyB); // Are they both empty now? Assert.IsTrue(bodyA.Shapes == null || !bodyA.Shapes.Any()); Assert.IsTrue(bodyB.Shapes == null || !bodyB.Shapes.Any()); }
[Test] public void CopyModifyShapes() { int radiusA = MathF.Rnd.Next(); int radiusB = MathF.Rnd.Next(); // Create two bodies GameObject objA = new GameObject("ObjectA"); GameObject objB = new GameObject("ObjectB", objA); objA.AddComponent <Transform>(); objB.AddComponent <Transform>(); RigidBody bodyA = objA.AddComponent <RigidBody>(); RigidBody bodyB = objB.AddComponent <RigidBody>(); // Add a similar shape to both bodyA.AddShape(new CircleShapeInfo(radiusA, Vector2.Zero, 1.0f)); bodyB.AddShape(new CircleShapeInfo(radiusB, Vector2.Zero, 1.0f)); // Check if each body carries its designated shape Assert.IsTrue(bodyA.Shapes != null && (bodyA.Shapes.First() as CircleShapeInfo).Radius == radiusA); Assert.IsTrue(bodyB.Shapes != null && (bodyB.Shapes.First() as CircleShapeInfo).Radius == radiusB); // Copy the first over to the second bodyA.CopyTo(bodyB); // Are they both equal now? Assert.AreNotSame(bodyA.Shapes, bodyB.Shapes); Assert.AreNotSame(bodyA.Shapes.First(), bodyB.Shapes.First()); Assert.IsTrue(bodyA.Shapes != null && (bodyA.Shapes.First() as CircleShapeInfo).Radius == radiusA); Assert.IsTrue(bodyB.Shapes != null && (bodyB.Shapes.First() as CircleShapeInfo).Radius == radiusA); }
void ICmpInitializable.OnInit(Component.InitContext context) { if (context == InitContext.Activate) { this.RetrieveSourceTilemaps(); this.UpdateRigidBody(true); this.SubscribeSourceEvents(); } else if (context == InitContext.Saved) { // Since we're removing all generated bodies in the saving process, // we'll have to add them back now. Note that we don't actually // re-generate them. RigidBody body = this.GameObj.GetComponent <RigidBody>(); for (int y = 0; y < this.sectorCount.Y; y++) { for (int x = 0; x < this.sectorCount.X; x++) { Sector sector = this.sectors[x, y]; if (sector.Shapes != null) { foreach (ShapeInfo shape in sector.Shapes) { body.AddShape(shape); } } this.sectors[x, y] = sector; } } } }
[Test] public void CopyReplaceShapes() { int radius = MathF.Rnd.Next(); // Create two bodies GameObject objA = new GameObject("ObjectA"); GameObject objB = new GameObject("ObjectB", objA); objA.AddComponent <Transform>(); objB.AddComponent <Transform>(); RigidBody bodyA = objA.AddComponent <RigidBody>(); RigidBody bodyB = objB.AddComponent <RigidBody>(); // Add a different kind of shape to both bodyA.AddShape(new CircleShapeInfo(radius, Vector2.Zero, 1.0f)); bodyB.AddShape(new PolyShapeInfo(new Vector2[] { Vector2.Zero, Vector2.UnitX, Vector2.UnitY }, 1.0f)); // Check if each body carries its designated shape Assert.IsNotNull(bodyA.Shapes); Assert.IsNotNull(bodyA.Shapes.First() as CircleShapeInfo); Assert.IsNotNull(bodyB.Shapes); Assert.IsNotNull(bodyB.Shapes.First() as PolyShapeInfo); // Copy the first over to the second bodyA.CopyTo(bodyB); // Are they both equal now? Assert.AreNotSame(bodyA.Shapes, bodyB.Shapes); Assert.AreNotSame(bodyA.Shapes.First(), bodyB.Shapes.First()); Assert.IsTrue(bodyA.Shapes != null && (bodyA.Shapes.First() as CircleShapeInfo).Radius == radius); Assert.IsTrue(bodyB.Shapes != null && (bodyB.Shapes.First() as CircleShapeInfo).Radius == radius); }
public Bullet CreateBullet() { GameObject obj = new GameObject("Bullet"); Transform transform = obj.AddComponent <Transform>(); RigidBody body = obj.AddComponent <RigidBody>(); SpriteRenderer sprite = obj.AddComponent <SpriteRenderer>(); Bullet bullet = obj.AddComponent <Bullet>(); Material spriteMaterial = this.spriteMaterial.Res ?? Material.SolidWhite.Res; Vector2 spriteSize = spriteMaterial.MainTexture.IsAvailable ? spriteMaterial.MainTexture.Res.Size : new Vector2(5, 5); float spriteRadius = MathF.Max(spriteSize.X, spriteSize.Y) * 0.25f; body.ClearShapes(); CircleShapeInfo circleShape = new CircleShapeInfo(spriteRadius, Vector2.Zero, 1.0f); circleShape.IsSensor = true; body.AddShape(circleShape); body.CollisionCategory = CollisionCategory.Cat3; body.CollidesWith &= ~CollisionCategory.Cat3; sprite.SharedMaterial = this.spriteMaterial; sprite.Rect = Rect.Align(Alignment.Center, 0.0f, 0.0f, spriteSize.X * 0.5f, spriteSize.Y * 0.5f); bullet.InitFrom(this); return(bullet); }
[Test] public void CloneShapeRigidBodies() { // Create a body with a simple shape GameObject source = new GameObject("ObjectA"); source.AddComponent <Transform>(); RigidBody sourceBody = source.AddComponent <RigidBody>(); CircleShapeInfo sourceShape = new CircleShapeInfo(32.0f, Vector2.Zero, 1.0f); sourceBody.AddShape(sourceShape); // Clone the object hierarchy GameObject target = source.DeepClone(); RigidBody targetBody = target.GetComponent <RigidBody>(); CircleShapeInfo targetShape = targetBody.Shapes.FirstOrDefault() as CircleShapeInfo; // Is the cloned shape set up like the source shape? Assert.AreEqual(1, targetBody.Shapes.Count()); Assert.AreSame(targetShape.Parent, targetBody); Assert.AreSame(sourceShape.Parent, sourceBody); Assert.AreNotSame(targetShape.Parent, sourceBody); Assert.AreNotSame(sourceShape.Parent, targetBody); // Clone only the source shape, but not any body CircleShapeInfo isolatedSourceShape = sourceShape; CircleShapeInfo isolatedTargetShape = isolatedSourceShape.DeepClone(); // Is the cloned joint still isolated, and not attached to any body? Assert.IsNotNull(isolatedSourceShape.Parent); Assert.IsNull(isolatedTargetShape.Parent); Assert.AreEqual(1, sourceBody.Shapes.Count()); }
/// <summary> /// This test will determine whether a <see cref="Scene"/> can be activated, updated and deactivated /// in isolation from the global <see cref="Scene.Current"/> setting. /// </summary> [Test] public void IsolatedSimulation() { // Create an isolated new test scene with a ball and a platform Scene scene = new Scene(); GameObject ball = new GameObject("Ball"); Transform ballTransform = ball.AddComponent <Transform>(); RigidBody ballBody = ball.AddComponent <RigidBody>(); ballBody.AddShape(new CircleShapeInfo(32.0f, new Vector2(0.0f, 0.0f), 1.0f)); ball.AddComponent <RigidBodyRenderer>(); scene.AddObject(ball); GameObject platform = new GameObject("Platform"); Transform platformTransform = platform.AddComponent <Transform>(); platformTransform.Pos = new Vector3(0.0f, 128.0f, 0.0f); RigidBody platformBody = platform.AddComponent <RigidBody>(); platformBody.AddShape(new ChainShapeInfo(new[] { new Vector2(-128.0f, 0.0f), new Vector2(128.0f, 0.0f) })); platformBody.BodyType = BodyType.Static; platform.AddComponent <RigidBodyRenderer>(); scene.AddObject(platform); // Do a single, fixed-step Duality update in order to set up // Time.DeltaTime in a predictable way. DualityApp.Update(true); // Assert that the isolated scene remains unaffected Assert.AreEqual(new Vector3(0.0f, 0.0f, 0.0f), ballTransform.Pos); Assert.AreEqual(new Vector3(0.0f, 128.0f, 0.0f), platformTransform.Pos); // Activate the scene to prepare for simulation scene.Activate(); // Run the simulation for a few fixed-step frames for (int i = 0; i < 100; i++) { scene.Update(); } // Deactivate the scene again scene.Deactivate(); // Assert that the balls position is within expected values Assert.IsTrue(ballTransform.Pos.Y > 96.0f); Assert.IsTrue(ballTransform.Pos.Y < 128.0f); Assert.IsTrue(Math.Abs(ballTransform.Pos.X) < 1.00f); Assert.IsTrue(Math.Abs(ballTransform.Pos.Z) < 1.00f); }
[Test] public void FallingBallOnPlatform() { Scene scene = new Scene(); Scene.SwitchTo(scene); // Create the ball GameObject ball = new GameObject("Ball"); Transform ballTransform = ball.AddComponent <Transform>(); RigidBody ballBody = ball.AddComponent <RigidBody>(); ballBody.Restitution = 0f; CollisionEventReceiver listener = ball.AddComponent <CollisionEventReceiver>(); ballBody.AddShape(new CircleShapeInfo(1, new Vector2(0, 0), 1)); scene.AddObject(ball); // Create the platform GameObject platform = new GameObject("Platform"); Transform platformTrans = platform.AddComponent <Transform>(); platformTrans.Pos = new Vector3(0, 5, 0); RigidBody platformBody = platform.AddComponent <RigidBody>(); platformBody.Restitution = 0f; platformBody.AddShape(new ChainShapeInfo(new[] { new Vector2(-1, 0), new Vector2(1, 0), })); platformBody.BodyType = BodyType.Static; scene.AddObject(platform); // Simulate some update steps for (int i = 0; i < 10; i++) { DualityApp.Update(true); } // Check if the position is within expected values Assert.IsTrue(ballTransform.Pos.Y > 3f); Assert.IsTrue(ballTransform.Pos.Y < 5f); Assert.IsTrue(Math.Abs(ballTransform.Pos.X) < 0.01f); Assert.IsTrue(Math.Abs(ballTransform.Pos.Z) < 0.01f); // Check if the collision events were triggered // First one should always be a begin Assert.IsTrue(listener.Collisions[0].Type == CollisionEventReceiver.CollisionType.Begin); // The ones after that should all be of type Solve. There should be no event of type End since there is no bouncing. Assert.IsTrue(listener.Collisions.Skip(1).All(x => x.Type == CollisionEventReceiver.CollisionType.Solve)); }
void ICmpSerializeListener.OnSaved() { // Since we're removing all generated bodies in the saving process, // we'll have to add them back now. Note that we don't actually // re-generate them. RigidBody body = this.GameObj.GetComponent <RigidBody>(); for (int y = 0; y < this.sectorCount.Y; y++) { for (int x = 0; x < this.sectorCount.X; x++) { Sector sector = this.sectors[x, y]; if (sector.Shapes != null) { foreach (ShapeInfo shape in sector.Shapes) { body.AddShape(shape); } } this.sectors[x, y] = sector; } } }
private void UpdateRigidBody(RigidBody body, int sectorX, int sectorY) { Sector sector = this.sectors[sectorX, sectorY]; // Determine collision checksum this.tempCollisionData.Clear(); int newChecksum = this.MergeCollisionData(sectorX, sectorY, this.tempCollisionData); // If it differs from our previous value, update collision shapes if (sector.Checksum != newChecksum) { // Clean up old shapes if (sector.Shapes != null) { foreach (ShapeInfo shape in sector.Shapes) { body.RemoveShape(shape); } sector.Shapes.Clear(); } else { sector.Shapes = new List <ShapeInfo>(); } // Generate new shapes { // Determine general working data Tilemap tilemap = this.referenceTilemap; Tileset tileset = tilemap != null ? tilemap.Tileset.Res : null; Vector2 tileSize = tileset != null ? tileset.TileSize : Tileset.DefaultTileSize; Point2 sectorBaseTile = new Point2( sectorX * SectorSize, sectorY * SectorSize); Vector2 sectorBasePos = sectorBaseTile * tileSize; // Clear the temporary edge map first this.tempEdgeMap.Clear(); // Populate the edge map with fence and block geometry AddFenceCollisionEdges(this.tempCollisionData, this.tempEdgeMap); AddBlockCollisionEdges(this.tempCollisionData, this.tempEdgeMap, sectorBaseTile, this.tileCount); if (this.solidOuterEdges) { AddBorderCollisionEdges(this.tempEdgeMap, sectorBaseTile, this.tileCount); } // Now traverse the edge map and gradually create chain / loop // shapes until all edges have been used. Rect localRect = Rect.Align(this.origin, 0, 0, this.tileCount.X * tileSize.X, this.tileCount.Y * tileSize.Y); GenerateCollisionShapes(this.tempEdgeMap, localRect.TopLeft + sectorBasePos, tileSize, this.roundedCorners, sector.Shapes); // Add all the generated shapes to the target body foreach (ShapeInfo shape in sector.Shapes) { body.AddShape(shape); shape.Friction = this.shapeFriction; shape.Restitution = this.shapeRestitution; } } sector.Checksum = newChecksum; } this.sectors[sectorX, sectorY] = sector; }
private GameObject CreateNote(byte ID) { GameObject x = new GameObject("Note" + ID.ToString()); RigidBody hitbox; hitbox = new RigidBody(); CircleShapeInfo collision = new CircleShapeInfo(524.5f, new Vector2(0, 0), 1); collision.IsSensor = true; hitbox.AddShape(collision); hitbox.IgnoreGravity = true; x.AddComponent(hitbox); SpriteRenderer sprite; sprite = new SpriteRenderer(new Rect(-498.5f, -498.5f, 997, 977), ContentProvider.RequestContent <Duality.Resources.Material>("Data\\Ghost_Arrow.Material.res")); x.AddComponent(sprite); x.AddComponent(new GhostArrow()); Transform transform = new Transform(); int xpos = 0; int xpos2 = 0; float angle2 = 0; switch (ID) { case 8: xpos = -858; break; case 2: xpos = -558; transform.Angle = (float)(Math.PI); break; case 4: xpos = -1158; transform.Angle = (float)((3 * Math.PI) / 2); break; case 6: transform.Angle = (float)(Math.PI / 2); xpos = -258; break; case 7: angle2 = (float)((3 * Math.PI) / 2); xpos = -858; xpos2 = -1158; break; case 9: angle2 = (float)(Math.PI / 2); xpos = -858; xpos2 = -258; break; case 1: transform.Angle = (float)(Math.PI); angle2 = (float)((3 * Math.PI) / 2); xpos = -558; xpos2 = -1158; break; case 3: transform.Angle = (float)(Math.PI); angle2 = (float)(Math.PI / 2); xpos = -558; xpos2 = -258; break; case 5: angle2 = (float)(Math.PI); xpos = -858; xpos2 = -558; break; case 0: transform.Angle = (float)((3 * Math.PI) / 2); angle2 = (float)(Math.PI / 2); xpos = -1158; xpos2 = -258; break; default: return(null); } transform.Pos = new Vector3(xpos, -1300, 1); transform.Scale = .2f; x.AddComponent(transform); if (ID == 7 || ID == 9 || ID == 1 || ID == 3 || ID == 5 || ID == 0) { GameObject y = new GameObject("Note" + ID.ToString()); x.CopyTo(y); //Transform transform2 = new Transform(); y.Transform.Pos = new Vector3(xpos2, -1300, 1); y.Transform.Angle = angle2; GameObject z = x; x = new GameObject("The double"); z.Parent = x; y.Parent = x; x.AddComponent(new DoubleManager()); } return(x); }