836 lines
26 KiB
C#
836 lines
26 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using Unity.VisualScripting;
|
|
using UnityEngine;
|
|
|
|
public class GamePole : MonoBehaviour
|
|
{
|
|
|
|
public GameManager gameManager;
|
|
|
|
public GameObject eLiters, eNums, ePole;
|
|
|
|
public GameObject[] ShipMass;
|
|
private List<GameObject> placedShips = new List<GameObject>();
|
|
|
|
public bool IsReady { get; private set; } = false;
|
|
|
|
GameObject[] Liters;
|
|
|
|
GameObject[] Nums;
|
|
|
|
public GameObject[,] Pole;
|
|
|
|
public int LengPole = 10;
|
|
|
|
public int[,] PoleShot; // 0 - íå ñòðåëÿë 1 - ïðîìàõ 2 - ðàíèë 3 - óíè÷òîæåí
|
|
|
|
public int[,] FreePole; // ïîëå äëÿ ðàñòîíîâêè êîðàáëåé
|
|
|
|
|
|
|
|
public Material hitMaterial;
|
|
|
|
|
|
private GameObject ghostShip = null;
|
|
private int ghostShipIndex = -1;
|
|
|
|
private int currentShipIndex = 0;
|
|
private int shipCaunt = 10;
|
|
|
|
/// <summary>Êîëè÷åñòâî êîðàáëåé â òåêóùåé êîíôèãóðàöèè.</summary>
|
|
public int ShipCount => shipCaunt;
|
|
|
|
/// <summary>Ìàñøòàá îäíîé êëåòêè (è êîðàáëåé) îòíîñèòåëüíî áàçîâîãî 10x10.</summary>
|
|
public float CellScale => _cellScale;
|
|
|
|
/// <summary>Òåêóùèé ìàñøòàá êëåòêè è êîðàáëåé (âû÷èñëÿåòñÿ â CreatePole).</summary>
|
|
private float _cellScale = 1f;
|
|
|
|
/// <summary>Ïîçèöèè ðèôîâ òåêóùåé èãðû — âîññòàíàâëèâàþòñÿ ïîñëå êàæäîãî ClearPole.</summary>
|
|
private readonly List<Vector2Int> _savedReefs = new List<Vector2Int>();
|
|
|
|
/// <summary>Ãðóïïû (ïðÿìîóãîëüíèêè) ðèôîâ äëÿ ïîâòîðíîãî ñïàâíà îáúåêòîâ.</summary>
|
|
private readonly List<RectInt> _savedReefGroups = new List<RectInt>();
|
|
|
|
/// <summary>Êîíôèã ðèôà äëÿ êàæäîé ãðóïïû — ïàðàëëåëüíûé ñïèñîê ê _savedReefGroups.</summary>
|
|
private readonly List<ReefConfig> _savedReefConfigs = new List<ReefConfig>();
|
|
|
|
/// <summary>Spawned 3D-îáúåêòû ðèôîâ — óíè÷òîæàþòñÿ ïðè Configure è ïåðåñîçäàþòñÿ â RestoreReefs.</summary>
|
|
private readonly List<GameObject> _spawnedReefObjects = new List<GameObject>();
|
|
|
|
|
|
public GameObject[] missEffectPrefabs; // ïðîìàõ
|
|
|
|
|
|
|
|
void Awake()
|
|
{
|
|
PoleShot = new int[LengPole, LengPole];
|
|
FreePole = new int[LengPole, LengPole];
|
|
if (gameManager == null)
|
|
gameManager = GetComponentInParent<GameManager>();
|
|
}
|
|
|
|
|
|
void Start()
|
|
{
|
|
CreatePole();
|
|
|
|
}
|
|
|
|
public Cell GetCell(int x, int y)
|
|
{
|
|
// Ïðîâåðÿåì, ÷òî ïîëå óæå ñîçäàíî
|
|
if (Pole == null) return null;
|
|
|
|
// Ïðîâåðÿåì êîððåêòíîñòü êîîðäèíàò
|
|
if (x < 0 || x >= LengPole || y < 0 || y >= LengPole) return null;
|
|
|
|
GameObject cellObject = Pole[x, y];
|
|
|
|
if (cellObject == null) return null;
|
|
|
|
return cellObject.GetComponent<Cell>();
|
|
}
|
|
public List<GameObject> GetPlacedShips()
|
|
{
|
|
return placedShips;
|
|
}
|
|
|
|
|
|
void CreatePole()
|
|
{
|
|
// 95% îò ðàçìåðà êëàññè÷åñêîãî 10x10, ÷òîáû îñòàâàëñÿ íåáîëüøîé îòñòóï
|
|
_cellScale = 9.5f / LengPole;
|
|
float cellScale = _cellScale;
|
|
|
|
float XX = cellScale;
|
|
float ZZ = -cellScale;
|
|
|
|
Liters = new GameObject[LengPole];
|
|
Nums = new GameObject[LengPole];
|
|
|
|
for (int i = 0; i < LengPole; i++)
|
|
{
|
|
Liters[i] = Instantiate(eLiters, transform);
|
|
Liters[i].transform.localPosition = new Vector3(XX, 0, 0);
|
|
Liters[i].transform.localScale = Vector3.one * cellScale;
|
|
Liters[i].GetComponent<Chanks>().Index = i;
|
|
XX += cellScale;
|
|
|
|
Nums[i] = Instantiate(eNums, transform);
|
|
Nums[i].transform.localPosition = new Vector3(0, 0, ZZ);
|
|
Nums[i].transform.localScale = Vector3.one * cellScale;
|
|
Nums[i].GetComponent<Chanks>().Index = i;
|
|
ZZ -= cellScale;
|
|
}
|
|
|
|
XX = cellScale;
|
|
ZZ = -cellScale;
|
|
|
|
Pole = new GameObject[LengPole, LengPole];
|
|
|
|
for (int Z = 0; Z < LengPole; Z++)
|
|
{
|
|
for (int X = 0; X < LengPole; X++)
|
|
{
|
|
Pole[X, Z] = Instantiate(ePole, transform);
|
|
Pole[X, Z].transform.localPosition = new Vector3(XX, 0, ZZ);
|
|
Pole[X, Z].transform.localScale = Vector3.one * cellScale;
|
|
XX += cellScale;
|
|
}
|
|
XX = cellScale;
|
|
ZZ -= cellScale;
|
|
}
|
|
}
|
|
public void Configure(int fieldSize, int shipCount)
|
|
{
|
|
// Ñáðîñ âñåõ äàííûõ ðèôîâ ïðè ñòàðòå íîâîé èãðû
|
|
_savedReefs.Clear();
|
|
_savedReefGroups.Clear();
|
|
_savedReefConfigs.Clear();
|
|
foreach (var o in _spawnedReefObjects) if (o != null) Destroy(o);
|
|
_spawnedReefObjects.Clear();
|
|
|
|
bool needRebuild = Pole == null || LengPole != fieldSize;
|
|
|
|
if (needRebuild)
|
|
{
|
|
DestroyGrid();
|
|
LengPole = fieldSize;
|
|
PoleShot = new int[LengPole, LengPole];
|
|
FreePole = new int[LengPole, LengPole];
|
|
CreatePole();
|
|
}
|
|
else
|
|
{
|
|
// Òîò æå ðàçìåð — ïðîñòî ñáðàñûâàåì ìàññèâû (ClearPole ñäåëàåò ýòî åù¸ ðàç, íå ñòðàøíî)
|
|
PoleShot = new int[LengPole, LengPole];
|
|
FreePole = new int[LengPole, LengPole];
|
|
}
|
|
|
|
shipCaunt = (ShipMass != null) ? Mathf.Min(shipCount, ShipMass.Length) : shipCount;
|
|
currentShipIndex = 0;
|
|
IsReady = false;
|
|
// placedShips — ÍÅ òðîãàåì çäåñü; ClearPole() (âíóòðè PrepareNewGame) óíè÷òîæèò èõ êîððåêòíî
|
|
}
|
|
|
|
private void DestroyGrid()
|
|
{
|
|
if (Liters != null) { foreach (var o in Liters) if (o != null) Destroy(o); Liters = null; }
|
|
if (Nums != null) { foreach (var o in Nums) if (o != null) Destroy(o); Nums = null; }
|
|
if (Pole != null) { foreach (var o in Pole) if (o != null) Destroy(o); Pole = null; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ðàçìåùàåò ðèôû ñîãëàñíî ìàññèâó ReefEntry[].
|
|
/// Êàæäûé entry — òèï ðèôà (ReefConfig) è ñêîëüêî øòóê ïîñòàâèòü.
|
|
/// Âûçûâàòü ÏÎÑËÅ ClearPole(), ÄÎ ðàññòàíîâêè êîðàáëåé.
|
|
/// </summary>
|
|
public void ApplyRandomReefs(BossLevelConfig.ReefEntry[] reefs)
|
|
{
|
|
_savedReefs.Clear();
|
|
_savedReefGroups.Clear();
|
|
_savedReefConfigs.Clear();
|
|
foreach (var o in _spawnedReefObjects) if (o != null) Destroy(o);
|
|
_spawnedReefObjects.Clear();
|
|
|
|
if (reefs == null) return;
|
|
|
|
foreach (var entry in reefs)
|
|
{
|
|
if (entry?.config == null) continue;
|
|
|
|
int w = Mathf.Max(1, entry.config.groupWidth);
|
|
int h = Mathf.Max(1, entry.config.groupHeight);
|
|
|
|
// Ðèô êðóïíåå ïîëÿ — ðàçìåñòèòü íåâîçìîæíî
|
|
if (LengPole < w || LengPole < h)
|
|
{
|
|
Debug.LogWarning($"[GamePole] Ðèô '{entry.config.name}': ðàçìåð ãðóïïû {w}x{h} áîëüøå ïîëÿ {LengPole}x{LengPole}.");
|
|
continue;
|
|
}
|
|
|
|
// Ñîáèðàåì âñå ñòàðòîâûå ïîçèöèè, ãäå ãðóïïà ñåé÷àñ ïîìåùàåòñÿ
|
|
var validPositions = new List<Vector2Int>();
|
|
for (int rx = 0; rx <= LengPole - w; rx++)
|
|
{
|
|
for (int ry = 0; ry <= LengPole - h; ry++)
|
|
{
|
|
bool ok = true;
|
|
for (int dx = 0; dx < w && ok; dx++)
|
|
for (int dy = 0; dy < h && ok; dy++)
|
|
if (FreePole[rx + dx, ry + dy] != 0) ok = false;
|
|
|
|
if (ok) validPositions.Add(new Vector2Int(rx, ry));
|
|
}
|
|
}
|
|
|
|
// Ïåðåìåøèâàåì — êàæäàÿ èãðà óíèêàëüíà
|
|
Shuffle(validPositions);
|
|
|
|
int placed = 0;
|
|
foreach (var pos in validPositions)
|
|
{
|
|
if (placed >= entry.count) break;
|
|
|
|
// Ïåðåïðîâåðÿåì: ïðåäûäóùèé ðàçìåù¸ííûé ðèô ìîã çàíÿòü ýòó ïîçèöèþ
|
|
bool canPlace = true;
|
|
for (int dx = 0; dx < w && canPlace; dx++)
|
|
for (int dy = 0; dy < h && canPlace; dy++)
|
|
if (FreePole[pos.x + dx, pos.y + dy] != 0) canPlace = false;
|
|
|
|
if (!canPlace) continue;
|
|
|
|
// Ðàçìåùàåì ãðóïïó
|
|
var group = new RectInt(pos.x, pos.y, w, h);
|
|
_savedReefGroups.Add(group);
|
|
_savedReefConfigs.Add(entry.config);
|
|
|
|
for (int dx = 0; dx < w; dx++)
|
|
for (int dy = 0; dy < h; dy++)
|
|
{
|
|
int cx = pos.x + dx, cy = pos.y + dy;
|
|
_savedReefs.Add(new Vector2Int(cx, cy));
|
|
FreePole[cx, cy] = 3;
|
|
PoleShot[cx, cy] = 1;
|
|
Pole[cx, cy]?.GetComponent<Cell>()?.ShowReef();
|
|
}
|
|
|
|
if (entry.config.prefab != null)
|
|
SpawnReefObject(group, entry.config);
|
|
|
|
placed++;
|
|
}
|
|
|
|
if (placed < entry.count)
|
|
Debug.LogWarning($"[GamePole] Ðèô '{entry.config.name}': ðàçìåùåíî {placed}/{entry.count} — " +
|
|
$"ïîëå ñëèøêîì çàíÿòî äëÿ ãðóïï {w}x{h}. Óìåíüøè count èëè ðàçìåð ãðóïï.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ñïàâíèò 3D-îáúåêò ðèôà â öåíòðå ãðóïïû êëåòîê.
|
|
/// Ìàñøòàá óìíîæàåòñÿ íà _cellScale äëÿ ïðîïîðöèè ñ ïîëåì.
|
|
/// </summary>
|
|
private void SpawnReefObject(RectInt group, ReefConfig config)
|
|
{
|
|
int x2 = Mathf.Min(group.x + group.width - 1, LengPole - 1);
|
|
int y2 = Mathf.Min(group.y + group.height - 1, LengPole - 1);
|
|
|
|
// Öåíòð ìåæäó ïåðâîé è ïîñëåäíåé êëåòêîé ãðóïïû
|
|
Vector3 topLeft = Pole[group.x, group.y].transform.localPosition;
|
|
Vector3 bottomRight = Pole[x2, y2].transform.localPosition;
|
|
Vector3 center = (topLeft + bottomRight) * 0.5f;
|
|
center.y = config.yOffset;
|
|
|
|
var obj = Instantiate(config.prefab, transform);
|
|
obj.transform.localPosition = center;
|
|
obj.transform.localScale = config.scale * _cellScale;
|
|
|
|
float rotY = config.randomRotationY
|
|
? Random.Range(0f, 360f)
|
|
: config.fixedRotationY;
|
|
obj.transform.localRotation = Quaternion.Euler(0f, rotY, 0f);
|
|
|
|
_spawnedReefObjects.Add(obj);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Âîññòàíàâëèâàåò ðèôû (êëåòêè + 3D-îáúåêòû) ïîñëå ClearPole.
|
|
/// Âûçûâàåòñÿ àâòîìàòè÷åñêè â êîíöå ClearPole.
|
|
/// </summary>
|
|
private void RestoreReefs()
|
|
{
|
|
// Óíè÷òîæàåì ñòàðûå îáúåêòû ïåðåä ïåðåñîçäàíèåì
|
|
foreach (var o in _spawnedReefObjects) if (o != null) Destroy(o);
|
|
_spawnedReefObjects.Clear();
|
|
|
|
// Âîññòàíàâëèâàåì êëåòêè
|
|
foreach (var pos in _savedReefs)
|
|
{
|
|
FreePole[pos.x, pos.y] = 3;
|
|
PoleShot[pos.x, pos.y] = 1;
|
|
Pole[pos.x, pos.y]?.GetComponent<Cell>()?.ShowReef();
|
|
}
|
|
|
|
// Ïåðåñîçäà¸ì 3D-îáúåêòû — êàæäàÿ ãðóïïà çíàåò ñâîé êîíôèã
|
|
for (int i = 0; i < _savedReefGroups.Count; i++)
|
|
{
|
|
var cfg = _savedReefConfigs[i];
|
|
if (cfg?.prefab != null)
|
|
SpawnReefObject(_savedReefGroups[i], cfg);
|
|
}
|
|
}
|
|
|
|
public List<(int x, int y)> GetAvailableShots() // ïîëó÷àåì äîñòóïíûå äëÿ âûñòðåëà ïîëÿ
|
|
{
|
|
var available = new List<(int, int)>();
|
|
for (int x = 0; x < LengPole; x++)
|
|
{
|
|
for (int y = 0; y < LengPole; y++)
|
|
{
|
|
if (PoleShot[x, y] == 0)
|
|
available.Add((x, y));
|
|
}
|
|
}
|
|
return available;
|
|
}
|
|
public int[] SearchWreckedShip() // èùåì êîðàáëè âàîêðóã
|
|
{
|
|
for (int x = 0; x < LengPole; x++)
|
|
{
|
|
for (int y = 0; y < LengPole; y++)
|
|
{
|
|
if (PoleShot[x, y] == 2)
|
|
{
|
|
// Ïðîâåðÿåì êëåòêè âîêðóã
|
|
if (HasFreeAdjacent( x, y))
|
|
return new int[] { x, y };
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private bool HasFreeAdjacent( int x, int y)
|
|
{
|
|
int[,] dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
|
|
foreach (var i in new int[] { 0, 1, 2, 3 })
|
|
{
|
|
int dx = x + dirs[i, 0];
|
|
int dy = y + dirs[i, 1];
|
|
if (dx >= 0 && dx < LengPole && dy >= 0 && dy < LengPole)
|
|
{
|
|
if (PoleShot[dx, dy] == 0)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool Shot(int x, int y)
|
|
{
|
|
if (PoleShot[x, y] != 0) return true; // çàòû÷êà
|
|
bool hit = Pole[x, y].GetComponent<Cell>().hit();
|
|
|
|
if (hit)
|
|
{
|
|
var cell = Pole[x, y].GetComponent<Cell>();
|
|
if (cell != null && cell.deck != null)
|
|
{
|
|
PoleShot[x, y] = 2;
|
|
gameManager.playerCamera.GetComponent<CameraShake>().Shake(0.3f, 0.2f);
|
|
var ship = cell.deck.GetComponentInParent<Ship>();
|
|
if (ship != null && ship.IsDestroyed())
|
|
{
|
|
HitAroundShip(ship);
|
|
ship.Destroy();
|
|
|
|
bool isPlayer = this == gameManager.playerField;
|
|
// gameManager.ShipDestroyed(isPlayer);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PoleShot[x, y] = 1;
|
|
if (missEffectPrefabs != null && missEffectPrefabs.Length > 0)
|
|
{
|
|
Vector3 spawnPos = Pole[x, y].transform.position;
|
|
|
|
// âûáèðàåì ñëó÷àéíûé ýëåìåíò
|
|
GameObject prefab = missEffectPrefabs[Random.Range(0, missEffectPrefabs.Length)];
|
|
|
|
if (prefab != null)
|
|
{
|
|
GameObject effect = Instantiate(prefab, spawnPos, Quaternion.identity);
|
|
|
|
// Àâòîìàòè÷åñêè óíè÷òîæàåì ÷åðåç 2 ñåêóíäû
|
|
Destroy(effect, 2f);
|
|
}
|
|
}
|
|
|
|
if (EffectManager.Instance != null)
|
|
{
|
|
Vector3 basePos = Pole[x, y].transform.position;
|
|
|
|
// Ñëó÷àéíîå ñìåùåíèå: ïî Y îò 5 äî 10, ïî X îò -1 äî 1
|
|
float randomY = Random.Range(7f, 14f);
|
|
float randomX = Random.Range(-2f, 2f);
|
|
|
|
Vector3 spawnPos = basePos + new Vector3(randomX, randomY, 0f);
|
|
GameObject textFx = EffectManager.Instance.PlayMissText(spawnPos);
|
|
|
|
if (textFx != null)
|
|
{
|
|
// Ñëó÷àéíûé ìàñøòàá äëÿ ðàçíîîáðàçèÿ
|
|
float scale = Random.Range(3f, 4f);
|
|
textFx.transform.localScale *= scale;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
return hit;
|
|
|
|
}
|
|
// îáâäèì êîðàáëü
|
|
void HitAroundShip(Ship ship)
|
|
{
|
|
foreach (var coord in ship.deckCoords)
|
|
{
|
|
for (int dx = -1; dx <= 1; dx++)
|
|
{
|
|
for (int dy = -1; dy <= 1; dy++)
|
|
{
|
|
int nx = coord.x + dx;
|
|
int ny = coord.y + dy;
|
|
|
|
if (nx >= 0 && nx < LengPole && ny >= 0 && ny < LengPole)
|
|
{
|
|
if (dx == 0 && dy == 0)
|
|
{
|
|
PoleShot[nx, ny] = 3; // êîðàáëü óáèò
|
|
continue;
|
|
}
|
|
|
|
// Ðèô — íå çàêðàøèâàåì, ÷òîáû íå íàêëàäûâàëèñü ñïðàéòû
|
|
if (FreePole[nx, ny] == 3) continue;
|
|
|
|
var cell = Pole[nx, ny].GetComponent<Cell>();
|
|
if (cell != null)
|
|
{
|
|
PoleShot[nx, ny] = 1;
|
|
cell.hit();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void ClearPole()
|
|
{
|
|
ClearGhost();
|
|
|
|
foreach (var ship in placedShips)
|
|
{
|
|
if (ship != null)
|
|
Destroy(ship);
|
|
}
|
|
placedShips.Clear();
|
|
currentShipIndex = 0;
|
|
IsReady = false;
|
|
|
|
for (int x = 0; x < LengPole; x++)
|
|
{
|
|
for (int y = 0; y < LengPole; y++)
|
|
{
|
|
if (Pole[x, y] != null)
|
|
{
|
|
var cell = Pole[x, y].GetComponent<Cell>();
|
|
if (cell != null)
|
|
{
|
|
cell.deck = null;
|
|
cell.HideAll();
|
|
}
|
|
}
|
|
|
|
FreePole[x, y] = 0;
|
|
PoleShot[x, y] = 0;
|
|
}
|
|
}
|
|
|
|
RestoreReefs(); // ðèôû âîññòàíàâëèâàþòñÿ ñðàçó ïîñëå î÷èñòêè
|
|
}
|
|
|
|
// ïðîâåðÿåìñ ñâîáîäíû ëè êëåòêè
|
|
bool CanPlaceShip(int[,] field, int start_x, int start_y, int length, Direction dir)
|
|
{
|
|
int dx = 0, dy = 0;
|
|
|
|
switch (dir)
|
|
{
|
|
case Direction.Left: dx = -1; break;
|
|
case Direction.Right: dx = 1; break;
|
|
case Direction.Up: dy = -1; break;
|
|
case Direction.Down: dy = 1; break;
|
|
}
|
|
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
int x = start_x + dx * i;
|
|
int y = start_y + dy * i;
|
|
|
|
if (x < 0 || x >= LengPole || y < 0 || y >= LengPole) return false;
|
|
if (field[x, y] != 0) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool PlaceShipManual(int x, int y, Direction direction)
|
|
{
|
|
if (currentShipIndex >= shipCaunt)
|
|
return false;
|
|
GameObject shipPrefab = ShipMass[currentShipIndex];
|
|
|
|
int size = shipPrefab.GetComponent<Ship>().decks.Count;
|
|
|
|
if (!CanPlaceShip(FreePole, x, y, size, direction))
|
|
return false;
|
|
|
|
GameObject ship = Instantiate(shipPrefab, transform);
|
|
ship.SetActive(true);
|
|
ship.transform.localScale *= _cellScale;
|
|
switch (direction)
|
|
{
|
|
case Direction.Left: ship.transform.localRotation = Quaternion.Euler(0, 0, 0); break;
|
|
case Direction.Right: ship.transform.localRotation = Quaternion.Euler(0, 180, 0); break;
|
|
case Direction.Up: ship.transform.localRotation = Quaternion.Euler(0, 90, 0); break;
|
|
case Direction.Down: ship.transform.localRotation = Quaternion.Euler(0, 270, 0); break;
|
|
}
|
|
|
|
Vector3 basePos = Pole[x, y].transform.localPosition;
|
|
ship.transform.localPosition = new Vector3(basePos.x, basePos.y - 0.1f, basePos.z);
|
|
|
|
int end_x = x + (direction == Direction.Left ? -size + 1 :
|
|
direction == Direction.Right ? size - 1 : 0);
|
|
int end_y = y + (direction == Direction.Up ? -size + 1 :
|
|
direction == Direction.Down ? size - 1 : 0);
|
|
|
|
PlaceShip(FreePole, ship, x, y, end_x, end_y);
|
|
placedShips.Add(ship);
|
|
|
|
ClearGhost(); // óáèðàåì ïðèçðàê
|
|
|
|
currentShipIndex++;
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ShowShipGhost(int x, int y, Direction direction)
|
|
{
|
|
if(currentShipIndex >= shipCaunt) return;
|
|
|
|
int size = ShipMass[currentShipIndex].GetComponent<Ship>().decks.Count;
|
|
|
|
if (!CanPlaceShip(FreePole, x, y, size, direction))
|
|
{
|
|
if (ghostShip != null) ghostShip.SetActive(false); // ïðîñòî ñêðûâàåì
|
|
return;
|
|
}
|
|
|
|
// Åñëè óæå ñîçäàí ïðèçðàê íóæíîãî òèïà — ïðîñòî îáíîâëÿåì ïîçèöèþ
|
|
if (ghostShip != null && ghostShipIndex == currentShipIndex)
|
|
{
|
|
ghostShip.SetActive(true); // âäðóã áûë ñêðûò
|
|
}
|
|
else
|
|
{
|
|
if (ghostShip != null)
|
|
Destroy(ghostShip);
|
|
|
|
ghostShip = Instantiate(ShipMass[currentShipIndex], transform);
|
|
ghostShipIndex = currentShipIndex;
|
|
ghostShip.transform.localScale *= _cellScale;
|
|
|
|
foreach (Collider col in ghostShip.GetComponentsInChildren<Collider>())
|
|
col.enabled = false;
|
|
|
|
foreach (Renderer renderer in ghostShip.GetComponentsInChildren<Renderer>())
|
|
renderer.material.color = new Color(1f, 1f, 1f, 0.3f); // ïîëóïðîçðà÷íûé
|
|
}
|
|
|
|
// Ïîâîðîò
|
|
switch (direction)
|
|
{
|
|
case Direction.Left: ghostShip.transform.localRotation = Quaternion.Euler(0, 0, 0); break;
|
|
case Direction.Right: ghostShip.transform.localRotation = Quaternion.Euler(0, 180, 0); break;
|
|
case Direction.Up: ghostShip.transform.localRotation = Quaternion.Euler(0, 90, 0); break;
|
|
case Direction.Down: ghostShip.transform.localRotation = Quaternion.Euler(0, 270, 0); break;
|
|
}
|
|
|
|
Vector3 basePos = Pole[x, y].transform.localPosition;
|
|
ghostShip.transform.localPosition = new Vector3(basePos.x, basePos.y - 0.1f, basePos.z);
|
|
}
|
|
|
|
|
|
public void ClearGhost()
|
|
{
|
|
if (ghostShip != null)
|
|
{
|
|
Destroy(ghostShip);
|
|
ghostShip = null;
|
|
ghostShipIndex = -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ðàñòàâëÿåì êîðàáëè
|
|
public void ArrangeShip(bool hideShips = false)
|
|
{
|
|
ClearPole();
|
|
|
|
int count = Mathf.Min(shipCaunt, ShipMass != null ? ShipMass.Length : 0);
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
GameObject shipPrefab = ShipMass[i];
|
|
GameObject ship = Instantiate(shipPrefab);
|
|
ship.transform.SetParent(this.transform, false);
|
|
ship.SetActive(true);
|
|
ship.transform.localScale *= _cellScale;
|
|
placedShips.Add(ship);
|
|
|
|
if (hideShips)
|
|
{
|
|
foreach (Renderer r in ship.GetComponentsInChildren<Renderer>())
|
|
r.enabled = false;
|
|
}
|
|
|
|
int quantity = ship.GetComponent<Ship>().decks.Count;
|
|
|
|
// Ãåíåðèðóåì ñïèñîê âñåõ âîçìîæíûõ ïîçèöèé
|
|
List<(int x, int y, Direction dir)> possiblePlacements = new();
|
|
|
|
for (int x = 0; x < LengPole; x++)
|
|
{
|
|
for (int y = 0; y < LengPole; y++)
|
|
{
|
|
foreach (Direction direction in System.Enum.GetValues(typeof(Direction)))
|
|
{
|
|
if (CanPlaceShip(FreePole, x, y, quantity, direction))
|
|
possiblePlacements.Add((x, y, direction));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Åñëè íåò íè îäíîãî ïîäõîäÿùåãî ìåñòà
|
|
if (possiblePlacements.Count == 0)
|
|
{
|
|
Debug.LogWarning("Íå óäàëîñü ðàçìåñòèòü êîðàáëü, ïåðåçàïóñêàåì ðàññòàíîâêó.");
|
|
ArrangeShip(hideShips);
|
|
continue;
|
|
}
|
|
|
|
// Ïåðåìåøèâàåì âîçìîæíûå ïîçèöèè
|
|
Shuffle(possiblePlacements);
|
|
|
|
// Áåðåì ïåðâóþ ïîäõîäÿùóþ
|
|
var (start_x, start_y, dir) = possiblePlacements[0];
|
|
|
|
switch (dir)
|
|
{
|
|
case Direction.Left: ship.transform.localRotation = Quaternion.Euler(0, 0, 0); break;
|
|
case Direction.Right: ship.transform.localRotation = Quaternion.Euler(0, 180, 0); break;
|
|
case Direction.Up: ship.transform.localRotation = Quaternion.Euler(0, 90, 0); break;
|
|
case Direction.Down: ship.transform.localRotation = Quaternion.Euler(0, 270, 0); break;
|
|
}
|
|
|
|
Vector3 basePos = Pole[start_x, start_y].transform.localPosition;
|
|
ship.transform.localPosition = new Vector3(basePos.x, basePos.y - 0.1f, basePos.z);
|
|
|
|
int end_x = start_x + (dir == Direction.Left ? -quantity + 1 :
|
|
dir == Direction.Right ? quantity - 1 : 0);
|
|
int end_y = start_y + (dir == Direction.Up ? -quantity + 1 :
|
|
dir == Direction.Down ? quantity - 1 : 0);
|
|
|
|
PlaceShip(FreePole, ship, start_x, start_y, end_x, end_y);
|
|
}
|
|
|
|
currentShipIndex = count; // âñå êîðàáëè ðàññòàâëåíû — ðó÷íàÿ ðàññòàíîâêà çàáëîêèðîâàíà
|
|
IsReady = true;
|
|
}
|
|
|
|
void Shuffle<T>(List<T> list)
|
|
{
|
|
for (int i = list.Count - 1; i > 0; i--)
|
|
{
|
|
int j = Random.Range(0, i + 1);
|
|
(list[i], list[j]) = (list[j], list[i]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// òóò ðàñòàâëÿþòñÿ êîðàáëè
|
|
void PlaceShip(int[,] FreePole, GameObject ship, int start_x, int start_y, int end_x, int end_y)
|
|
{
|
|
var decks = ship.GetComponent<Ship>().decks;
|
|
int deckIndex = 0;
|
|
|
|
if (start_x != end_x)
|
|
{
|
|
int step = start_x < end_x ? 1 : -1;
|
|
|
|
for (; start_x != end_x + step; start_x += step)
|
|
{
|
|
SetDeckAndAround(FreePole, start_x, start_y, decks[deckIndex]);
|
|
ship.GetComponent<Ship>().AddDeckCoord(start_x, start_y);
|
|
deckIndex++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int step = start_y < end_y ? 1 : -1;
|
|
|
|
for (; start_y != end_y + step; start_y += step)
|
|
{
|
|
SetDeckAndAround(FreePole, start_x, start_y, decks[deckIndex]);
|
|
ship.GetComponent<Ship>().AddDeckCoord(start_x, start_y);
|
|
deckIndex++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// òóò óñòàíàâëèâàåì ïàëóáû è ñâîáîäíîå ïîëå äåëàåì íå ñâîáîäíûì
|
|
void SetDeckAndAround(int[,] FreePole, int x, int y, GameObject deck)
|
|
{
|
|
FreePole[x, y] = 1;
|
|
|
|
// Ïðèâÿçêà ïàëóáû ê êëåòêå
|
|
Pole[x, y].GetComponent<Cell>().deck = deck; // TODU íàäî ïðèäóìàòü ÷òî-òî ïîóìíåå
|
|
|
|
deck.SetActive(true);
|
|
|
|
for (int dx = -1; dx <= 1; dx++)
|
|
{
|
|
for (int dy = -1; dy <= 1; dy++)
|
|
{
|
|
int nx = x + dx;
|
|
int ny = y + dy;
|
|
|
|
if (nx >= 0 && nx < LengPole && ny >= 0 && ny < LengPole && FreePole[nx, ny] == 0)
|
|
{
|
|
FreePole[nx, ny] = 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// òóò êîïèðóåì êîðàáëè
|
|
|
|
public void CopyShipsFrom(GamePole sourceField, bool hideShips = true)
|
|
{
|
|
ClearPole();
|
|
|
|
foreach (var originalShip in sourceField.placedShips)
|
|
{
|
|
GameObject copy = Instantiate(originalShip);
|
|
|
|
// Äåëàåì êîïèþ äî÷åðíèì îáúåêòîì òåêóùåãî ïîëÿ
|
|
copy.transform.SetParent(this.transform, false);
|
|
|
|
// Êîïèðóåì ËÎÊÀËÜÍÛÅ êîîðäèíàòû, ÷òîáû êîðàáëè âñòàëè íà ñåòêó ïîëÿ
|
|
copy.transform.localPosition = originalShip.transform.localPosition;
|
|
copy.transform.localRotation = originalShip.transform.localRotation;
|
|
|
|
if (hideShips)
|
|
{
|
|
foreach (Renderer r in copy.GetComponentsInChildren<Renderer>())
|
|
r.enabled = false;
|
|
}
|
|
|
|
placedShips.Add(copy);
|
|
|
|
var ship = copy.GetComponent<Ship>();
|
|
var sourceShip = originalShip.GetComponent<Ship>();
|
|
|
|
for (int i = 0; i < sourceShip.deckCoords.Count; i++)
|
|
{
|
|
var coord = sourceShip.deckCoords[i];
|
|
Pole[coord.x, coord.y].GetComponent<Cell>().deck = ship.decks[i];
|
|
ship.AddDeckCoord(coord.x, coord.y);
|
|
}
|
|
}
|
|
|
|
IsReady = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|