Ejemplo n.º 1
0
        public VehicleCreator(Scene scene, Urho.Resources.ResourceCache cache, ScreenInfoRatio screenInfo, Vector2 initPositionHeight)
        {
            _screenInfo             = screenInfo;
            _vehicleVerticalOffset += initPositionHeight.Y;

            // Load vehicle info
            _vehicleModel = VehicleManager.Instance.SelectedVehicleModel;

            var l = _vehicleModel.BodyPosition.Left;
            var t = _vehicleModel.BodyPosition.Top;
            var r = _vehicleModel.BodyPosition.Right;
            var b = _vehicleModel.BodyPosition.Bottom;

            // Get vehicle texture from coordinates
            var sprite = new Sprite2D {
                Texture   = cache.GetTexture2D("Textures/Garage/vehicles_body.png"),
                Rectangle = new IntRect(l, t, r, b)
            };

            // Create vehicle main body reference
            Node box = scene.CreateChild("Box");

            StaticSprite2D boxSprite = box.CreateComponent <StaticSprite2D>();

            boxSprite.Sprite = sprite;

            _mainBody                = box.CreateComponent <RigidBody2D>();
            _mainBody.BodyType       = BodyType2D.Dynamic;
            _mainBody.LinearDamping  = 0.2f;
            _mainBody.AngularDamping = 0.2f;
            _mainBody.Bullet         = true;
            _mainBody.Mass           = 1.0f;
            //_mainBody.SetMassCenter(new Vector2(-2.1f * _screenInfo.XScreenRatio, -0.1f * _screenInfo.YScreenRatio));

            /****************************************/
            /* Outer body for collision - null mass */
            /****************************************/
            float startVX       = -1.2f + _vehicleModel.BalanceBodyOffset[0];
            float startVY       = -0.55f + _vehicleModel.BalanceBodyOffset[1];
            float driverXOffset = 1.0f + _vehicleModel.BalanceBodyOffset[2];

            VehicleObjectPosition = new Vector3(-0.7f * _screenInfo.XScreenRatio, _vehicleVerticalOffset + _vehicleModel.BalanceBodyOffset[1], 3.0f);
            // MAIN BODY BOUNDS
            CollisionChain2D bodyBounds = box.CreateComponent <CollisionChain2D>();

            bodyBounds.VertexCount = 9;
            bodyBounds.SetVertex(0, new Vector2(startVX, startVY)); // BOTTOM LEFT
            bodyBounds.SetVertex(1, new Vector2(startVX, startVY + 0.1f));
            bodyBounds.SetVertex(2, new Vector2(startVX + driverXOffset, startVY + 0.1f));
            bodyBounds.SetVertex(3, new Vector2(startVX + driverXOffset, startVY + 0.2f));
            bodyBounds.SetVertex(4, new Vector2(startVX + driverXOffset + 0.3f, startVY + 0.2f));
            bodyBounds.SetVertex(5, new Vector2(startVX + driverXOffset + 0.3f, startVY + 0.1f));
            bodyBounds.SetVertex(6, new Vector2(startVX + driverXOffset + 0.8f, startVY + 0.1f));
            bodyBounds.SetVertex(7, new Vector2(startVX + driverXOffset + 0.8f, startVY)); // BOTTOM RIGHT
            bodyBounds.SetVertex(8, new Vector2(startVX, startVY));                        // BOTTOM LEFT
            bodyBounds.Friction    = 1.0f;
            bodyBounds.Restitution = 0.0f;

            // BACK BODY BOUND
            CollisionChain2D backBounds = box.CreateComponent <CollisionChain2D>();

            backBounds.VertexCount = 4;
            backBounds.SetVertex(0, new Vector2(startVX, startVY + 0.1f));
            backBounds.SetVertex(1, new Vector2(startVX, startVY + 0.15f));
            backBounds.SetVertex(2, new Vector2(startVX + 0.02f, startVY + 0.15f));
            backBounds.SetVertex(3, new Vector2(startVX + 0.02f, startVY + 0.1f));
            backBounds.SetVertex(4, new Vector2(startVX, startVY + 0.1f));

            backBounds.Friction    = 1.0f;
            backBounds.Restitution = 0.0f;

            // Main body for constraints and mass
            // Create box shape
            CollisionBox2D shape = box.CreateComponent <CollisionBox2D>();

            // Set size
            shape.Size        = new Vector2(0.32f, 0.32f);
            shape.Density     = 8.0f;  // Set shape density (kilograms per meter squared)
            shape.Friction    = 0.8f;  // Set friction
            shape.Restitution = 0.0f;  // Set restitution (no bounce)

            // Update center of collision body - moves center of mass
            shape.SetCenter(-0.2f, -0.65f);

            // Create a vehicle from a compound of 2 ConstraintWheel2Ds
            var car = box;

            //car.Scale = new Vector3(1.5f * _screenInfo.XScreenRatio, 1.5f * _screenInfo.YScreenRatio, 0.0f);

            // DEFINES POSITION OF SPRITE AND MAIN BODY MASS
            car.Position = new Vector3(0.0f * _screenInfo.XScreenRatio, _vehicleVerticalOffset * _screenInfo.YScreenRatio, 1.0f);

            /*****************/
            /* DEFINE WHEELS */
            /*****************/

            var wheelSprites = new List <Sprite2D>();

            foreach (var w in _vehicleModel.WheelsPosition)
            {
                wheelSprites.Add(new Sprite2D {
                    Texture   = cache.GetTexture2D("Textures/Garage/vehicles_wheels.png"),
                    Rectangle = new IntRect(w.Left, w.Top, w.Right, w.Bottom)
                });
            }
            // Create a ball (will be cloned later)
            Node           ball1WheelNode = scene.CreateChild("Wheel");
            StaticSprite2D ballSprite     = ball1WheelNode.CreateComponent <StaticSprite2D>();

            ballSprite.Sprite    = wheelSprites[0];
            ball1WheelNode.Scale = new Vector3(_vehicleModel.WheelsSize[0], _vehicleModel.WheelsSize[0], 1.0f);

            RigidBody2D ballBody = ball1WheelNode.CreateComponent <RigidBody2D>();

            ballBody.BodyType       = BodyType2D.Dynamic;
            ballBody.LinearDamping  = 0.1f;
            ballBody.AngularDamping = 0.1f;
            ballBody.Bullet         = true;
            ballBody.Mass           = 2.0f;

            // WHEEL COLLISION
            CollisionCircle2D ballShape = ball1WheelNode.CreateComponent <CollisionCircle2D>(); // Create circle shape

            ballShape.Radius      = 0.14f;                                                      // * _vehicleModel.WheelsSize[0]; // Set radius
            ballShape.Density     = 2.0f;                                                       // Set shape density (kilograms per meter squared)
            ballShape.Friction    = (_vehicleModel.Wheel / 2) / 10.0f;                          // Set friction: 1.0 = max friction
            ballShape.Restitution = (20 - _vehicleModel.Suspensions) / 2 / 10.0f;               // Set restitution: make it bounce: 0.0 = no bounce

            // CLONE AND POSITION WHEELS

            for (var i = 0; i < _vehicleModel.WheelsBodyPosition.Count; i++)
            {
                if (i == 0)
                {
                    float x1 = _vehicleModel.WheelsBodyPosition[i].X % _vehicleImgPos;
                    float y1 = _vehicleModel.WheelsBodyPosition[i].Y % _vehicleImgPos;
                    x1 = x1 >= _vehicleImgPos / 2 ? (x1 - _vehicleImgPos / 2) * Application.PixelSize : -(_vehicleImgPos / 2 - x1) * Application.PixelSize;
                    y1 = (_vehicleImgPos / 2 - y1) * Application.PixelSize;

                    // WHEEL POSITION - NEEDS TO BE SET RELATIVE TO MAIN BODY
                    ball1WheelNode.Position = new Vector3(x1, y1 + (_vehicleVerticalOffset - 0.05f) * _screenInfo.YScreenRatio, 1.0f);

                    // SET BACK WHEEL CONSTRAINT COMPONENTS
                    var constraintWheel = car.CreateComponent <ConstraintWheel2D>();
                    constraintWheel.OtherBody      = ball1WheelNode.GetComponent <RigidBody2D>();
                    constraintWheel.Anchor         = ball1WheelNode.Position2D;
                    constraintWheel.Axis           = new Vector2(0.0f, 1.0f);
                    constraintWheel.MaxMotorTorque = 150.0f;
                    constraintWheel.FrequencyHz    = 15.0f;
                    constraintWheel.DampingRatio   = 10.0f;
                    constraintWheel.MotorSpeed     = 0.0f;
                    _wheelsConstraints.Add(constraintWheel);
                }
                else
                {
                    Node           newWheelNode  = ball1WheelNode.Clone(CreateMode.Replicated);
                    StaticSprite2D newBallSprite = newWheelNode.CreateComponent <StaticSprite2D>();
                    newBallSprite.Sprite = wheelSprites.Count > i ? wheelSprites[i] : wheelSprites.Last();

                    float x2 = _vehicleModel.WheelsBodyPosition[i].X % _vehicleImgPos;
                    float y2 = _vehicleModel.WheelsBodyPosition[i].Y % _vehicleImgPos;
                    x2 = x2 >= _vehicleImgPos / 2 ? (x2 - _vehicleImgPos / 2) * Application.PixelSize : -(_vehicleImgPos / 2 - x2) * Application.PixelSize;
                    y2 = (_vehicleImgPos / 2 - y2) * Application.PixelSize;

                    // Update collision shape
                    CollisionCircle2D collisionShape = newWheelNode.GetComponent <CollisionCircle2D>(); // Create circle shape
                    collisionShape.Radius = 0.14f;                                                      // * _vehicleModel.WheelsSize[i];
                    // WHEEL POSITION - NEEDS TO BE SET RELATIVE TO MAIN BODY
                    newWheelNode.Scale    = new Vector3(_vehicleModel.WheelsSize[i], _vehicleModel.WheelsSize[i], 1.0f);
                    newWheelNode.Position = new Vector3(x2, y2 + (_vehicleVerticalOffset - 0.05f) * _screenInfo.YScreenRatio, 1.0f);

                    // SET FRONT WHEEL CONSTRAINT COMPONENTS
                    var constraintWheel = car.CreateComponent <ConstraintWheel2D>();
                    constraintWheel.OtherBody      = newWheelNode.GetComponent <RigidBody2D>();
                    constraintWheel.Anchor         = newWheelNode.Position2D;
                    constraintWheel.Axis           = new Vector2(0.0f, 1.0f);
                    constraintWheel.MaxMotorTorque = 150.0f;
                    constraintWheel.FrequencyHz    = 15.0f;
                    constraintWheel.DampingRatio   = 10.0f;
                    constraintWheel.MotorSpeed     = 0.0f;
                    _wheelsConstraints.Add(constraintWheel);
                }
            }
        }
