Exemplo n.º 1
0
    public Planetoid CreatePlanetoid(Vector2 pos)
    {
        Planetoid newPlanetoid = GetNewOrCashedPlanetoid();

        newPlanetoid.transform.position = pos;
        newPlanetoid.Initialize(_planetoidSize, _planetoidPointCount, this);
        return(newPlanetoid);
    }
Exemplo n.º 2
0
    // returns null if nothing was sliced
    // even when hit by the laser nothing might get sliced
    //	this is because I limit the minimum size of a new
    //	planetoid for performance reasons.
    //
    public Planetoid Slice(Ray2D laser, float laserPower, PlanetoidsManager manager)
    {
        if (_fading)
        {
            return(null);
        }

        try {
            Vector2 start = transform.InverseTransformPoint(laser.origin);
            Vector2 end   = transform.InverseTransformPoint(laser.origin + laser.direction * Laser.LASER_DISTANCE);

            SlicePoint[] slicePoints = new SlicePoint[2];
            Vector2[]    vertices    = _collider.points;
            int          foundPoints = 0;
            for (int i = 0; i < vertices.Length && foundPoints <= 2; ++i)
            {
                //Calculate intersectionPoint
                //For formula see http://en.wikipedia.org/wiki/Line-line_intersection
                //I'm using x1, x2, ... since that's easier to write.
                float   x1 = start.x, x2 = end.x, x3 = vertices[i].x, x4 = vertices[(i + 1) % vertices.Length].x;
                float   y1 = start.y, y2 = end.y, y3 = vertices[i].y, y4 = vertices[(i + 1) % vertices.Length].y;
                Vector2 intersectionPoint = new Vector2(
                    (((x1 * y2 - y1 * x2) * (x3 - x4)) - ((x1 - x2) * (x3 * y4 - y3 * x4))) / (((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))),
                    (((x1 * y2 - y1 * x2) * (y3 - y4)) - ((y1 - y2) * (x3 * y4 - y3 * x4))) / (((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4)))
                    );

                //See if the point is is actually on the side & laser.

                float startx = Mathf.Min(vertices[i].x, vertices[(i + 1) % vertices.Length].x);              //side
                float endx   = Mathf.Max(vertices[i].x, vertices[(i + 1) % vertices.Length].x);
                float starty = Mathf.Min(vertices[i].y, vertices[(i + 1) % vertices.Length].y);
                float endy   = Mathf.Max(vertices[i].y, vertices[(i + 1) % vertices.Length].y);

                float start2x = Mathf.Min(start.x, end.x);                 //laser
                float end2x   = Mathf.Max(start.x, end.x);
                float start2y = Mathf.Min(start.y, end.y);
                float end2y   = Mathf.Max(start.y, end.y);
                if (intersectionPoint.x >= startx && intersectionPoint.x < endx && intersectionPoint.y >= starty && intersectionPoint.y < endy &&
                    intersectionPoint.x >= start2x && intersectionPoint.x < end2x && intersectionPoint.y >= start2y && intersectionPoint.y < end2y)
                {
                    //Add to the slicePoints vector if you find anything
                    // throws when too many points were found
                    slicePoints[foundPoints] = new SlicePoint(intersectionPoint, i);
                    ++foundPoints;
                }
            }

            if (foundPoints != 2)
            {
                throw new UnityException("Wrong number of points found while slicing: " + foundPoints);
            }

            //Calculate the number of sides each part of the rock will have
            int numberOfPoints1 = Mathf.Abs(slicePoints[0].side - slicePoints[1].side);
            int numberOfPoints2 = vertices.Length - numberOfPoints1;
            //numberOfPoints1 = min(numberOfPoints1, b2_maxPolygonVertices-2); //Make sure there aren't too many vertexes (Box2D 'limitation')
            //numberOfPoints2 = min(numberOfPoints2, b2_maxPolygonVertices-2); //I raised the max Polygon verts to 16 (default 8) so it will almost never happen, though when it does it's almost invisible
            //Create vectors to save the sides of each new rock
            Vector2[] sides1 = new Vector2[numberOfPoints1 + 2];
            Vector2[] sides2 = new Vector2[numberOfPoints2 + 2];

            //Filling in the first vector
            int counter = slicePoints[0].side + 1;
            for (var i = 0; i < numberOfPoints1; ++i)
            {
                if (counter >= vertices.Length)
                {
                    throw new UnityException("Whoops, something wrong with the slicing. Should never happen, please report this.");                     //Should never go over 0
                }
                sides1[i] = vertices[counter];
                ++counter;
            }
            //Lastly add the intersection points to the sides1.
            sides1[numberOfPoints1 + 0] = slicePoints[1].point;             //Since I add them to the back the second one found will always be the first one here.
            sides1[numberOfPoints1 + 1] = slicePoints[0].point;

            //Filling in the second one
            for (var i = 0; i < numberOfPoints2; ++i)
            {
                counter   = counter % vertices.Length;
                sides2[i] = vertices[counter];
                ++counter;
            }
            sides2[numberOfPoints2 + 0] = slicePoints[0].point;
            sides2[numberOfPoints2 + 1] = slicePoints[1].point;

            //Check if both new polygons are valid. Their size & winding will be checked, also they have to be convex.
            if (GetArea(sides1) < MINIMUM_AREA || GetArea(sides2) < MINIMUM_AREA)
            {
                throw new UnityException("At least one of the new planetoids is too small, not slicing for performance reasons.");
            }

            //Get some values needed to set later.
            Vector2 linVel   = _rigidbody.velocity;
            float   angleVel = _rigidbody.angularVelocity;
            Vector2 dir      = laser.direction;
            Vector2 lr       = new Vector2(-dir.y, dir.x);
            lr.Normalize();
            lr *= laserPower;

            //Change this rock.
            Initialize(sides1, manager);

            //Make the other part.
            Planetoid newRock = manager.GetNewOrCashedPlanetoid();
            newRock.Initialize(sides2, manager);
            newRock.transform.position         = transform.position;
            newRock.transform.rotation         = transform.rotation;
            newRock._rigidbody.velocity        = linVel;
            newRock._rigidbody.angularVelocity = angleVel;
            newRock._density = _density;

            //Set Velocities.
            _rigidbody.AddForce(lr, ForceMode2D.Impulse);
            newRock._rigidbody.AddForce(-lr, ForceMode2D.Impulse);

            return(newRock);
        }
        catch (UnityException ex) {
            Debug.Log("Failed slicing: " + ex.Message);
            return(null);
        }
        catch {
            Debug.Log("Failed slicing for an unknown reason");
            return(null);
        }
    }