예제 #1
0
    // Check only the bottom part of the object
    protected bool GroundCheck(float sizeY = 0.01f)
    {
        Vector2 size   = new Vector2(0.1f, sizeY);
        Vector3 offset = new Vector2(0, sr.bounds.extents.y + size.y);

        GameDebug.DrawBox(transform.position - offset, size, Color.red);
        return(Physics2D.BoxCast(transform.position - offset, size, 0, Vector2.down, size.y, LayerMask.GetMask("Ground")));
    }
예제 #2
0
    bool CastBox()
    {
        Vector2 boxSize = new Vector2(spriteExtents.x / 1.5f, 0.02f);
        Vector3 boxPos  = transform.position - new Vector3(0, spriteExtents.y + boxSize.y + .075f) * Mathf.Sign(rb.gravityScale);

        GameDebug.DrawBox(boxPos, boxSize, Color.red);
        return(Physics2D.BoxCast(boxPos, boxSize, 0, Vector2.zero, 0, LayerMask.GetMask("Ground")));
    }
예제 #3
0
 bool BoxCast(Vector2 pos, Vector2 size, Color color)
 {
     GameDebug.DrawBox(pos, size, color);
     return(Physics2D.BoxCast(pos, size, 0, Vector2.zero, 0, LayerMask.GetMask("Ground")));
 }
