PacMan/Assets/Scripts/RedGhost.cs

181 lines
4.9 KiB
C#
Raw Normal View History

using System;
2025-03-17 21:56:02 +08:00
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
2025-03-17 21:56:02 +08:00
using UnityEngine;
using UnityEngine.UIElements;
2025-03-17 21:56:02 +08:00
public class RedGhost : MonoBehaviour
{
// ========== ״̬ö<CCAC><C3B6> ==========
public enum GhostState
2025-03-17 21:56:02 +08:00
{
Idle, //<2F><><EFBFBD>ֵĴ<D6B5><C4B4><EFBFBD>
Start, //<2F><EFBFBD><EBBFAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Chase, // ׷<><D7B7>ģʽ
Frightened, // <20>־<EFBFBD>ģʽ,<2C><><EFBFBD><EFBFBD>
Die // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
2025-03-17 21:56:02 +08:00
}
public GhostState curstate;//<2F><>ǰö<C7B0><C3B6>
2025-03-17 21:56:02 +08:00
[Header("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public Rigidbody2D rb;
public Animator anim;
public GameObject pacMan;//<2F>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
public LayerMask obstadeLayer;//ǽ<>IJ㼶
[Header("׷<><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><EFBFBD><EFBFBD>")]
private Vector2 currentDirection; //<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߲<EFBFBD><DFB2><EFBFBD>
[Header("<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>")]
public float castDistance = 1f; // <20><><EFBFBD>߼<EFBFBD><DFBC><EFBFBD><E2B3A4>
public float boxWidth = 0.3f; // <20><><EFBFBD>߿<EFBFBD><DFBF><EFBFBD>
public Color validColor = Color.green; // <20><>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
public Color blockedColor = Color.red; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
public float speed;//<2F><><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>
public float frightenedSpeed;//<2F><><EFBFBD><EFBFBD><EFBFBD>ٶ<EFBFBD>
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
// anim = GetComponent<Animator>();
pacMan = GameObject.Find("PacManPlayer");//<2F>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD>
}
private void Update()
{
switch (curstate)
{
case GhostState.Idle:
Idle();
break;
case GhostState.Start:
GhostStart();
break;
case GhostState.Chase:
Chase();
break;
case GhostState.Frightened:
Frightened();
break;
case GhostState.Die:
Die();
break;
}
}
private void Idle()
{
curstate = GhostState.Chase;
}
private void GhostStart()
{
throw new NotImplementedException();
}
private void Chase()
2025-03-17 21:56:02 +08:00
{
UpdateMovement(pacMan.transform.position, true);
}
private void Frightened()
{
throw new NotImplementedException();
}
private void Die()
{
throw new NotImplementedException();
}
// <20><><EFBFBD><EFBFBD><EFBFBD>ƶ<EFBFBD><C6B6>߼<EFBFBD><DFBC><EFBFBD>׷<EFBFBD><D7B7>/<2F><><EFBFBD>ܹ<EFBFBD><DCB9>ã<EFBFBD>
private void UpdateMovement(Vector2 targetPos, bool isChasing)
{
Vector2[] directions = { Vector2.up, Vector2.down, Vector2.left, Vector2.right };
Vector2 bestDir = Vector2.zero;
float bestValue = isChasing ? Mathf.Infinity : -Mathf.Infinity;//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>󣬸<EFBFBD><F3A3ACB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
foreach (Vector2 dir in directions)
{
if (dir == -currentDirection) continue; // ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ǰ<EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD>򣬼<EFBFBD><F2A3ACBC><EFBFBD>ִ<EFBFBD>У<EFBFBD><D0A3><EFBFBD>ֱֹ<D6B9>ӻ<EFBFBD>ͷ
// ʹ<><CAB9>BoxCast<73><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool isBlocked = Physics2D.BoxCast(transform.position,GetBoxSize(dir),0f,dir,castDistance,obstadeLayer);
if (isBlocked) continue;
// <20><><EFBFBD><EFBFBD><E3B7BD><EFBFBD><EFBFBD>ֵ
float distance = Vector2.Distance(rb.position + dir, targetPos);//<2F><>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ֵ
float currentValue = isChasing ? distance : -distance;//<2F><>׷<EFBFBD><D7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if ((isChasing && currentValue < bestValue) || (!isChasing && currentValue > bestValue))
{
bestValue = currentValue;
bestDir = dir;
}
}
if (bestDir != Vector2.zero)
{
currentDirection = bestDir;
rb.velocity = currentDirection.normalized * (curstate == GhostState.Frightened ? frightenedSpeed : speed) * Time.deltaTime;
}
2025-03-17 21:56:02 +08:00
}
// <20><><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD>ߺ<EFBFBD><DFBA>ӳߴ<D3B3>
private Vector2 GetBoxSize(Vector2 direction)
{
return new Vector2(
direction.x = boxWidth,
direction.y = boxWidth
);
}
// <20><><EFBFBD>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD>
private void OnDrawGizmos()
{
if (!Application.isPlaying) return;
foreach (Vector2 dir in new[] { Vector2.up, Vector2.down, Vector2.left, Vector2.right })
{
Gizmos.color = Physics2D.BoxCast(transform.position, GetBoxSize(dir), 0f, dir, castDistance, obstadeLayer)
? blockedColor
: validColor;
DrawBoxCastGizmo(
transform.position,
dir,
GetBoxSize(dir),
castDistance
);
}
}
// <20><><EFBFBD>ƺ<EFBFBD><C6BA><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
private void DrawBoxCastGizmo(Vector2 origin, Vector2 direction, Vector2 size, float distance)
{
Vector2 endPos = origin + direction * distance;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5>ĺ<EFBFBD><C4BA><EFBFBD>
Gizmos.DrawWireCube(origin, size);
Gizmos.DrawWireCube(endPos, size);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Vector2 perpendicular = new Vector2(-direction.y, direction.x) * size.x / 2;
Vector2 edge1 = origin + perpendicular;
Vector2 edge2 = origin - perpendicular;
Gizmos.DrawLine(edge1, edge1 + direction * distance);
Gizmos.DrawLine(edge2, edge2 + direction * distance);
}
2025-03-17 21:56:02 +08:00
}