Files
2026-08-03 22:34:03 +03:00

259 lines
6.4 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
public class PlayerMovement : MonoBehaviour
{
Rigidbody2D rb;
public AudioClip attackSound;
private AudioSource audioSource;
private Animator anim;
public float speed = 5f;
public float minX = -15f;
public float maxX = 15f;
public float minY = -15f;
public float maxY = 15f;
public GameObject attackEffect;
public float invincibilityTimeStart = 1.5f;
public float invincibilityTimeMid = 2.5f;
public float invincibilityTimeLow = 3.5f;
public float surviveTime = 999f;
private float currentTime;
private bool isGameOver = false;
private bool isWin = false;
public int maxHits = 3;
private int currentHits = 0;
public float knockbackForce = 2f;
private bool isInvincible = false;
public GameObject[] hearts;
public int maxHP = 3;
private int currentHP;
private bool facingRight = true;
public AudioClip footstepSound;
Vector2 input;
void Start()
{
anim = GetComponent<Animator>();
audioSource = GetComponent<AudioSource>();
currentTime = surviveTime;
currentHP = maxHP;
UpdateHPUI();
rb = GetComponent<Rigidbody2D>();
}
void UpdateHPUI()
{
for (int i = 0; i < hearts.Length; i++)
{
hearts[i].SetActive(i < currentHP);
}
}
void Update()
{
if (isGameOver) return;
currentTime -= Time.deltaTime;
if (currentTime <= 0f)
{
currentTime = 0f;
isWin = true;
return;
}
// движение
float moveX = 0f;
float moveY = 0f;
if (Input.GetKey(KeyCode.A)) moveX = -1f;
if (Input.GetKey(KeyCode.D)) moveX = 1f;
if (Input.GetKey(KeyCode.W)) moveY = 1f;
if (Input.GetKey(KeyCode.S)) moveY = -1f;
input = new Vector2(moveX, moveY);
bool isMoving = moveX != 0 || moveY != 0;
anim.SetBool("isMoving", isMoving);
if (moveX > 0)
{
facingRight = true;
}
else if (moveX < 0)
{
facingRight = false;
}
transform.localScale = new Vector3(facingRight ? 1 : -1, 1, 1);
//Vector3 move = new Vector3(moveX, moveY, 0f);
//Vector3 newPosition = transform.position + move * speed * Time.deltaTime;
SpriteRenderer sr = GetComponent<SpriteRenderer>();
float halfWidth = sr.bounds.extents.x;
float halfHeight = sr.bounds.extents.y;
//newPosition.x = Mathf.Clamp(newPosition.x, minX, maxX);
// newPosition.y = Mathf.Clamp(newPosition.y, minY, maxY);
// rb.MovePosition(newPosition);
// атака
if (Input.GetKeyDown(KeyCode.Space))
{
Attack();
}
}
void FixedUpdate()
{
Vector2 newPosition = rb.position + input * speed * Time.fixedDeltaTime;
newPosition.x = Mathf.Clamp(newPosition.x, minX, maxX);
newPosition.y = Mathf.Clamp(newPosition.y, minY, maxY);
rb.MovePosition(newPosition);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Enemy") && !isInvincible)
{
TakeHit(other.transform);
}
}
void TakeHit(Transform enemy)
{
currentHP--;
currentHits++;
UpdateHPUI();
// отталкивание
Vector2 direction = (transform.position - enemy.position).normalized;
//transform.position += (Vector3)(direction * knockbackForce);
rb.MovePosition(rb.position + direction * knockbackForce);
// мигание
StartCoroutine(HitFlash());
// неуязвимость на время
StartCoroutine(Invincibility());
if (currentHits >= maxHits)
{
isGameOver = true;
FindAnyObjectByType<GameManager>().EndGame(false);
}
if(currentHP <=0)
{
isGameOver = true;
FindObjectOfType<GameManager>().EndGame(false);
}
}
IEnumerator Invincibility()
{
isInvincible = true;
float time = invincibilityTimeStart;
if (currentHP == 2)
time = invincibilityTimeMid;
else if(currentHP == 1)
time= invincibilityTimeLow;
yield return new WaitForSeconds(time);
isInvincible = false;
}
IEnumerator HitFlash()
{
SpriteRenderer sr = GetComponent<SpriteRenderer>();
Color original = sr.color;
sr.color = Color.red;
yield return new WaitForSeconds(0.1f);
sr.color = original;
}
void Attack()
{
anim.SetTrigger("Attack");
if (attackSound != null)
audioSource.PlayOneShot(attackSound, 0.07f);
Vector2 direction = Vector2.right;
if (Input.GetKey(KeyCode.A)) direction = Vector2.left;
if (Input.GetKey(KeyCode.D)) direction = Vector2.right;
if (Input.GetKey(KeyCode.W)) direction = Vector2.up;
if (Input.GetKey(KeyCode.S)) direction = Vector2.down;
// нормальный хитбокс
RaycastHit2D[] hits = Physics2D.BoxCastAll(
transform.position,
new Vector2(1f, 1f),
0f,
direction,
1.5f
);
foreach (var hit in hits)
{
if (hit.collider.CompareTag("Enemy"))
{
hit.collider.GetComponent<Enemy>()?.TakeDamage(1);
}
}
// эффекты
//StartCoroutine(AttackAnimation());
//ShowAttackEffect();
Debug.DrawRay(transform.position, direction * 1.5f, Color.red, 0.2f);
}
IEnumerator AttackAnimation()
{
Vector3 originalScale = transform.localScale;
transform.localScale = originalScale * 1.3f;
yield return new WaitForSeconds(0.1f);
transform.localScale = originalScale;
}
void ShowAttackEffect()
{
if (attackEffect == null) return;
GameObject effect = Instantiate(attackEffect, transform.position, Quaternion.identity);
effect.transform.localScale = Vector3.one * 2f;
Destroy(effect, 0.2f);
}
// звук ходьбы
void PlayFootstep()
{
if (footstepSound != null)
audioSource.PlayOneShot(footstepSound, 0.05f);
}
}