using System.Collections;
using UnityEngine;
public class Tank : MonoBehaviour
{
[SerializeField] GameObject indicator;
[SerializeField] GameObject explosionPrefab;
[SerializeField] Sprite tank_mode;
[SerializeField] Sprite siege_mode;
public LayerMask enemyLayer;
[SerializeField] float tank_mode_attack_range = 3f;
[SerializeField] float siege_mode_attack_range = 5f;
[SerializeField] float splashRange = 2f;
public float speed = 5.0f;
private Vector3 targetPosition;
private bool isMoving = false;
private bool isSiege = false;
private Camera mainCamera;
private Vector3 currentMousePosition;
void Start()
{
indicator.SetActive(false);
StartCoroutine(CoMove());
StartCoroutine(ChangeMode());
mainCamera = Camera.main;
}
void Update()
{
// 마우스 위치를 월드 좌표계로 변환하여 저장
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
currentMousePosition = mousePosition;
if (Input.GetKey(KeyCode.A))
{
if(Input.GetMouseButtonDown(0) && isSiege)
{
StartCoroutine("CoSiegeAttack");
}
else if (Input.GetMouseButtonDown(0) && !isSiege)
{
StartCoroutine("CoAttack");
}
}
}
IEnumerator CoMove()
{
while (true)
{
if (Input.GetMouseButtonDown(1) && !isSiege)
{
targetPosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);
targetPosition.z = transform.position.z;
StopCoroutine(MoveIndicator(targetPosition));
StartCoroutine(MoveIndicator(targetPosition));
if (transform.position.x < targetPosition.x) this.gameObject.transform.localScale = new Vector3(1, 1, 1);
else this.gameObject.transform.localScale = new Vector3(-1, 1, 1);
isMoving = true;
}
if (isMoving && !isSiege)
{
transform.position = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.deltaTime);
if (Vector3.Distance(transform.position, targetPosition) < 0.01f)
{
isMoving = false;
}
}
yield return null;
}
}
IEnumerator ChangeMode()
{
while (true)
{
if (Input.GetKeyDown(KeyCode.O))
{
isSiege = !isSiege;
GetComponent<SpriteRenderer>().sprite = isSiege ? siege_mode : tank_mode;
isMoving = false;
}
yield return null;
}
}
IEnumerator MoveIndicator(Vector3 position)
{
indicator.SetActive(true);
indicator.transform.position = position;
yield return new WaitForSeconds(0.5f);
indicator.SetActive(false);
}
IEnumerator CoAttack()
{
Vector3 mousePosition = mainCamera.ScreenToWorldPoint(Input.mousePosition);
Collider2D clickedCollider = Physics2D.OverlapPoint(mousePosition, enemyLayer);
if (clickedCollider != null)
{
float distance = Vector2.Distance(transform.position, clickedCollider.transform.position);
if (!isSiege && distance <= tank_mode_attack_range)
{
Instantiate(explosionPrefab, clickedCollider.transform.position, Quaternion.identity);
Destroy(clickedCollider.gameObject);
isMoving = false;
}
}
yield return null;
}
IEnumerator CoSiegeAttack()
{
// 마우스 위치를 월드 좌표로 변환
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
// splashRange 내에 있는 모든 적 탐지
Collider2D[] enemies = Physics2D.OverlapCircleAll(mousePosition, splashRange, enemyLayer);
foreach (Collider2D enemy in enemies)
{
// 폭발 이펙트 생성 및 적 파괴
Instantiate(explosionPrefab, enemy.transform.position, Quaternion.identity);
Destroy(enemy.gameObject);
}
yield return null;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, isSiege ? siege_mode_attack_range : tank_mode_attack_range);
if (Input.GetKey(KeyCode.A) && isSiege)
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(currentMousePosition, splashRange);
}
}
}
Tank.cs
Enemy는 Layer를 Enemy로 설정해주자.
반응형
'산대특 > 게임 플랫폼 응용 프로그래밍' 카테고리의 다른 글
화면을 클릭할때까지 기다리다가 2초마다 "대기중" 이라고 출력하고, 화면을 클릭하면 "완료" 라고 출력하기 (0) | 2024.02.29 |
---|---|
코루틴 안에서 코루틴 실행하기 (0) | 2024.02.29 |
탱크 공격 과 폭발 이펙트 + 적 삭제 구현하기 (0) | 2024.02.29 |
탱크 이동과 모드 전환 구현하기 (0) | 2024.02.29 |
[Zombero] Boss Stage 만들기 (0) | 2024.02.29 |