Beispiel #1
0
        public bool RaycastSquare(Vector2 origin, float size, TileDirection direction, float len, out TileHitInfo hitInfo)
        {
            size *= 0.95f;

            hitInfo = new TileHitInfo();

            int iterations = Mathf.Max(Mathf.CeilToInt(size / TILE_SIZE), 1);

            Vector2 from = origin - GetTanget(origin, direction) * (size * 0.5f);
            Vector2 step = GetTanget(origin, direction) * (size / iterations);

            bool        hitAny = false;
            TileHitInfo localHitInfo;

            for (int i = 0; i <= iterations; i++)
            {
                if (Raycast(from, direction, len, out localHitInfo))
                {
                    if (!hitAny)
                    {
                        hitAny  = true;
                        hitInfo = localHitInfo;
                    }
                    else if (localHitInfo.hitDistance < hitInfo.hitDistance)
                    {
                        hitInfo = localHitInfo;
                    }
                }

                from += step;
            }

            return(hitAny);
        }
Beispiel #2
0
        public bool Raycast(Vector2 origin, TileDirection direction, float len, out TileHitInfo hitInfo)
        {
            hitInfo = new TileHitInfo();

            float dx             = origin.x - position.x;
            float dy             = origin.y - position.y;
            float originDistance = Mathf.Sqrt(dx * dx + dy * dy);

            Vector2 target;
            float   targetdx;
            float   targetdy;
            float   targetDistance;
            float   tangentDistance;

            float segmentSize;

            if (originDistance < 0.001f)
            {
                originDistance = 0.001f;
            }

            float originMapAngle = -Mathf.Atan2(dy, dx) + Mathf.PI * 0.5f;

            while (originMapAngle > Mathf.PI * 2.0f)
            {
                originMapAngle -= Mathf.PI * 2.0f;
            }

            while (originMapAngle < 0.0f)
            {
                originMapAngle += Mathf.PI * 2.0f;
            }

            Vector2 originNormal  = new Vector2(dx / originDistance, dy / originDistance);
            Vector2 originTangent = new Vector2(originNormal.y, -originNormal.x);

            if (direction == TileDirection.Right)
            {
                target         = origin + originTangent * len;
                targetdx       = target.x - position.x;
                targetdy       = target.y - position.y;
                targetDistance = Mathf.Sqrt(targetdx * targetdx + targetdy * targetdy);

                if (originDistance > circleHeights[circleHeights.Length - 1])
                {
                    //Origin point outside, not hit!
                    return(false);
                }

                for (int i = 1; i < circleHeights.Length; i++)
                {
                    if (originDistance < circleHeights[i])
                    {
                        hitInfo.hitTileY = i - 1;
                        break;
                    }
                }

                segmentSize     = (circleHeights[hitInfo.hitTileY] * 2.0f * Mathf.PI) / width;
                tangentDistance = ((originMapAngle / (Mathf.PI * 2.0f)) * width);

                hitInfo.hitTileX = (int)tangentDistance;
                hitInfo.hitTileX = (hitInfo.hitTileX + 1) % width;

                len -= segmentSize * (Mathf.Ceil(tangentDistance) - tangentDistance);

                while (hitInfo.hitTileX < width && len >= 0)
                {
                    if (GetTile(hitInfo.hitTileX, hitInfo.hitTileY) != 0)
                    {
                        hitInfo.hitNormal = -GetTangentFromTileCoordinate(hitInfo.hitTileX, hitInfo.hitTileY);

                        hitInfo.hitPosition = position +
                                              circleNormals[hitInfo.hitTileX] * originDistance;

                        hitInfo.hitDistance = (origin - hitInfo.hitPosition).magnitude;
                        return(true);
                    }

                    len -= segmentSize;

                    hitInfo.hitTileX++;
                }
            }
            else if (direction == TileDirection.Left)
            {
                target         = origin + originTangent * len;
                targetdx       = target.x - position.x;
                targetdy       = target.y - position.y;
                targetDistance = Mathf.Sqrt(targetdx * targetdx + targetdy * targetdy);

                if (originDistance > circleHeights[circleHeights.Length - 1])
                {
                    //Origin point outside, not hit!
                    return(false);
                }

                for (int i = 1; i < circleHeights.Length; i++)
                {
                    if (originDistance < circleHeights[i])
                    {
                        hitInfo.hitTileY = i - 1;
                        break;
                    }
                }

                segmentSize     = (circleHeights[hitInfo.hitTileY] * 2.0f * Mathf.PI) / width;
                tangentDistance = ((originMapAngle / (Mathf.PI * 2.0f)) * width);

                hitInfo.hitTileX = (int)tangentDistance;
                hitInfo.hitTileX = (hitInfo.hitTileX - 1) % width;
                if (hitInfo.hitTileX < 0)
                {
                    hitInfo.hitTileX += width;
                }

                len -= segmentSize * (tangentDistance - Mathf.Floor(tangentDistance));

                while (hitInfo.hitTileX >= 0 && len >= 0)
                {
                    if (GetTile(hitInfo.hitTileX, hitInfo.hitTileY) != 0)
                    {
                        hitInfo.hitNormal = GetTangentFromTileCoordinate(hitInfo.hitTileX + 1, hitInfo.hitTileY);

                        hitInfo.hitPosition = position +
                                              circleNormals[(hitInfo.hitTileX + 1) % width] * originDistance;

                        hitInfo.hitDistance = (origin - hitInfo.hitPosition).magnitude;
                        return(true);
                    }

                    len -= segmentSize;

                    hitInfo.hitTileX--;
                }
            }
            else if (direction == TileDirection.Up)
            {
                target         = origin + originNormal * len;
                targetdx       = target.x - position.x;
                targetdy       = target.y - position.y;
                targetDistance = Mathf.Sqrt(targetdx * targetdx + targetdy * targetdy);

                if (originDistance > circleHeights[circleHeights.Length - 1])
                {
                    //Origin point outside, not hit!
                    return(false);
                }

                hitInfo.hitTileX = (int)((originMapAngle / (Mathf.PI * 2.0f)) * width);
                hitInfo.hitTileX = hitInfo.hitTileX % width;

                for (int i = 1; i < circleHeights.Length; i++)
                {
                    if (originDistance < circleHeights[i])
                    {
                        hitInfo.hitTileY = i;
                        len -= circleHeights[i] - originDistance;
                        break;
                    }
                }

                while (hitInfo.hitTileY < height && len >= 0)
                {
                    if (GetTile(hitInfo.hitTileX, hitInfo.hitTileY) != 0)
                    {
                        hitInfo.hitNormal   = -originNormal;
                        hitInfo.hitPosition = position + originNormal * circleHeights[hitInfo.hitTileY];
                        hitInfo.hitDistance = (origin - hitInfo.hitPosition).magnitude;
                        return(true);
                    }

                    if (hitInfo.hitTileY < height - 1)
                    {
                        len -= (circleHeights[hitInfo.hitTileY + 1] - circleHeights[hitInfo.hitTileY]);
                    }

                    hitInfo.hitTileY++;
                }
            }
            else if (direction == TileDirection.Down)
            {
                target         = origin - originNormal * len;
                targetdx       = target.x - position.x;
                targetdy       = target.y - position.y;
                targetDistance = Mathf.Sqrt(targetdx * targetdx + targetdy * targetdy);

                if (/*originDistance > circleHeights[circleHeights.Length - 1] &&*/
                    targetDistance > circleHeights[circleHeights.Length - 1])
                {
                    //Target outside, no hit!
                    return(false);
                }
                else if (targetDistance < circleHeights[0])
                {
                    //Target inside core, core hit!
                    hitInfo.hitTileY    = 0;
                    hitInfo.hitNormal   = originNormal;
                    hitInfo.hitPosition = position + originNormal * circleHeights[0];
                    hitInfo.hitDistance = (origin - hitInfo.hitPosition).magnitude;

                    return(true);
                }

                hitInfo.hitTileX = (int)((originMapAngle / (Mathf.PI * 2.0f)) * width);
                hitInfo.hitTileX = hitInfo.hitTileX % width;

                for (int i = circleHeights.Length - 1; i >= 1; i--)
                {
                    if (originDistance > circleHeights[i])
                    {
                        hitInfo.hitTileY = i - 1;
                        len -= originDistance - circleHeights[i];
                        break;
                    }
                }

                while (hitInfo.hitTileY >= 0 && len > 0)
                {
                    if (GetTile(hitInfo.hitTileX, hitInfo.hitTileY) != 0)
                    {
                        hitInfo.hitNormal   = originNormal;
                        hitInfo.hitPosition = position + originNormal * circleHeights[hitInfo.hitTileY + 1];
                        hitInfo.hitDistance = (origin - hitInfo.hitPosition).magnitude;
                        return(true);
                    }

                    if (hitInfo.hitTileY > 0)
                    {
                        len -= (circleHeights[hitInfo.hitTileY] - circleHeights[hitInfo.hitTileY - 1]);
                    }
                    hitInfo.hitTileY--;
                }
            }

            return(false);
        }