Пример #1
0
    public void MoveClockwise(float units)
    {
        if (_target == null)
        {
            return;
        }

        var normalAngle = (_target.rotation + _curPos.normalDegrees) * Mathf.Deg2Rad;
        var normal      = Vector2Ext.FromPolar(1, normalAngle);
        var moveVec     = Vector2Ext.FromPolar(units, normalAngle - Mathf.PI / 2);
        var newPos      = transform.position.AsVector2() + moveVec;

        if (linecastAndSnap(newPos + normal, newPos - normal))
        {
            return;
        }

        var cornerTestRot = -45 * Mathf.Sign(units);
        var cornerNormal  = normal.Rotate(cornerTestRot);
        var cornerMoveVec = moveVec.Rotate(cornerTestRot);
        var cornerNewPos  = transform.position.AsVector2() + cornerMoveVec;

        if (linecastAndSnap(cornerNewPos + cornerNormal, cornerNewPos - cornerNormal))
        {
            return;
        }

        cornerTestRot = 45 * Mathf.Sign(units);
        cornerNormal  = normal.Rotate(cornerTestRot);
        cornerMoveVec = moveVec.Rotate(cornerTestRot);
        cornerNewPos  = transform.position.AsVector2() + cornerMoveVec;

        if (linecastAndSnap(cornerNewPos + cornerNormal, cornerNewPos - cornerNormal))
        {
            return;
        }
    }
