diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/AttackPattern.cs b/Gameton-06/Assets/Gameton/Scripts/Monster/AttackPattern.cs new file mode 100644 index 00000000..ccb1b2c2 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/AttackPattern.cs @@ -0,0 +1,100 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace TON +{ + public class AttackPattern + { + protected MonsterBase _monsterBase; + protected float _lastSkillTime; + protected float _skill1Cooldown = 5f; + protected float _skill2Cooldown = 8f; + + public AttackPattern(MonsterBase monsterBase) + { + _monsterBase = monsterBase; + // 쿨다운 값을 MonsterData에서 가져오기 + _skill1Cooldown = _monsterBase.GetSkillCooldown(1); + _skill2Cooldown = _monsterBase.GetSkillCooldown(2); + _lastSkillTime = -_skill1Cooldown; + } + + public virtual void Attack() + { + } + } + + public class Monster1AttackPattern : AttackPattern + { + public Monster1AttackPattern(MonsterBase monsterBase) : base(monsterBase) + { + } + + public override void Attack() + { + if (Time.time >= _lastSkillTime + _skill1Cooldown) + { + Skill1(); + _lastSkillTime = Time.time; + } + else + { + MeleeAttack(); + } + } + + private void Skill1() + { + _monsterBase.MonsterSkillLaunch(); + } + + private void MeleeAttack() + { + _monsterBase.PlayerAttack(); + } + } + + public class Monster2AttackPattern : AttackPattern + { + private float _lastSkill2Time; + + public Monster2AttackPattern(MonsterBase monsterBase) : base(monsterBase) + { + _lastSkill2Time = -_skill2Cooldown; + } + + public override void Attack() + { + if (Time.time >= _lastSkillTime + _skill1Cooldown) + { + Skill1(); + _lastSkillTime = Time.time; + } + else if (Time.time >= _lastSkill2Time + _skill2Cooldown) + { + Skill2(); + _lastSkill2Time = Time.time; + } + else + { + MeleeAttack(); + } + } + + private void Skill1() + { + _monsterBase.MonsterSkillLaunch(1); // 스킬 1 발사 + } + + private void Skill2() + { + _monsterBase.MonsterSkillLaunch(2); // 스킬 2 발사 + } + + private void MeleeAttack() + { + _monsterBase.PlayerAttack(); + } + } +} \ No newline at end of file diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/AttackPattern.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Monster/AttackPattern.cs.meta new file mode 100644 index 00000000..90e82e78 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/AttackPattern.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 96a0da67c3a27a447997ee4aee452d02 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterBase.Debug.cs b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterBase.Debug.cs new file mode 100644 index 00000000..f2a0c6e8 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterBase.Debug.cs @@ -0,0 +1,20 @@ +using UnityEngine; + +namespace TON +{ + public partial class MonsterBase + { + private void OnGUI() + { + if (GUILayout.Button("Hit")) + { + ApplyDamage(1); + } + + if (GUILayout.Button("Dead")) + { + ApplyDamage(1000000000); + } + } + } +} diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterBase.Debug.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterBase.Debug.cs.meta new file mode 100644 index 00000000..5eb5c706 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterBase.Debug.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: be351d22396005d4bbcd8a3e72592f75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkill.cs b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkill.cs new file mode 100644 index 00000000..252d46f0 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkill.cs @@ -0,0 +1,100 @@ +using UnityEngine; + +namespace TON +{ + public class MonsterSkill : MonoBehaviour + { + public float speed = 5f; + public float damage = 1; + + Vector2 direction; + Transform playerTransform; // 플레이어의 Transform을 저장할 변수 + [SerializeField] private SpriteRenderer _spriteRenderer; // 스킬의 스프라이트 렌더러 + + public Vector2 Direction + { + set { direction = value.normalized; } + } + + private MonsterBase _monsterBase; + private MonsterSkillData _skillData; + + void Start() + { + _spriteRenderer = GetComponent(); + + GameObject player = GameObject.FindGameObjectWithTag("Player"); + + if (player != null) + { + playerTransform = player.transform; + } + else + { + Debug.LogError("Player 오브젝트를 찾을 수 없습니다. 태그를 확인하세요."); + return; // 플레이어 없으면 이후 로직 실행 중지 + } + + SetDirection(); // 발사 방향 설정 + } + + void Update() + { + transform.Translate(direction * speed * Time.deltaTime); + } + + public void Initialize(MonsterBase monsterBase, MonsterSkillData skillData) + { + _monsterBase = monsterBase; + _skillData = skillData; + + GameObject player = GameObject.FindGameObjectWithTag("Player"); + if (player != null) + { + // 플레이어 방향으로 발사 + Vector2 direction = (player.transform.position - transform.position).normalized; + Direction = direction; + + // 스프라이트 방향 설정 + if (_spriteRenderer != null) + { + // 플레이어가 왼쪽에 있을 때 스프라이트를 반전 + _spriteRenderer.flipX = direction.x > 0; // 부등호 방향 변경 + } + } + else + { + Debug.LogWarning("플레이어를 찾을 수 없습니다!"); + Destroy(gameObject); + } + } + + private void OnTriggerEnter2D(Collider2D collision) + { + if (collision.CompareTag("Player") || collision.CompareTag("Ground")) + { + Destroy(gameObject); + } + } + + void SetDirection() + { + if (playerTransform == null) return; // 플레이어가 없으면 방향 설정 불가 + + Vector2 toPlayer = playerTransform.position - transform.position; // MonsterSkill과 Player의 위치 차이 계산 + + // 플레이어의 왼쪽/오른쪽 판별 + if (toPlayer.x < 0) + { + direction = new Vector2(-1, 0); // 플레이어가 왼쪽에 있으면 왼쪽 방향으로 발사 + } + else + { + direction = new Vector2(1, 0); // 플레이어가 오른쪽에 있으면 오른쪽 방향으로 발사 + _spriteRenderer.flipX = true; // 왼쪽 방향일 때 좌우 반전 + } + } + } + + +} diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkill.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkill.cs.meta new file mode 100644 index 00000000..9923ed38 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkill.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 190405d8d5d2c0e4683121e913af8457 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkillDataManager.cs b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkillDataManager.cs new file mode 100644 index 00000000..4e084e99 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkillDataManager.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace TON +{ + public class MonsterSkillDataManager : SingletonBase + { + // 전체 몬스터 스킬 데이터 리스트 + public List monstersSkillData { get; private set; } + + // 현재 선택된 몬스터 스킬 데이터 + public MonsterSkillData currentMonsterSkill { get; private set; } + + protected override void Awake() + { + base.Awake(); + LoadMonsterSkillData(); + } + + private void LoadMonsterSkillData() + { + monstersSkillData = JSONLoader.LoadFromResources>("MonsterSkills"); + if (monstersSkillData == null) + { + monstersSkillData = new List(); + Debug.LogError("몬스터 스킬 데이터 로드 실패"); + } + } + + public MonsterSkillData GetMonsterSkillData(int monsterSkillId) + { + if (monsterSkillId >= 0 && monsterSkillId < monstersSkillData.Count) + { + currentMonsterSkill = monstersSkillData[monsterSkillId]; + return currentMonsterSkill; + } + else + { + Debug.LogError($"유효하지 않은 몬스터 SkillID입니다: {monsterSkillId}"); + return null; + } + } + + public List GetAllMonsterSkillData() + { + return monstersSkillData; + } + } +} diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkillDataManager.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkillDataManager.cs.meta new file mode 100644 index 00000000..b982368b --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/MonsterSkillDataManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 517b06d480f28194b830fa1520a0a395 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/SkillPattern.cs b/Gameton-06/Assets/Gameton/Scripts/Monster/SkillPattern.cs new file mode 100644 index 00000000..d97711d4 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/SkillPattern.cs @@ -0,0 +1,130 @@ +using UnityEngine; + +namespace TON +{ + public abstract class SkillPattern + { + protected MonsterData _monsterData; + protected MonsterBase _monsterBase; + + protected SkillPattern(MonsterData monsterData, MonsterBase monsterBase) + { + _monsterData = monsterData; + _monsterBase = monsterBase; + } + + public bool IsAttackable { get; set; } + + public abstract void Attack(GameObject target); + + + public abstract void Update(); + } + + public class Monster1SkillPattern : SkillPattern + { + private float _skill1CoolTime; + private float _skill2CoolTime; + + private MonsterSkillData _monsterSkillData; + private MonsterSkillData _monsterSkillDataTwo; + + private MonsterSkill _skill1; + private MonsterSkill _skill2; + + private Vector3 _skillOffset = new Vector3(0, -0.5f, 0); // 스킬 생성 위치 조정값 + + public Monster1SkillPattern(MonsterData monsterData, MonsterBase monsterBase) : base(monsterData, monsterBase) + { + _monsterSkillData = MonsterSkillDataManager.Singleton.GetMonsterSkillData(_monsterData.monsterSkillID); + if (_monsterData.monsterSkillIDTwo > -1) + { + _monsterSkillDataTwo = MonsterSkillDataManager.Singleton.GetMonsterSkillData(_monsterData.monsterSkillIDTwo); + } + + if (_monsterSkillData != null && _monsterSkillDataTwo != null) + { + + Debug.Log($"몬스터 {_monsterSkillData.skillName} 데이터 로드 완료"); + Debug.Log($"몬스터 {_monsterSkillDataTwo.skillName} 데이터 로드 완료"); + + // 프리팹을 연결한 코드 + _skill1 = Resources.Load($"MonsterSkillPrefabs/{_monsterSkillData.skillName}"); + _skill2 = Resources.Load($"MonsterSkillPrefabs/{_monsterSkillDataTwo.skillName}"); + } + else + { + Debug.LogError($"몬스터 스킬 ID {_monsterSkillData.skillId}에 대한 데이터를 찾을 수 없습니다."); + Debug.LogError($"몬스터 스킬 ID {_monsterSkillDataTwo.skillId}에 대한 데이터를 찾을 수 없습니다."); + } + + _skill1CoolTime = Time.realtimeSinceStartup; + _skill2CoolTime = Time.realtimeSinceStartup; + + } + + public override void Attack(GameObject target) + { + if (target == null) return; + + // 스킬 스프라이트 방향 플레이어 바라보게 + _monsterBase.GetComponent().flipX = target.transform.position.x < _monsterBase.transform.position.x; + // 몬스터의 현재 위치에서 offset만큼 아래에 스킬 생성 + Vector3 spawnPosition = _monsterBase.transform.position - _skillOffset; + + // 프리팹을 지정된 위치에 생성 + Object.Instantiate(_skill1, spawnPosition, Quaternion.identity); + } + + public override void Update() + { + if (Time.realtimeSinceStartup - _skill1CoolTime >= _monsterSkillData.cooldown) + { + // TODO : 범위 체크 + IsAttackable = true; + } + + if (Time.realtimeSinceStartup - _skill2CoolTime >= _monsterSkillDataTwo.cooldown) + { + // TODO : 범위 체크 + IsAttackable = true; + } + } + } + + // public class Monster2AttackPattern : AttackPattern + // { + // + // + // public Monster2AttackPattern(MonsterBase monsterBase) : base(monsterBase) + // { + // + // } + // + // public override void Attack() + // { + // + // Skill1(); + // + // Skill2(); + // + // MeleeAttack(); + // + // } + // + // private void Skill1() + // { + // + // } + // + // private void Skill2() + // { + // + // } + // + // private void MeleeAttack() + // { + // _monsterBase.PlayerAttack(); + // } + // } +} diff --git a/Gameton-06/Assets/Gameton/Scripts/Monster/SkillPattern.cs.meta b/Gameton-06/Assets/Gameton/Scripts/Monster/SkillPattern.cs.meta new file mode 100644 index 00000000..d10e9f20 --- /dev/null +++ b/Gameton-06/Assets/Gameton/Scripts/Monster/SkillPattern.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55724230a1ec9b5418a40829c72b81fa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: