IdleGirl/Assets/2_Codes/BattleManager.cs

341 lines
12 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using TMPro;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using DarkTonic.MasterAudio;
using System.Collections;
#if UNITY_EDITOR
// PackageManager 관련 코드
#endif
public class BattleManager : MonoBehaviour
{
public GameObject HeroUnit;
public Transform[] MonsterPositions = new Transform[3];
public GameObject HitEffectPrefab;
public GameObject MissPrefab;
public GameObject NumberPrefab;
public GameObject CriticalPrefab;
public TextMeshProUGUI stageClearText;
public Image darkPanel; // 다크 커튼 이미지를 담을 변수
public float CriticalRate; // 치명타 확률(10000분율)
public float CriticalDamage; // 치명타 배율(10000분율)
public int HeroDamag; // 영웅 공격력
private List<Transform> aliveMonsters = new List<Transform>();
private bool stageCleared = false;
private bool isHeroAttacking = false;
public string playlistName = "Bgm";
// 스프라이트 랜더러 배열 추가
private SpriteRenderer[] spriteRenderers;
private void Start()
{
// 처음에 모든 몬스터를 생존 몬스터 리스트에 추가
foreach (Transform monsterPos in MonsterPositions)
{
aliveMonsters.Add(monsterPos);
}
// NumberPrefab의 자식 오브젝트 수를 가져옵니다.
int childCount = NumberPrefab.transform.childCount;
// 스프라이트 랜더러 배열 초기화
spriteRenderers = new SpriteRenderer[childCount];
// 각 자식 오브젝트의 스프라이트 랜더러 컴포넌트를 배열에 할당
for (int i = 0; i < childCount; i++)
{
Transform child = NumberPrefab.transform.GetChild(i);
SpriteRenderer spriteRenderer = child.GetComponent<SpriteRenderer>();
if (spriteRenderer != null)
{
spriteRenderers[i] = spriteRenderer;
}
else
{
Debug.LogError("SpriteRenderer component not found on child " + i + " of NumberPrefab.");
}
}
MasterAudio.PlaylistsMuted = true;
MasterAudio.PlaySound("BGM_DAILYDUNGEON", 0.7f);
}
public void HeroAttack()
{
if (aliveMonsters.Count > 0 && !isHeroAttacking)
{
isHeroAttacking = true;
HeroUnit.SetActive(true);
// 영웅의 공격 애니메이션
Sequence attackSequence = DOTween.Sequence();
attackSequence.Append(HeroUnit.transform.DOLocalMoveY(-700, 0.25f).SetEase(Ease.OutCubic));
attackSequence.AppendCallback(() =>
{
// 공격 애니메이션이 끝나면 몬스터에게 피해를 입힙니다.
DealDamageToMonster();
});
attackSequence.Append(HeroUnit.transform.DOLocalMoveY(-1500, 0.15f).SetEase(Ease.OutCubic));
attackSequence.OnComplete(() =>
{
// 애니메이션 종료 후 공격을 허용
isHeroAttacking = false;
HeroUnit.SetActive(false);
});
}
}
private void DealDamageToMonster()
{
if (aliveMonsters.Count > 0)
{
int randomMonsterIndex = Random.Range(0, aliveMonsters.Count);
Transform targetMonster = aliveMonsters[randomMonsterIndex];
float randomNumber = Random.Range(0, HeroDamag); // 0부터 영웅 공격력만큼의 피해를 적용
// 랜덤 값을 생성하여 크리티컬 확률과 비교
float randomValue = Random.Range(0, 10000); // 0부터 9999까지의 랜덤 값
bool isCritical = randomValue<= CriticalRate;
int resultNumber = 0;
int randomSoundIndex = Random.Range(1, 4); // 1부터 3까지의 랜덤한 정수 생성
string soundName = "Hot_Type2_" + randomSoundIndex.ToString(); // 사운드 이름 생성
MasterAudio.PlaySound(soundName, 0.7f, null);
int randomVoiceIndex = Random.Range(1, 13); // 1부터 12까지의 랜덤한 정수 생성
string voiceName = "Voice_HERO_01_Combo_1_" + randomVoiceIndex.ToString(); // 사운드 이름 생성
MasterAudio.PlaySound(voiceName, 0.7f, null);
if (isCritical)
{
resultNumber = Mathf.RoundToInt((randomNumber * CriticalDamage) / 10000f);
}
else
{
resultNumber = (int)randomNumber;
}
// HitEffectPrefab 오브젝트를 복제하여 이펙트를 표시할 오브젝트 생성
GameObject hitEffectPosition = Instantiate(HitEffectPrefab, targetMonster.position, Quaternion.identity);
hitEffectPosition.SetActive(true);
Destroy(hitEffectPosition, 0.5f); // 일정 시간 후에 제거
if (resultNumber == 0)
{
// 몬스터 위치로 미스 이펙트 발생
ShowMissDamage(targetMonster.position + new Vector3(0, 1.4f, 0), targetMonster);
}
else
{
ShowNumberDamage(targetMonster.position + new Vector3(0, 1.4f, 0), targetMonster, resultNumber, isCritical);
// HitEffectPrefab 오브젝트를 복제하여 이펙트를 표시할 오브젝트 생성
}
}
}
private void ShowMissDamage(Vector3 monsterPosition, Transform targetMonster)
{
// 몬스터 위치로 미스 이펙트 생성
GameObject missObject = Instantiate(MissPrefab, monsterPosition, Quaternion.identity);
missObject.SetActive(true);
// 미스 애니메이션
missObject.transform.localScale = Vector3.one * 1.5f;
missObject.transform.DOScale(Vector3.one * 0.3f, 0.4f).SetEase(Ease.OutCubic);
missObject.transform.DOMoveY(missObject.transform.position.y + 1, 0.5f).SetEase(Ease.OutCubic).OnComplete(() =>
{
Destroy(missObject);
});
}
private void ShowCriEffect(Vector3 monsterPosition, Transform targetMonster)
{
GameObject CriObject = Instantiate(CriticalPrefab, monsterPosition, Quaternion.identity);
CriObject.SetActive(true);
// 크리 애니메이션
CriObject.transform.localScale = Vector3.one * 1.5f;
CriObject.transform.DOScale(Vector3.one * 0.3f, 0.4f).SetEase(Ease.OutCubic);
CriObject.transform.DOMoveY(CriObject.transform.position.y + 1, 0.5f).SetEase(Ease.OutCubic).OnComplete(() =>
{
Destroy(CriObject);
});
}
private void ShowNumberDamage(Vector3 monsterPosition, Transform targetMonster, int damage, bool isCritical)
{
// 떨림 효과 추가
targetMonster.DOPunchPosition(new Vector3(10, 0, 0), 0.2f);
// damage를 문자열로 변환
string damageString = damage.ToString();
// 서로 떨어진 위치 조절값
float xOffset = 0;
if (isCritical)
{
xOffset+=2.3f;
}
else
{
xOffset += 1.1f;
}
float totalWidth = ((damageString.Length-1) * xOffset); // 전체 너비
// 부모 오브젝트 생성
GameObject digitObject = new GameObject("HitNumber");
// 숫자 위치를 monsterPosition을 기준으로 설정 (로컬 포지션)
digitObject.transform.localPosition = new Vector3(monsterPosition.x, monsterPosition.y - 2f, monsterPosition.z);
// 애니메이션 및 위치 설정
for (int i = 0; i < damageString.Length; i++)
{
int digit = int.Parse(damageString[i].ToString()); // 자릿수를 추출
if (digit >= 0 && digit < spriteRenderers.Length)
{
if (isCritical)
{
digit += 10;
}
// 숫자 스프라이트 랜더러 설정
SpriteRenderer digitSpriteRenderer = spriteRenderers[digit];
// 숫자 스프라이트 복제
GameObject digitImageObject = new GameObject("DigitImage"); // 새 게임 오브젝트 생성
//digitImageObject.transform.position = digitObject.transform.position;
// 스프라이트 랜더러 추가 및 설정
SpriteRenderer newRenderer = digitImageObject.AddComponent<SpriteRenderer>();
newRenderer.sprite = digitSpriteRenderer.sprite;
// Order 값을 300으로 설정
newRenderer.sortingOrder = 300;
// x 위치 조절하여 중앙 정렬된 상태에서 배치
float xPos = -totalWidth / 2 + i * xOffset;
digitImageObject.transform.localPosition = new Vector3(xPos, 0, 0);
// 스케일 조절 (크기 동일하게)
digitImageObject.transform.localScale = Vector3.one * 1.0f;
// 부모 설정
digitImageObject.transform.SetParent(digitObject.transform);
}
else
{
Debug.LogWarning("Digit out of range: " + digit);
}
}
if (isCritical)
{
ShowCriEffect(targetMonster.position + new Vector3(0, 1.8f, 0), targetMonster);
digitObject.transform.localScale = Vector3.one * 0.5f; // 크기 설정
digitObject.transform.DOScale(Vector3.one * 0.2f, 0.3f).SetEase(Ease.OutCubic);
digitObject.transform.DOMoveY(digitObject.transform.position.y + 2, 0.5f).SetEase(Ease.OutCubic).OnComplete(() =>
{
Destroy(digitObject); // 스프라이트 랜더러를 가진 게임 오브젝트를 제거합니다.
});
}
else
{
// digitObject를 기준으로 애니메이션 설정
digitObject.transform.localScale = Vector3.one * 0.5f; // 크기 설정
digitObject.transform.DOScale(Vector3.one * 0.3f, 0.3f).SetEase(Ease.OutCubic);
digitObject.transform.DOMoveY(digitObject.transform.position.y + 2, 0.5f).SetEase(Ease.OutCubic).OnComplete(() =>
{
Destroy(digitObject); // 스프라이트 랜더러를 가진 게임 오브젝트를 제거합니다.
});
}
// 몬스터의 HP 게이지 감소 처리
MonsterHealth monsterHealth = targetMonster.GetComponentInChildren<MonsterHealth>();
if (monsterHealth != null && !monsterHealth.IsDead)
{
monsterHealth.TakeDamage(damage); // damage 만큼 감소
// 만약 몬스터의 HP가 0 이하면
if (monsterHealth.CurrentHealth <= 0)
{
// 몬스터를 리스트에서 제거
aliveMonsters.Remove(targetMonster);
// 남은 몬스터가 없으면 StageClear 효과 표시
if (aliveMonsters.Count == 0 && !stageCleared)
{
stageCleared = true;
MasterAudio.StopAllOfSound("BGM_DAILYDUNGEON");
MasterAudio.PlaySound("BGM_VAILAGE", 0.7f);
ShowStageClearAnimation();
}
}
}
}
private void ShowStageClearAnimation()
{
// 텍스트 활성화 및 초기화
stageClearText.gameObject.SetActive(true);
HeroUnit.SetActive(false);
stageClearText.transform.localScale = Vector3.zero;
// Scale 애니메이션
stageClearText.transform.DOScale(Vector3.one, 0.5f).SetEase(Ease.OutBack).OnComplete(() =>
{
// 텍스트 흔들림 애니메이션
stageClearText.transform.DOShakePosition(1.0f, new Vector3(0, 10, 0), 10, 90, false, true).OnComplete(() =>
{
// 텍스트 페이드 아웃 애니메이션
CanvasGroup canvasGroup = stageClearText.GetComponent<CanvasGroup>();
canvasGroup.DOFade(0, 0.5f).OnComplete(() =>
{
// 다크 커튼 이미지 활성화
darkPanel.gameObject.SetActive(true);
// 어두움 효과 애니메이션 (투명도를 0에서 1로 변경)
DOVirtual.Float(0, 1.0f, 1.0f, (fadeValue) =>
{
darkPanel.color = new Color(0, 0, 0, fadeValue);
}).OnComplete(() =>
{
// 다음 씬 호출
MasterAudio.PlaySound("BGM_VAILAGE", 0);
MasterAudio.PlaylistsMuted = false;
SceneManager.LoadScene(4);
});
});
});
});
}
}