Ejemplo n.º 2
0
    void GenerateChunk(int startx)
    {
        // We create a node and position where the chunk starts
        Node node = _scene.CreateChild();

        node.SetPosition2D(startx, 0);

        // We create components to render the geometries of the surface and the ground
        var groundComponent = node.CreateComponent <CustomGeometry>();

        groundComponent.SetMaterial(_chunkmat);
        groundComponent.BeginGeometry(0, PrimitiveType.TRIANGLE_LIST);

        var surfaceComponent = node.CreateComponent <CustomGeometry>();

        surfaceComponent.SetMaterial(_surfMat);
        surfaceComponent.BeginGeometry(0, PrimitiveType.TRIANGLE_LIST);

        // We initialize and add a single entry to the surface points list
        List <Vector2> surface = new List <Vector2>()
        {
            new Vector2(0,
                        (float)_noise.Evaluate(startx * NoiseScaleX, 0) * NoiseScaleY
                        )
        };

        // We translate the last surface extrusion point so it's local relative to the chunk we're creating
        _lastSurfaceExtrusion += Vector3.Left * Chunksize;

        // We //TODO continue
        float incr = SurfaceSegmentSize;

        for (float i = 0; i < Chunksize - float.Epsilon * 2; i += incr)
        {
            float iend = i + incr;
            float tlY  = SampleSurface(startx + i);
            float trY  = SampleSurface(startx + iend);
            float blY  = tlY + Chunkheight;
            float brY  = trY + Chunkheight;

            Vector3 bl = new Vector3(i, blY, -10);
            Vector3 tl = new Vector3(i, tlY, -10);
            Vector3 br = new Vector3(iend, brY, -10);
            Vector3 tr = new Vector3(iend, trY, -10);

            //phys
            surface.Add(new Vector2(tr));

            //decor
            CreateDecor(tr + Vector3.Right * startx, tl - tr);

            //surface visual
            Vector2 startV = Vector2.UnitX * (i / Chunksize) * SurfaceRepeatPerChunk;
            Vector2 endV   = Vector2.UnitX * (iend / Chunksize * SurfaceRepeatPerChunk);
            //bl
            surfaceComponent.DefineVertex(_lastSurfaceExtrusion);
            surfaceComponent.DefineTexCoord(startV);
            //tl
            surfaceComponent.DefineVertex(tl);
            surfaceComponent.DefineTexCoord(startV - Vector2.UnitY);
            //tr
            surfaceComponent.DefineVertex(tr);
            surfaceComponent.DefineTexCoord(-Vector2.UnitY + endV);
            //bl
            surfaceComponent.DefineVertex(_lastSurfaceExtrusion);
            surfaceComponent.DefineTexCoord(startV);
            //tr
            surfaceComponent.DefineVertex(tr);
            surfaceComponent.DefineTexCoord(-Vector2.UnitY + endV);
            //br
            _lastSurfaceExtrusion = tr + Quaternion.FromAxisAngle(Vector3.Back, 90) * Vector3.NormalizeFast(tr - tl);
            surfaceComponent.DefineVertex(_lastSurfaceExtrusion);
            surfaceComponent.DefineTexCoord(endV);

            //ground
            //bl
            groundComponent.DefineVertex(bl);
            groundComponent.DefineTexCoord(new Vector2(bl / Chunksize));
            //tl
            groundComponent.DefineVertex(tl);
            groundComponent.DefineTexCoord(new Vector2(tl / Chunksize));
            //tr
            groundComponent.DefineVertex(tr);
            groundComponent.DefineTexCoord(new Vector2(tr / Chunksize));
            //bl
            groundComponent.DefineVertex(bl);
            groundComponent.DefineTexCoord(new Vector2(bl / Chunksize));
            //tr
            groundComponent.DefineVertex(tr);
            groundComponent.DefineTexCoord(new Vector2(tr / Chunksize));
            //br
            groundComponent.DefineVertex(br);
            groundComponent.DefineTexCoord(new Vector2(br / Chunksize));
        }
        surfaceComponent.Commit();
        groundComponent.Commit();


        CollisionChain2D col = node.CreateComponent <CollisionChain2D>();

        col.SetLoop(false);
        col.SetFriction(10);
        col.SetVertexCount((uint)surface.Count + 1);
        _chunks.Add(col);

        //Vector3 smoother = Quaternion.FromRotationTo(Vector3.Left, new Vector3(-1,-.3f,0)) * new Vector3(surface[0] - surface[1]);
        //col.SetVertex(0,surface[0] + new Vector2(smoother));

        Vector2 smoother = new Vector2(-incr * .5f, (float)_noise.Evaluate((startx - incr * .5f) * NoiseScaleX, 0) * NoiseScaleY - 0.005f);

        col.SetVertex(0, smoother);

        uint c2 = 0;

        foreach (Vector2 surfpoint in surface)
        {
            col.SetVertex(++c2, new Vector2(surfpoint.X, surfpoint.Y));
        }

        node.CreateComponent <RigidBody2D>().SetBodyType(BodyType2D.BT_STATIC);
    }