예제 #4
0
    void ExecuteBrain(BrainType type)
    {
        switch (type)
        {
        case BrainType.Maggot:
        {
            if (cliffCheck || wallCheck)
            {
                targetDir *= -1;
            }
            switch (state)
            {
            case EnemyState.Normal:
            {
                if (!isDelaying)
                {
                    bool inRange = IsInRangeX(distanceToTeleportX) && IsInRangeY(distanceToTeleportY);
                    if (player.controller.groundCheck && (!inRange || cliffCheck))
                    {
                        if (canTeleport || cliffCheck)
                        {
                            canTeleport = false;
                            StartCoroutine(Teleport(waitTimeAfterExecute));
                        }
                        else
                        {
                            StartCoroutine(DelayTeleport(delayTeleportTime));

                            IEnumerator DelayTeleport(float delayTime)
                            {
                                isDelaying = true;
                                yield return(new WaitForSeconds(delayTime));

                                canTeleport = true;
                                isDelaying  = false;
                            }
                        }
                    }
                    else if (canTeleport)
                    {
                        canTeleport = false;
                    }
                }

                if (IsInRange(distanceToExecute))
                {
                    StartCoroutine(Explode());
                }
            } break;
            }
        } break;

        case BrainType.NoEyes:
        {
            // TODO: Handle cases when the player is still in range after cooldown.
            switch (state)
            {
            case EnemyState.Normal:
            {
                if (IsInRange(distanceToExecute))
                {
                    StartCoroutine(Dash(true));
                }
                else
                {
                    targetDir = (player.transform.position - transform.position).normalized;
                }
            } break;

            case EnemyState.Cooldown:
            {
                rb.velocity = new Vector2(-Mathf.Sign(player.transform.position.x - transform.position.x), Mathf.Sign(player.transform.position.y - transform.position.y)) * speed * speedAfterDashScale;
                StartCoroutine(StartState(EnemyState.Charge, abilityCooldownTime));
            } break;
            }
        } break;

        case BrainType.FlyDrone:
        {
            targetDir = (player.transform.position - transform.position).normalized;
            if ((targetDir.x < .5f) && (targetDir.x > -.5f))         // between 60-120 degrees
            {
                if (targetDir.y > 0)
                {
                    eye.localPosition = lookUpPos;
                }
                else
                {
                    eye.localPosition = lookDownPos;
                }
            }
            else
            {
                eye.localPosition = Vector3.zero;
            }
            if (IsInRange(distanceToExecute))
            {
                StartCoroutine(Explode());
                StartCoroutine(RotateEnemy(0, timeToReachRot));
            }
        } break;

        case BrainType.Bat:
        {
            targetDir = (player.transform.position - transform.position).normalized;
            if (IsInRange(distanceToExecute))
            {
                StartCoroutine(Explode());
            }
        } break;

        case BrainType.GiantEye:
        {
            /*
             * Phase 1:
             * - Moves like no eyes
             * - Spawns little eyes
             * - When dashes and hits wall, create a wave of projectile
             * Phase 2:
             * - Moves to the center
             * - Shoots circle waves of projectiles
             * - Shoots toward the player
             * - Shoots big projectiles that explode into smaller projectiles
             */

            switch (state)
            {
            case EnemyState.Normal:
            {
                // TODO: Sometimes the enemy already collide with wall. Fix it so that the enemy only dash when doesn't collide with wall.
                if (IsInRange(distanceToExecute))
                {
                    StartCoroutine(Dash(false));                 // NOTE: Maybe enable trail differently.
                }
#if false
                else if (Time.time > timer)
                {
                    timer = Time.time + abilityCooldownTime;
                    int enemyCount = numberOfEnemiesToSpawn.randomValue;
                    for (int i = 0; i < enemyCount; i++)
                    {
                        Vector3 pos;                 // TODO: Get random position, maybe from RoomManager
                        Instantiate(enemyToSpawn, pos, Quaternion.identity);
                    }

                    anim.Play("");
                    StartCoroutine(StartState(EnemyState.Charge, anim.GetCurrentAnimatorStateInfo(0).length));
                }
#endif
                else
                {
                    targetDir = (player.transform.position - transform.position).normalized;
                }
            } break;

            case EnemyState.Cooldown:
            {
                // Spawn wave of bullets
                {
                    Vector2 dir = MathUtils.Sign(targetDir);
                    // Make sure the enemy isn't inside wall
                    {
                        float magnitude;
                        // Calculate the magnitude of the ray from the center to the egde of the box collider.
                        // https://stackoverflow.com/questions/1343346/calculate-a-vector-from-the-center-of-a-square-to-edge-based-on-radius
                        {
                            float absCos = Mathf.Abs(Mathf.Cos(targetDir.x));
                            float absSin = Mathf.Abs(Mathf.Sin(targetDir.y));
                            if (spriteSize.x * absSin <= spriteSize.y * absCos)
                            {
                                magnitude = spriteSize.x / 2 / absCos;
                            }
                            else
                            {
                                magnitude = spriteSize.y / 2 / absSin;
                            }
                        }

                        Vector2      spriteOrigin = (Vector2)transform.position + spriteOffset * dir.x;
                        RaycastHit2D hitInfo      = Physics2D.Raycast(spriteOrigin, targetDir, magnitude, LayerMask.GetMask("Ground"));
                        Debug.DrawRay(spriteOrigin, targetDir * magnitude, Color.white);

                        if (hitInfo)                 // NOTE: Sometime the enemy stop right before actually touching the ground (because of the raycast's length) so I will need this check.
                        {
                            transform.position -= (Vector3)dir * (magnitude - hitInfo.distance);
                            GameDebug.DrawBox(spriteOrigin - dir * (magnitude - hitInfo.distance), spriteSize, Color.white);
                        }
                    }

                    Vector3 center = transform.position + (Vector3)spriteOffset * dir.x;
                    if (wallCheck)
                    {
                        center.x += (spriteSize.x - 1.5f) / 2 * dir.x;
                    }
                    if (groundCheck)
                    {
                        center.y += (spriteSize.y - 1.5f) / 2 * dir.y;
                    }

                    Vector2 compareOffset = Vector2.Scale(Vector2.one * .2f, dir);                 // For precision error
                    MathUtils.GenerateCircleOutlineNonAlloc(center, radius, bulletsPos);
                    foreach (var pos in bulletsPos)
                    {
                        if (wallCheck && (Mathf.Sign(pos.x - (center.x + compareOffset.x)) == dir.x))
                        {
                            continue;
                        }
                        if (groundCheck && (Mathf.Sign(pos.y - (center.y + compareOffset.y)) == dir.y))
                        {
                            continue;
                        }

                        Vector3 euler = new Vector3(0, 0, Vector2.SignedAngle(Vector2.right, pos - center));
                        if (euler.z > 90 || euler.z < -90)
                        {
                            euler = new Vector3(0, 180f, 180f - euler.z);
                        }
                        ObjectPooler.Spawn(PoolType.Bullet_Blood, pos, Quaternion.Euler(euler)).GetComponent <MovingEntity>().InitBullet(bulletDamage, false, true);
                    }
                }

                anim.Play("");
                StartCoroutine(StartState(EnemyState.Charge, waitTimeAfterExecute));
            } break;
            }
        } break;

        case BrainType.LittleEye:
        {
            // TODO: Behave like no eyes but explode into projectiles when die
        } break;
        }
    }