/// <summary> /// Changes from Fase 1 to Fase 2 /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator F1ToF2StateCoroutine() { // Make boss vanish yield return(StartCoroutine(MakeBossVanish(_bossVanishTime))); // Move boss gameObject to F2 position transform.position = new Vector3(_f2PlatformPosition.position.x, _f2PlatformPosition.position.y, transform.position.z); // Wait for some time yield return(new WaitForSeconds(2.0f)); // Make platforms appear for (int i = 0; i < _f2OtherPlatforms.Length; i++) { _f2OtherPlatforms[i].SetActive(true); } // Make spikes appear _f2LeftSpikes.SetActive(true); _f2RightSpikes.SetActive(true); _f2LeftPlatformSpikes.SetActive(true); _f2RightPlatformSpikes.SetActive(true); // Make boss appear yield return(StartCoroutine(MakeBossReappear(_bossVanishTime))); // Change state _enemyState = EEnemyStates.Alert; // Clear coroutine reference _f1ToF2StateCoroutine = null; }
/// <summary> /// F2 spikes reappearing coroutine /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator F2SpikesReappearCoroutine() { // Vanish boss _spriteRenderer.enabled = false; _capsuleCollider2D.enabled = false; _attackSlider.normalizedValue = 0.0f; //_attackSlider.gameObject.SetActive(false); //_healthSlider.gameObject.SetActive(false); // Disable spikes colliders ManageSpikesCollidersTriggers(false); // Reappearing process float l_iter = 0; // Process while (l_iter < _f2SpikesReappearTimes) { // Enable spikes ManageSpikes(true); yield return(new WaitForSeconds(0.75f)); // Disable spikes ManageSpikes(false); yield return(new WaitForSeconds(0.25f)); l_iter++; } // Enable spikes colliders ManageSpikesCollidersTriggers(true); // Enable spikes ManageSpikes(true); // Disable platform _f2FirstPlatform.SetActive(false); // Wait some time yield return(new WaitForSeconds(2.0f)); // Disable middle spike _f2MiddleSpikes.SetActive(false); // Reappear boss _spriteRenderer.enabled = true; _capsuleCollider2D.enabled = true; //_attackSlider.gameObject.SetActive(true); //_healthSlider.gameObject.SetActive(true); // Change state _enemyState = EEnemyStates.DistanceAttack; // Change animator AnimatorStateInfo l_animatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0); if (!l_animatorStateInfo.IsName("SamuraiHeavyBoss_Alert")) { _animator.SetTrigger("ToAlert"); } // Recharge attack bar _attackSlider.normalizedValue = 1.0f; // Clear coroutine reference _f2SpikesReappearCoroutine = null; }
public void AttackState() { // Get attack target position if (_attackTargetPosition == Vector3.zero) { float l_x = _player.position.x > _f3RightLimit.position.x ? _f3RightLimit.position.x : (_player.position.x < _f3LeftLimit.position.x ? _f3LeftLimit.position.x : _player.position.x); float l_y = _f3LeftLimit.position.y; _attackTargetPosition = new Vector3(l_x, l_y, 0.0f); // Flip is needed if (transform.position.x < _attackTargetPosition.x && !_facingRight) { FlipFacingDirection(); } // Flip is needed if (transform.position.x > _attackTargetPosition.x && _facingRight) { FlipFacingDirection(); } // Play attack sound PlayRandomSound(); } // Attack // Distance to move float l_dist = _flySpeed * Time.fixedDeltaTime; // Save boss previous position before moving Vector3 l_previousPosition = transform.position; // Move boss towards attack target position transform.position = Vector3.MoveTowards(transform.position, _attackTargetPosition, l_dist); // Check if boss has reached attack target position if (Mathf.Abs(transform.position.x - l_previousPosition.x) < 0.01f && Mathf.Abs(transform.position.y - l_previousPosition.y) < 0.01f) { // Put boss on attack target position transform.position = _attackTargetPosition; // Put attack target position to zero _attackTargetPosition = Vector3.zero; // Change state _enemyState = EEnemyStates.None; // Loops left _loopsLeft--; // Attack bar _attackSlider.normalizedValue = (float)_loopsLeft / (float)_attackLoops; // Check loops left if (_loopsLeft == 0) { // Change state _enemyState = EEnemyStates.Idle; // Enable animator _animator.enabled = true; _animator.SetTrigger("ToIdle"); } } }
/// <summary> /// Gets called when boss hurt animations ends /// </summary> public void BossHurtEndAnimationEvent() { // Set flag _isHurt = false; // Manage flip //FlipFacingDirection(); // Set run slashing loops left //_loopsLeft = _attackLoops; // Change state _enemyState = EEnemyStates.Alert; // Change boss fase if (_hitsLeft > 4) { } if (_hitsLeft <= 4 && _hitsLeft > 2) { if (_bossFase != EBossFases.Fase2) { // Change fase _bossFase = EBossFases.Fase2; // Change state _enemyState = EEnemyStates.None; // Start fase 1 to fase 2 coroutine _f1ToF2StateCoroutine = StartCoroutine(F1ToF2StateCoroutine()); } else { // Change state _enemyState = EEnemyStates.None; // Start reappearing spikes _f2SpikesReappearCoroutine = StartCoroutine(F2SpikesReappearCoroutine()); } } if (_hitsLeft <= 2 && _hitsLeft > 0) { if (_bossFase != EBossFases.Fase3) { // Change fase _bossFase = EBossFases.Fase3; // Change state _enemyState = EEnemyStates.None; // Start fase 2 to fase 3 coroutine _f2ToF3StateCoroutine = StartCoroutine(F2ToF3StateCoroutine()); } else { // Change state _enemyState = EEnemyStates.None; // Start reappearing spikes _f3VanishReappearCoroutine = StartCoroutine(F3VanishReappearCoroutine()); } } // Change animator state _animator.SetBool("IsHurt", false); }
public void RunSlashingState() { // Set speed direction float l_runSpeed = _facingRight ? _runSpeed : _runSpeed * (-1.0f); // Move enemy transform.Translate(l_runSpeed * Time.fixedDeltaTime, 0.0f, 0.0f, Space.Self); // Whether the enemy is facing right or not... if (_facingRight) { // If right limit is reached if (transform.position.x > _f1RightLimit.position.x) { // Put enemy in right limit position transform.position = new Vector3(_f1RightLimit.position.x, transform.position.y, transform.position.z); // Set remaining lopps _loopsLeft--; // Set attack slider value _attackSlider.normalizedValue = (float)_loopsLeft / (float)_attackLoops; // If remaining loops are 0 if (_loopsLeft == 0) { // Change state _enemyState = EEnemyStates.Idle; // Change animator state _animator.SetTrigger("ToIdle"); // Cancel sound invoking CancelInvoke("PlayRandomSound"); return; } // Manage flip FlipFacingDirection(); } } else { // If left limit is reached if (transform.position.x < _f1LeftLimit.position.x) { // Put enemy in left limit position transform.position = new Vector3(_f1LeftLimit.position.x, transform.position.y, transform.position.z); // Manage flip FlipFacingDirection(); } } // Invoke attack sounds if (!IsInvoking("PlayRandomSound")) { InvokeRepeating("PlayRandomSound", 0.1f, 1.5f); } }
/// <summary> /// Gets called when enemy hurt animations ends /// </summary> public void EnemyHurtEndAnimationEvent() { // Set flag _isHurt = false; // Manage flip FlipFacingDirection(); // Set run slashing loops left _loopsLeft = _attackLoops; // Change state _enemyState = EEnemyStates.RunSlash; // Change animator state _animator.SetBool("IsHurt", false); }
/// <summary> /// Boss takes hit /// </summary> public void TakeDamage(int damage) { // Only hurt boss when in idle state if (_enemyState != EEnemyStates.Idle) { return; } // Take damage _hitsLeft--; // Set health slider _healthSlider.normalizedValue = (float)_hitsLeft / (float)_maxHits; // Cancel coroutine if (_idleStateCoroutine != null) { StopCoroutine(_idleStateCoroutine); _idleStateCoroutine = null; } // Manage state depending on remaining health if (_hitsLeft == 0) { // Attack bar _attackSlider.normalizedValue = 0.0f; // Disable collider _capsuleCollider2D.enabled = false; // Change state _enemyState = EEnemyStates.Dead; // Change animator state _animator.SetTrigger("IsDead"); // Play dead sound _audioSource.PlayOneShot(_deathAudioClip); } else { // Set flag _isHurt = true; // Change state _enemyState = EEnemyStates.Hurt; // Change animator state _animator.SetBool("IsHurt", true); // Play damage sound PlayRandomSound(); } }
/// <summary> /// Idle state coroutine waits for a period of time /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator IdleStateCoroutine() { // stay sometime in idle state before changing to run slashing yield return(new WaitForSeconds(_idleTime)); // Manage flip FlipFacingDirection(); // Set run slashing loops left _loopsLeft = _attackLoops; // Change state _enemyState = EEnemyStates.RunSlash; // Change animator state _animator.SetTrigger("ToRunSlashing"); // Set variable to null _idleStateCoroutine = null; }
/// <summary> /// Enemy takes damage /// </summary> /// <param name="damage">Damage</param> public void TakeDamage(int damage) { // Only hurt enemy when in idle state if (_enemyState != EEnemyStates.Idle) { return; } // Take damage _health = _health - damage < 0 ? 0 : _health - damage; // Set health slider _healthSlider.normalizedValue = (float)_health / (float)_maxHealth; // Cancel coroutine if (_idleStateCoroutine != null) { StopCoroutine(_idleStateCoroutine); _idleStateCoroutine = null; } // Manage state depending on remaining health if (_health == 0) { // Disable collider _capsuleCollider2D.enabled = false; // Change state _enemyState = EEnemyStates.Dead; // Change animator state _animator.SetTrigger("IsDead"); // Play dead sound _audioSource.PlayOneShot(_audioClipDead); } else { // Set flag _isHurt = true; // Change state _enemyState = EEnemyStates.Hurt; // Change animator state _animator.SetBool("IsHurt", true); // Play damage sound _audioSource.PlayOneShot(_audioClipDamage); } }
/// <summary> /// Waits between attack fases in F3 /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator F3WaitBetweenAttackFasesCoroutine(float waitTime) { // Enable animator _animator.enabled = true; // Wait some time yield return(new WaitForSeconds(waitTime)); // Rebind and disable animator _animator.Rebind(); _animator.enabled = false; // Change sprite _spriteRenderer.sprite = _f3AttackSprite; // Change state _enemyState = EEnemyStates.Attack; // Clear coroutine reference _f3WaitBetweenAttackFasesCoroutine = null; }
/// <summary> /// Run slashing state /// </summary> private void RunSlashingState() { // Set speed direction float l_runSpeed = _facingRight ? _runSpeed : _runSpeed * (-1.0f); // Move enemy transform.Translate(l_runSpeed * Time.fixedDeltaTime, 0.0f, 0.0f, Space.Self); // Whether the enemy is facing right or not... if (_facingRight) { // If right limit is reached if (transform.position.x > _rightLimit.position.x) { // Put enemy in right limit position transform.position = new Vector3(_rightLimit.position.x, transform.position.y, transform.position.z); // Set remaining lopps _loopsLeft--; // If remaining loops are 0 if (_loopsLeft == 0) { // Change state _enemyState = EEnemyStates.Idle; // Change animator state _animator.SetTrigger("ToIdle"); return; } // Manage flip FlipFacingDirection(); } } else { // If left limit is reached if (transform.position.x < _leftLimit.position.x) { // Put enemy in left limit position transform.position = new Vector3(_leftLimit.position.x, transform.position.y, transform.position.z); // Manage flip FlipFacingDirection(); } } }
/// <summary> /// Makes boss vanish and reappear in F3 /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator F3VanishReappearCoroutine() { // Change animator state _animator.SetTrigger("ToAlert"); // Make boss vanish yield return(StartCoroutine(MakeBossVanish(_bossVanishTime))); // Rebind and disable animator _animator.Rebind(); _animator.enabled = false; // Change to attack sprite _spriteRenderer.sprite = _f3AttackSprite; // Choose random reappear position transform.position = RandomReappearPosition(); // Flip is needed if (transform.position.x > 0.0f && _facingRight) { FlipFacingDirection(); } if (transform.position.x < 0.0f && !_facingRight) { FlipFacingDirection(); } // Boss levitation move if (_f3LevitationMove == null) { _f3LevitationMove = StartCoroutine(F3LevitationMove()); } // Make boss reappear yield return(StartCoroutine(MakeBossReappear(_bossVanishTime))); // Change state _enemyState = EEnemyStates.Alert; // Clear coroutine reference _f3VanishReappearCoroutine = null; }
/// <summary> /// F2 Vertical attack coroutine /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator F2VerticalKunaiCoroutine() { float l_waitedTime = 0.0f; while (l_waitedTime < _f2DistanceAttackTime) { GameObject l_verticalKunai = Instantiate(_kunaiPrefab, GameManager.Instance.PrefabContainer); l_verticalKunai.transform.position = new Vector3(_player.position.x, _f2KunaiSpawnerPosition.position.y, 0.0f); l_verticalKunai.transform.Rotate(0.0f, 0.0f, -90.0f, Space.Self); l_waitedTime += _f2VerticalKunaiAttackDeltaTime; _attackSlider.normalizedValue = Mathf.Clamp01(1.0f - l_waitedTime / _f2DistanceAttackTime); yield return(new WaitForSeconds(_f2VerticalKunaiAttackDeltaTime)); } // Change state _enemyState = EEnemyStates.Idle; // Change animator _animator.SetTrigger("ToIdle"); // Clear coroutine reference _f2VerticalKunaiCoroutine = null; }
/// <summary> /// Changes from Fase 2 to Fase 3 /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator F2ToF3StateCoroutine() { // Make boss vanish yield return(StartCoroutine(MakeBossVanish(_bossVanishTime))); // Disable spikes colliders ManageSpikesCollidersTriggers(false); // Disable platform _f2FirstPlatform.SetActive(false); // Reappearing process float l_iter = 0; // Process while (l_iter < _f2SpikesReappearTimes) { // Enable spikes ManageSpikes(true); yield return(new WaitForSeconds(0.75f)); // Disable spikes ManageSpikes(false); yield return(new WaitForSeconds(0.25f)); l_iter++; } // Enable spikes colliders ManageSpikesCollidersTriggers(true); // Enable spikes ManageSpikes(true); // Wait some time yield return(new WaitForSeconds(2.0f)); // Disable spikes ManageSpikes(false); // Disable other platforms for (int i = 0; i < _f2OtherPlatforms.Length; i++) { _f2OtherPlatforms[i].SetActive(false); } // Wait some time yield return(new WaitForSeconds(2.0f)); // Rebind and disable animator _animator.Rebind(); _animator.enabled = false; // Change to attack sprite _spriteRenderer.sprite = _f3AttackSprite; // Choose random reappear position transform.position = RandomReappearPosition(); // Flip is needed if (transform.position.x > 0.0f) { FlipFacingDirection(); } // Boss levitation move if (_f3LevitationMove == null) { _f3LevitationMove = StartCoroutine(F3LevitationMove()); } // Make boss reappear yield return(StartCoroutine(MakeBossReappear(_bossVanishTime))); // Change state _enemyState = EEnemyStates.Alert; // Clear coroutine reference _f2ToF3StateCoroutine = null; }
/// <summary> /// Idle state F1 coroutine waits for a period of time /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator IdleStateCoroutine() { // Before waiting switch (_bossFase) { case EBossFases.Fase1: break; case EBossFases.Fase2: { // Disable spikes _f2LeftSpikes.SetActive(false); _f2RightSpikes.SetActive(false); _f2LeftPlatformSpikes.SetActive(false); _f2RightPlatformSpikes.SetActive(false); // Enable platform _f2FirstPlatform.SetActive(true); } break; case EBossFases.Fase3: break; default: break; } // Set attack slider value to 0 _attackSlider.normalizedValue = 0.0f; // stay sometime in idle state before changing to run slashing // Recharge attack bar float l_waitedTime = 0.0f; float l_idleTime = _bossFase == EBossFases.Fase1 ? _f1IdleTime : (_bossFase == EBossFases.Fase2 ? _f2IdleTime : _f3IdleTime); while (l_waitedTime < l_idleTime) { yield return(new WaitForSeconds(0.1f)); l_waitedTime += 0.1f; if (l_waitedTime > l_idleTime) { l_waitedTime = l_idleTime; } _attackSlider.normalizedValue = l_waitedTime / l_idleTime; } // switch (_bossFase) { case EBossFases.Fase1: { // Manage flip FlipFacingDirection(); // Set run slashing loops left _loopsLeft = _attackLoops; // Change state and animator _enemyState = EEnemyStates.RunSlash; _animator.SetTrigger("ToRunSlashing"); } break; case EBossFases.Fase2: { // Change state _enemyState = EEnemyStates.None; // Start spikes reappearing _f2SpikesReappearCoroutine = StartCoroutine(F2SpikesReappearCoroutine()); } break; case EBossFases.Fase3: { // Change state _enemyState = EEnemyStates.None; // Start spikes reappearing _f3VanishReappearCoroutine = StartCoroutine(F3VanishReappearCoroutine()); } break; default: break; } // Clear coroutine reference _idleStateCoroutine = null; }
/// <summary> /// Alert state coroutine waits for a period of time /// </summary> /// <returns>The reference to the coroutine</returns> private IEnumerator AlertStateCoroutine() { // Before waiting switch (_bossFase) { case EBossFases.Fase1: break; case EBossFases.Fase2: { // Enable spikes _f2LeftSpikes.SetActive(true); _f2RightSpikes.SetActive(true); _f2LeftPlatformSpikes.SetActive(true); _f2RightPlatformSpikes.SetActive(true); // Disable platform _f2FirstPlatform.SetActive(false); } break; case EBossFases.Fase3: break; default: break; } // Set attack slider value to 0 _attackSlider.normalizedValue = 0.0f; // Enable particle system _rechargeAttackPSFX.SetActive(true); // Stay sometime in alert state before changing to next state and recharge atack bar float l_waitedTime = 0.0f; float l_alertTime = _bossFase == EBossFases.Fase1 ? _f1AlertTime : (_bossFase == EBossFases.Fase2 ? _f2AlertTime : _f3AlertTime); while (l_waitedTime < l_alertTime) { yield return(new WaitForSeconds(0.1f)); l_waitedTime += 0.1f; if (l_waitedTime > l_alertTime) { l_waitedTime = l_alertTime; } _attackSlider.normalizedValue = l_waitedTime / l_alertTime; } // Disable particle system _rechargeAttackPSFX.SetActive(false); // switch (_bossFase) { case EBossFases.Fase1: { // Manage flip FlipFacingDirection(); // Set run slashing loops left _loopsLeft = _attackLoops; // Change state and animator _enemyState = EEnemyStates.RunSlash; _animator.SetTrigger("ToRunSlashing"); } break; case EBossFases.Fase2: { // Change state _enemyState = EEnemyStates.DistanceAttack; } break; case EBossFases.Fase3: { // Set attack loops left _loopsLeft = _attackLoops; // Change state _enemyState = EEnemyStates.Attack; // Stop boss levitation move StopCoroutine(_f3LevitationMove); _f3LevitationMove = null; } break; default: break; } // Clear coroutine reference _alertStateCoroutine = null; }