Ejemplo n.º 3
0
    void GenerateChunk(int startx)
    {
        Node n = scene.CreateChild();

        n.SetPosition2D(startx, 0);

        var g = n.CreateComponent <CustomGeometry>();

        g.SetMaterial(chunkmat);
        g.BeginGeometry(0, PrimitiveType.TRIANGLE_LIST);

        var s = n.CreateComponent <CustomGeometry>();

        s.SetMaterial(surfMat);
        s.BeginGeometry(0, PrimitiveType.TRIANGLE_LIST);

        List <Vector2> surface = new List <Vector2>()
        {
            new Vector2(0,
                        (float)noise.Evaluate((startx) * noiseScaleX, 0) * noiseScaleY
                        )
        };

        lastSurfaceExtrusion += Vector3.Left * chunksize;

        float incr = 0.5f;

        for (float i = 0; i < chunksize - float.Epsilon * 2; i += incr)
        {
            float iend = i + incr;
            float tlY  = SampleSurface(startx + i);
            float trY  = SampleSurface(startx + iend);
            float blY  = tlY + chunkheight;
            float brY  = trY + chunkheight;

            Vector3 bl = new Vector3(i, blY, 0);
            Vector3 tl = new Vector3(i, tlY, 0);
            Vector3 br = new Vector3(iend, brY, 0);
            Vector3 tr = new Vector3(iend, trY, 0);

            //phys
            surface.Add(new Vector2(tr));

            //decor
            CreateDecor(tr + Vector3.Right * startx, tl - tr);

            //surface visual
            Vector2 startV = Vector2.UnitX * (i / chunksize) * surfaceVisualRepeatPerChunk;
            Vector2 endV   = Vector2.UnitX * (iend / chunksize * surfaceVisualRepeatPerChunk);
            //bl
            s.DefineVertex(lastSurfaceExtrusion);
            s.DefineTexCoord(startV);
            //tl
            s.DefineVertex(tl);
            s.DefineTexCoord(startV - Vector2.UnitY);
            //tr
            s.DefineVertex(tr);
            s.DefineTexCoord(-Vector2.UnitY + endV);
            //bl
            s.DefineVertex(lastSurfaceExtrusion);
            s.DefineTexCoord(startV);
            //tr
            s.DefineVertex(tr);
            s.DefineTexCoord(-Vector2.UnitY + endV);
            //br
            lastSurfaceExtrusion = tr + Quaternion.FromAxisAngle(Vector3.Back, 90) * Vector3.NormalizeFast(tr - tl);
            s.DefineVertex(lastSurfaceExtrusion);
            s.DefineTexCoord(endV);

            //ground
            //bl
            g.DefineVertex(bl);
            g.DefineTexCoord(new Vector2(bl / chunksize));
            //tl
            g.DefineVertex(tl);
            g.DefineTexCoord(new Vector2(tl / chunksize));
            //tr
            g.DefineVertex(tr);
            g.DefineTexCoord(new Vector2(tr / chunksize));
            //bl
            g.DefineVertex(bl);
            g.DefineTexCoord(new Vector2(bl / chunksize));
            //tr
            g.DefineVertex(tr);
            g.DefineTexCoord(new Vector2(tr / chunksize));
            //br
            g.DefineVertex(br);
            g.DefineTexCoord(new Vector2(br / chunksize));
        }
        s.Commit();
        g.Commit();


        CollisionChain2D col = n.CreateComponent <CollisionChain2D>();

        col.SetLoop(false);
        col.SetFriction(10);
        col.SetVertexCount((uint)surface.Count + 1);
        chunks.Add(col);

        //Vector3 smoother = Quaternion.FromRotationTo(Vector3.Left, new Vector3(-1,-.3f,0)) * new Vector3(surface[0] - surface[1]);
        //col.SetVertex(0,surface[0] + new Vector2(smoother));

        Vector2 smoother = new Vector2(-incr * .5f, (float)noise.Evaluate((startx - incr * .5f) * noiseScaleX, 0) * noiseScaleY - 0.005f);

        col.SetVertex(0, smoother);

        uint c2 = 0;

        foreach (Vector2 surfpoint in surface)
        {
            col.SetVertex(++c2, new Vector2(surfpoint.X, surfpoint.Y));
        }

        n.CreateComponent <RigidBody2D>().SetBodyType(BodyType2D.BT_STATIC);
    }