Пример #2
0
    SnapResult linecastAndSnap(Vector2 p0, Vector2 p1, Vector2 offset)
    {
        var hitsPrime = Physics2D.LinecastAll(p0, p1, MooseController.CollisionLayerMask);
        var hitsDos   = new List <RaycastHit2D>();

        for (var i = 0; i < hitsPrime.Length; ++i)
        {
            if (_targetBody)
            {
                if (hitsPrime[i].rigidbody == _targetBody)
                {
                    hitsDos.Add(hitsPrime[i]);
                }
            }
            else
            {
                if (hitsPrime[i].collider == _target)
                {
                    hitsDos.Add(hitsPrime[i]);
                }
            }
        }
        if (hitsDos.Count == 0)
        {
            return new SnapResult {
                       success = false
            }
        }
        ;
        var hit = hitsDos[0];

        return(new SnapResult {
            success = true,
            newPos = worldCoordsToSurfaceCoords(hit.point + offset, hit.normal),
            normal = hit.normal
        });
    }

    bool maybeMoveToSnap(SnapResult snap, Func <Vector2, bool> normalCheck)
    {
        if (!snap.success || !normalCheck(snap.normal))
        {
            return(false);
        }
        moveToSurfaceCoord(snap.newPos);
        return(true);
    }

    void moveToSurfaceCoord(SurfaceCoords pos)
    {
        _lastPos    = _curPos;
        _curPos     = pos;
        _updateFlag = true;
    }

    Vector2 surfaceCoordsToWorldCoords(SurfaceCoords s)
    {
        var targetObject = _targetBody ? _targetBody.gameObject : _target.gameObject;

        var theta = (targetObject.transform.rotation.eulerAngles.z + s.degrees) * Mathf.Deg2Rad;

        return(Vector2Ext.FromPolar(s.radius, theta) + targetObject.transform.position.AsVector2());
    }

    SurfaceCoords worldCoordsToSurfaceCoords(Vector2 pos, Vector2 normal)
    {
        var ds          = pos - (_targetBody ? _targetBody.position : _target.transform.position.AsVector2());
        var angleOffset = _targetBody ? _targetBody.rotation : _target.transform.rotation.z;

        return(new SurfaceCoords {
            radius = ds.magnitude,
            degrees = Mathf.Atan2(ds.y, ds.x) * Mathf.Rad2Deg - angleOffset,
            normalDegrees = Mathf.Atan2(normal.y, normal.x) * Mathf.Rad2Deg - angleOffset
        });
    }
}
Пример #3
0
    UpdateResult doUpdatePosition(float vx, Func <Vector2, bool> normalCheck, int collisionValue, bool collisionSolid, bool checkWalls)
    {
        var normalAngle = ((_targetBody ? _targetBody.rotation : _target.transform.rotation.z) + _curPos.normalDegrees) * Mathf.Deg2Rad;

        if (!checkWalls && Mathf.Abs(vx) < 0.0001f)
        {
            return(new UpdateResult {
                stillStanding = normalCheck(Vector2Ext.FromPolar(1, normalAngle)),
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        if (FixVX)
        {
            vx /= Mathf.Cos(normalAngle - Mathf.PI / 2);
        }

        var pos = surfaceCoordsToWorldCoords(_curPos);

        var normal  = Vector2Ext.FromPolar(1, normalAngle);
        var tangent = normal.Rotate(-90);
        var moveVec = vx * tangent;
        var newPos  = pos + moveVec;

        if (checkWalls)
        {
            var newMiddle = newPos + (GravitySetting.Reverse ? -1 : 1) * Vector2.up * _heroDim.HalfHeight;
            var wallTestL = newMiddle - (tangent * _heroDim.HalfWidth) / tangent.x;
            var wallTestR = newMiddle + (tangent * _heroDim.HalfWidth) / tangent.x;

            Debug.DrawLine(wallTestL, wallTestR, Color.magenta);

            bool pushed;
            var  penetration = wallTest(wallTestL, wallTestR, vx > 0 ? PushForce : -PushForce, out pushed, normalCheck);

            if (penetration.HasValue)
            {
                var depth = penetration.Value;
                if (GravitySetting.Reverse)
                {
                    depth *= -1;
                }
                var colVal = 0;
                if (!pushed)
                {
                    colVal = depth > 0 ? 1 : -1;
                }
                return(doUpdatePosition(vx - depth, normalCheck, colVal, !pushed, false));
            }

            if (Mathf.Abs(vx) < 0.0001f)
            {
                return(new UpdateResult {
                    stillStanding = normalCheck(Vector2Ext.FromPolar(1, normalAngle)),
                    wallCollision = collisionValue,
                    solidWallCollision = collisionSolid
                });
            }
        }

        // Check if the center ray of the player hits the target collider.

        if (maybeMoveToSnap(linecastAndSnap(newPos + normal, newPos - normal), normalCheck))
        {
            return(new UpdateResult {
                stillStanding = true,
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        // Check if we're walking around a 90 degree or greater bend.

        var cornerTestRot = -45 * Mathf.Sign(vx);
        var cornerNormal  = normal.Rotate(cornerTestRot);
        var cornerMoveVec = moveVec.Rotate(cornerTestRot);
        var cornerNewPos  = pos + cornerMoveVec;

        if (maybeMoveToSnap(linecastAndSnap(cornerNewPos + cornerNormal, cornerNewPos - cornerNormal), normalCheck))
        {
            return(new UpdateResult {
                stillStanding = true,
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        // Check if we're edging out where the center doesn't collider, but an edge does.
        var edgeVec = tangent * (_heroDim.HalfWidth - _heroDim.InsetX);

        if (maybeMoveToSnap(linecastAndSnap(newPos + edgeVec + normal, newPos + edgeVec - normal, -edgeVec), normalCheck) ||
            maybeMoveToSnap(linecastAndSnap(newPos - edgeVec + normal, newPos - edgeVec - normal, edgeVec), normalCheck))
        {
            return(new UpdateResult {
                stillStanding = true,
                wallCollision = collisionValue,
                solidWallCollision = collisionSolid
            });
        }

        return(new UpdateResult {
            stillStanding = false,
            wallCollision = collisionValue,
            solidWallCollision = collisionSolid
        });
    }
Пример #4
0
    Vector2 surfaceCoordsToWorldCoords(SurfaceCoords s)
    {
        var theta = (_target.gameObject.transform.rotation.eulerAngles.z + s.degrees) * Mathf.Deg2Rad;

        return(Vector2Ext.FromPolar(s.radius, theta) + _target.transform.position.AsVector2());
    }
Пример #5
0
    public Vector2 CheckNormal()
    {
        var normalAngle = (_target.rotation + _curPos.normalDegrees) * Mathf.Deg2Rad;

        return(Vector2Ext.FromPolar(1, normalAngle));
    }