using System.Collections; using System.Collections.Generic; using UnityEngine; using Fusion; using OnlyScove.Scripts.GameSetup.Maze; public class MapLocation { public int x; public int z; public MapLocation(int _x, int _z) { x = _x; z = _z; } } public class Maze : NetworkBehaviour { public List directions = new List() { new MapLocation(1,0), new MapLocation(0,1), new MapLocation(-1,0), new MapLocation(0,-1) }; public int width = 30; //x length public int depth = 30; //z length public byte[,] map; public int scale = 6; public Transform _mapParentObjet; [Header("Sync & Materials")] [Networked] public int MazeSeed { get; set; } public Material wallMaterial; public Material floorMaterial; [Header("Win Condition")] public GameObject goalPrefab; public override void Spawned() { if (Object.HasStateAuthority) { // Nếu chưa có seed thì tạo mới if (MazeSeed == 0) MazeSeed = Random.Range(1, 99999); } GenerateMazeWithSeed(MazeSeed); } public void GenerateMazeWithSeed(int seed) { if (_mapParentObjet != null) { // Dùng list để tránh lỗi modify collection khi đang duyệt List children = new List(); foreach (Transform child in _mapParentObjet) children.Add(child.gameObject); foreach (GameObject child in children) Destroy(child); } Random.InitState(seed); InitialiseMap(); Generate(); // Ép ô (1,1) là đường đi cho player spawn map[1, 1] = 0; PlaceExit(); DrawMap(); } public Vector3 GetPlayerSpawnPoint() { // Trả về vị trí tại ô (1,1). y = 1.0f cục bộ return transform.TransformPoint(new Vector3(1 * scale, 1.0f, 1 * scale)); } void InitialiseMap() { map = new byte[width,depth]; for (int z = 0; z < depth; z++) for (int x = 0; x < width; x++) { map[x, z] = 1; //1 = wall 0 = corridor } } public virtual void Generate() { for (int z = 0; z < depth; z++) for (int x = 0; x < width; x++) { if(Random.Range(0,100) < 50) map[x, z] = 0; //1 = wall 0 = corridor } } public virtual void PlaceExit() { int x = width - 2; int z = depth - 2; map[x, z] = 2; if (CountSquareNeighbours(x, z) == 0) map[x - 1, z] = 0; } void DrawMap() { if (_mapParentObjet == null) _mapParentObjet = this.transform; // Tạo sàn chống rơi và Z-fighting GameObject floor = GameObject.CreatePrimitive(PrimitiveType.Plane); floor.name = "Floor"; floor.transform.SetParent(_mapParentObjet); floor.transform.localPosition = new Vector3((width - 1) * scale / 2f, -0.05f, (depth - 1) * scale / 2f); floor.transform.localScale = new Vector3(width * scale / 10f, 1, depth * scale / 10f); if (floorMaterial != null) floor.GetComponent().material = floorMaterial; for (int z = 0; z < depth; z++) for (int x = 0; x < width; x++) { Vector3 pos = new Vector3(x * scale, scale / 2f, z * scale); if (map[x, z] == 1) { GameObject wall = GameObject.CreatePrimitive(PrimitiveType.Cube); wall.name = $"Wall_{x}_{z}"; wall.transform.localScale = new Vector3(scale, scale, scale); wall.transform.SetParent(_mapParentObjet); wall.transform.localPosition = pos; if (wallMaterial != null) wall.GetComponent().material = wallMaterial; } else if (map[x, z] == 2) { GameObject goalObj; if (goalPrefab != null) goalObj = Instantiate(goalPrefab, transform.TransformPoint(pos), Quaternion.identity); else { goalObj = GameObject.CreatePrimitive(PrimitiveType.Cylinder); goalObj.GetComponent().material.color = Color.yellow; goalObj.transform.localScale = new Vector3(scale * 0.5f, scale * 0.5f, scale * 0.5f); } goalObj.name = "Goal_WinSpot"; goalObj.transform.SetParent(_mapParentObjet); goalObj.transform.localPosition = pos; Collider col = goalObj.GetComponent(); if (col == null) col = goalObj.AddComponent(); col.isTrigger = true; if (goalObj.GetComponent() == null) goalObj.AddComponent(); } } } public int CountSquareNeighbours(int x, int z) { int count = 0; if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5; if (map[x - 1, z] == 0) count++; if (map[x + 1, z] == 0) count++; if (map[x, z + 1] == 0) count++; if (map[x, z - 1] == 0) count++; return count; } public int CountDiagonalNeighbours(int x, int z) { int count = 0; if (x <= 0 || x >= width - 1 || z <= 0 || z >= depth - 1) return 5; if (map[x - 1, z - 1] == 0) count++; if (map[x + 1, z + 1] == 0) count++; if (map[x - 1, z + 1] == 0) count++; if (map[x + 1, z - 1] == 0) count++; return count; } public int CountAllNeighbours(int x, int z) { return CountSquareNeighbours(x,z) + CountDiagonalNeighbours(x,z); } }