Ejemplo n.º 4
0
        void CreateBackgroundScene()
        {
            scene = new Scene();
            scene.CreateComponent <Octree>();
            scene.CreateComponent <DebugRenderer>();
            scene.CreateComponent <PhysicsWorld2D>();

            // Create camera node
            CameraNode = scene.CreateChild("Camera");
            // Set camera's position
            CameraNode.Position = (new Vector3(0.1f, 0.0f, -2.0f));

            Camera camera = CameraNode.CreateComponent <Camera>();

            camera.Orthographic = true;

            camera.OrthoSize = (float)graphics.Height * PixelSize;
            camera.Zoom      = 3.5f * Math.Min(screenInfoRatio.XScreenRatio, screenInfoRatio.YScreenRatio);

            // Create 2D physics world component
            scene.CreateComponent <PhysicsWorld2D>();

            Sprite2D boxSprite = cache.GetSprite2D("Urho2D/Box.png");

            // FOREGROUND
            Sprite2D foregroundSprite = cache.GetSprite2D("Urho2D/foreground.png");
            Node     foregroundNode   = scene.CreateChild("Foreground");

            foregroundNode.Position = (new Vector3(0.9f, -1.25f, 0.0f));
            foregroundNode.Scale    = new Vector3(2.0f, 2.0f, 0.0f);
            StaticSprite2D foregroundStaticSprite = foregroundNode.CreateComponent <StaticSprite2D>();

            foregroundStaticSprite.Sprite = foregroundSprite;

            // BACKGROUND LAYER 1
            Sprite2D bgLayer1Sprite = cache.GetSprite2D("Urho2D/bg_layer1.png");
            Node     bgLayer1Node   = scene.CreateChild("Background_layer1");

            bgLayer1Node.Position = (new Vector3(0.9f, -1.25f, 0.1f));
            bgLayer1Node.Scale    = new Vector3(2.0f, 2.0f, 0.0f);
            StaticSprite2D bgLayer1StaticSprite = bgLayer1Node.CreateComponent <StaticSprite2D>();

            bgLayer1StaticSprite.Sprite = bgLayer1Sprite;

            // BACKGROUND LAYER 2
            Sprite2D backgroundSprite = cache.GetSprite2D("Urho2D/bg_layer2.png");
            Node     backgroundNode   = scene.CreateChild("Background_layer2");

            backgroundNode.Position = (new Vector3(0.9f, -1.25f, 0.1f));
            backgroundNode.Scale    = new Vector3(2.0f, 2.0f, 0.0f);
            StaticSprite2D backgroundStaticSprite = backgroundNode.CreateComponent <StaticSprite2D>();

            backgroundStaticSprite.Sprite = backgroundSprite;

            // Create ground.
            Node groundNode = scene.CreateChild("Ground");

            groundNode.Position = (new Vector3(0.0f, -3.0f, 0.0f));
            //groundNode.Scale = new Vector3(200.0f, 1.0f, 0.0f);

            // Create 2D rigid body for gound
            groundNode.CreateComponent <RigidBody2D>();

            StaticSprite2D groundSprite = groundNode.CreateComponent <StaticSprite2D>();

            groundSprite.Sprite = boxSprite;

            // CHAIN GROUND
            CollisionChain2D collisionChain = groundNode.CreateComponent <CollisionChain2D>();

            collisionChain.VertexCount = 200;
            for (var i = 0; i < 200; i++)
            {
                Vector2 currVertex;
                if (i > 0)
                {
                    currVertex = collisionChain.GetVertex((uint)i - 1);
                    collisionChain.SetVertex((uint)i, new Vector2((i / 2.0f) - 5.0f, currVertex.Y + NextRandom(-0.1f, 0.1f)));
                }
                else
                {
                    collisionChain.SetVertex((uint)i, new Vector2((i / 2.0f) - 5.0f, NextRandom(-0.1f, 0.1f)));
                }
            }


            collisionChain.Friction    = 0.3f; // Set friction
            collisionChain.Restitution = 0.0f; // Set restitution (no bounce)


            // FLAT BOX GROUND
            // Create box collider for ground
            //CollisionBox2D groundShape = groundNode.CreateComponent<CollisionBox2D>();
            // Set box size
            //groundShape.Size = new Vector2(0.32f, 0.32f);
        }
