259 lines
6.4 KiB
C#
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);
|
|
}
|
|
} |