예제 #1
0
        [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());
        }
예제 #2
0
        [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);
        }
예제 #3
0
 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;
             }
         }
     }
 }
예제 #4
0
        [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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        [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());
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        [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));
        }
예제 #9
0
        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;
                }
            }
        }
예제 #10
0
        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;
        }
예제 #11
0
        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);
        }