Ejemplo n.º 5
0
    void GenerateChunk(int startx)
    {
        // We create a node and position where the chunk starts
        Node node = _scene.CreateChild();

        node.SetPosition2D(startx, 0);

        // We create components to render the geometries of the surface and the ground
        var groundComponent = node.CreateComponent <CustomGeometry>();

        groundComponent.SetMaterial(_chunkMaterial);
        groundComponent.BeginGeometry(0, PrimitiveType.TRIANGLE_LIST);

        var surfaceComponent = node.CreateComponent <CustomGeometry>();

        surfaceComponent.SetMaterial(_surfaceMaterial);
        surfaceComponent.BeginGeometry(0, PrimitiveType.TRIANGLE_LIST);

        // We initialize and add a single entry to the surface collider points list
        List <Vector2> surfacePoints = new List <Vector2>()
        {
            new Vector2(0,
                        (float)_noise.Evaluate(startx * NoiseScaleX, 0) * NoiseScaleY
                        )
        };

        // We translate the last surface extrusion point so it's local relative to the chunk we're creating
        _lastSurfaceExtrusion += Vector3.Left * Chunksize;

        // We loop all the segments in this chunk
        float incr = SurfaceSegmentSize;

        for (float x = 0; x < Chunksize - float.Epsilon * 8; x += incr)
        {
            // We store vars for the position for the current segment end point x position and for the y position of the 4 points
            float xEnd = x + incr;
            float tlY  = SampleSurface(startx + x);
            float trY  = SampleSurface(startx + xEnd);
            float blY  = tlY + Chunkheight;
            float brY  = trY + Chunkheight;

            // We create vectors that represent
            Vector3 bl = new Vector3(x, blY, -10);
            Vector3 tl = new Vector3(x, tlY, -10);
            Vector3 br = new Vector3(xEnd, brY, -10);
            Vector3 tr = new Vector3(xEnd, trY, -10);

            // We add the top right point to the surface points list (remember we added the first point in the list init)
            surfacePoints.Add(new Vector2(tr));

            // We call the CreateDecor function passing the global position of the current segment end point and the segment angle
            CreateDecor(tr + Vector3.Right * startx, tl - tr);

            // We create the geometry of the surface (UV os oriented according to the surface)
            Vector2 startV = Vector2.UnitX * (x / Chunksize) * SurfaceRepeatPerChunk;
            Vector2 endV   = Vector2.UnitX * (xEnd / Chunksize * SurfaceRepeatPerChunk);
            //bl
            surfaceComponent.DefineVertex(_lastSurfaceExtrusion);
            surfaceComponent.DefineTexCoord(startV);
            //tl
            surfaceComponent.DefineVertex(tl);
            surfaceComponent.DefineTexCoord(startV - Vector2.UnitY);
            //tr
            surfaceComponent.DefineVertex(tr);
            surfaceComponent.DefineTexCoord(-Vector2.UnitY + endV);
            //bl
            surfaceComponent.DefineVertex(_lastSurfaceExtrusion);
            surfaceComponent.DefineTexCoord(startV);
            //tr
            surfaceComponent.DefineVertex(tr);
            surfaceComponent.DefineTexCoord(-Vector2.UnitY + endV);
            //br - We store the last point to use for continuity
            _lastSurfaceExtrusion = tr + Quaternion.FromAxisAngle(Vector3.Back, 90) * Vector3.NormalizeFast(tr - tl);
            surfaceComponent.DefineVertex(_lastSurfaceExtrusion);
            surfaceComponent.DefineTexCoord(endV);

            // We create the geometry of the ground (UV is in world coordinates)
            //bl
            groundComponent.DefineVertex(bl);
            groundComponent.DefineTexCoord(new Vector2(bl / Chunksize));
            //tl
            groundComponent.DefineVertex(tl);
            groundComponent.DefineTexCoord(new Vector2(tl / Chunksize));
            //tr
            groundComponent.DefineVertex(tr);
            groundComponent.DefineTexCoord(new Vector2(tr / Chunksize));
            //bl
            groundComponent.DefineVertex(bl);
            groundComponent.DefineTexCoord(new Vector2(bl / Chunksize));
            //tr
            groundComponent.DefineVertex(tr);
            groundComponent.DefineTexCoord(new Vector2(tr / Chunksize));
            //br
            groundComponent.DefineVertex(br);
            groundComponent.DefineTexCoord(new Vector2(br / Chunksize));
        }
        // We commit the geometry data we just created
        surfaceComponent.Commit();
        groundComponent.Commit();

        // We create the collider component for the chunk surface
        CollisionChain2D surfaceCollider = node.CreateComponent <CollisionChain2D>();

        surfaceCollider.SetLoop(false);
        surfaceCollider.SetFriction(1);
        surfaceCollider.SetVertexCount((uint)surfacePoints.Count + 1);
        _chunks.Add(surfaceCollider);

        // We add a small overlapping segment with a bit of negative offset in y so the wheel passes smoothly over chunk seams
        Vector2 smoother = new Vector2(-incr * .5f, (float)_noise.Evaluate((startx - incr * .5f) * NoiseScaleX, 0) * NoiseScaleY - .005f);

        surfaceCollider.SetVertex(0, smoother);

        // Finally, we set the vertex of the surface collider
        for (int c = 0; c < surfacePoints.Count; c++)
        {
            Vector2 surfacePoint = surfacePoints[c];
            surfaceCollider.SetVertex((uint)c + 1, surfacePoint);
        }

        // A collider must have a rigid body to interact with other bodies, even if static which is the case
        node.CreateComponent <RigidBody2D>().SetBodyType(BodyType2D.BT_STATIC);
    }