Advertisement
Guest User

Untitled

a guest
Dec 11th, 2018
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.33 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. public class AsteroidSpawner : MonoBehaviour {
  6.     protected class PlayableGridCell
  7.     {
  8.         public Bounds cellBounds;
  9.         public bool isOccupied;
  10.     };
  11.     public static AsteroidSpawner Instance { get; private set; }
  12.  
  13.     public uint AsteroidsCount = 5;
  14.     public GameObject AsteroidPrefab1,AsteroidPrefab2,AsteroidPrefab3;
  15.     public float PlayableGridCellSize = 2.2f;
  16.     public int PlayerSafeCells = 1;
  17.     public bool ShowDebugDraw = false;
  18.  
  19.     GameObject PlayerShip = null;
  20.     PlayableGridCell[,] PlayableAreaGrid = null;
  21.     private bool IsSpawningFinished = false;
  22.  
  23.     public void RegisterPlayer(GameObject playerObject)
  24.     {
  25.         PlayerShip = playerObject;
  26.     }
  27.  
  28.     public void UnregisterPlayer(GameObject gameObject)
  29.     {
  30.         PlayerShip = null;
  31.     }
  32.  
  33.     void Awake()
  34.     {
  35.         if (Instance == null)
  36.         {
  37.             Instance = this;
  38.         }
  39.         else
  40.         {
  41.             Destroy(gameObject);
  42.         }
  43.     }
  44.     private float nextActionTime = 0.0f;
  45.     public float period = 5.0f;
  46.     void Update()
  47.     {
  48.         if (PlayerShip != null && Time.time > nextActionTime)
  49.         {
  50.             CreatePlayableGrid();
  51.             MarkPlayerSafeArea();
  52.             SpawnNewAsteroids();
  53.             nextActionTime += period;
  54.         }
  55.     }
  56.  
  57.     private void MarkPlayerSafeArea()
  58.     {
  59.         Vector2Int playerGridPos = GetCellCoordinates(PlayerShip.transform.position);
  60.  
  61.         //The player ship's pivot is located in grid cell (playerGridPos.x,playerGridPos.y)
  62.         //Define a square, that is with a side of PlayerSafeCells + 1;
  63.         //We will mark all cells in that square as Occupied, so that no asteroids can spawn there
  64.         int minX = Mathf.Max(0, playerGridPos.x - PlayerSafeCells);
  65.         int maxX = Mathf.Min(playerGridPos.x + PlayerSafeCells, PlayableAreaGrid.GetLength(0) - 1);
  66.         int minY = Mathf.Max(0, playerGridPos.y - PlayerSafeCells);
  67.         int maxY = Mathf.Min(playerGridPos.y + PlayerSafeCells, PlayableAreaGrid.GetLength(1) - 1);
  68.  
  69.         for (int xIter = minX; xIter <= maxX; ++xIter)
  70.         {
  71.             for (int yIter = minY; yIter <= maxY; ++yIter)
  72.             {
  73.                 PlayableAreaGrid[xIter, yIter].isOccupied = true;
  74.             }
  75.         }
  76.     }
  77.  
  78.     private float GetCameraDistance()
  79.     {
  80.         return Camera.main.transform.position.y - transform.position.y;
  81.     }
  82.  
  83.     private Vector3 GetPlayingFieldExtents()
  84.     {
  85.         float cameraDistance = GetCameraDistance();
  86.         Vector3 minPointVS = new Vector3(0, 0, cameraDistance);
  87.         Vector3 maxPointVS = new Vector3(1, 1, cameraDistance);
  88.         Vector3 minPoint = Camera.main.ViewportToWorldPoint(minPointVS);
  89.         Vector3 maxPoint = Camera.main.ViewportToWorldPoint(maxPointVS);
  90.         return maxPoint - minPoint;
  91.     }
  92.  
  93.     private void CreatePlayableGrid()
  94.     {
  95.         Vector3 playingFieldExtents = GetPlayingFieldExtents();
  96.         Vector3 cellExtents = new Vector3(PlayableGridCellSize, 0.1f, PlayableGridCellSize);
  97.         float halfCellSize = PlayableGridCellSize * 0.5f;
  98.  
  99.         //Determine size of the grid, based on the cell size and the playable area size
  100.         int xSize = (int)Mathf.Floor(playingFieldExtents.x / PlayableGridCellSize);
  101.         int zSize = (int)Mathf.Floor(playingFieldExtents.z / PlayableGridCellSize);
  102.         PlayableAreaGrid = new PlayableGridCell[xSize, zSize];
  103.  
  104.         for (int i = 0; i < xSize; ++i)
  105.         {
  106.             for (int j = 0; j < zSize; ++j)
  107.             {
  108.                 Vector3 cellOffset = new Vector3(i, 0, j) * PlayableGridCellSize + new Vector3(halfCellSize, playingFieldExtents.y, halfCellSize);
  109.                 Vector3 cellCenter = -playingFieldExtents * 0.5f + cellOffset;
  110.                 PlayableAreaGrid[i, j] = new PlayableGridCell
  111.                 {
  112.                     cellBounds = new Bounds(cellCenter, cellExtents),
  113.                     isOccupied = false
  114.                 };
  115.             }
  116.         }
  117.     }
  118.  
  119.     private void SpawnNewAsteroids()
  120.     {
  121.         List<Vector3> asteroidPositions = FindFreePositions(AsteroidsCount);
  122.         for (int i = 0; i < asteroidPositions.Count; ++i)
  123.         {
  124.             if ((nextActionTime + 5) % 2 == 0)
  125.             {
  126.                 Instantiate(AsteroidPrefab1, asteroidPositions[i], Random.rotation);
  127.             }
  128.             else if ((nextActionTime + 5) % 3 == 0)
  129.             {
  130.                 Instantiate(AsteroidPrefab2, asteroidPositions[i], Random.rotation);
  131.             }
  132.             else {
  133.                 Instantiate(AsteroidPrefab3, asteroidPositions[i], Random.rotation);
  134.             }
  135.         }
  136.     }
  137.  
  138.     private List<Vector3> FindFreePositions(uint requestedPositionsCnt)
  139.     {
  140.         //Create a list of all guaranteedly unoccupied cells
  141.         List<PlayableGridCell> freeCells = new List<PlayableGridCell>();
  142.  
  143.         for (int i = 0; i < PlayableAreaGrid.GetLength(0); ++i)
  144.         {
  145.             for (int j = 0; j < PlayableAreaGrid.GetLength(1); ++j)
  146.             {
  147.                 if (PlayableAreaGrid[i, j].isOccupied == false)
  148.                 {
  149.                     freeCells.Add(PlayableAreaGrid[i, j]);
  150.                 }
  151.             }
  152.         }
  153.  
  154.         var result = new List<Vector3>();
  155.         for (uint i = 0; i < requestedPositionsCnt; ++i)
  156.         {
  157.             if (freeCells.Count > 0)
  158.             {
  159.                 int chosenCellIndex = Random.Range(0, freeCells.Count);
  160.                 PlayableGridCell chosenCell = freeCells[chosenCellIndex];
  161.                 result.Add(chosenCell.cellBounds.center);
  162.                 freeCells.RemoveAt(chosenCellIndex);
  163.             }
  164.         }
  165.  
  166.         return result;
  167.     }
  168.  
  169.     enum Axis
  170.     {
  171.         X = 0,
  172.         Y = 1,
  173.         Z = 2
  174.     };
  175.  
  176.     private Vector2Int GetCellCoordinates(Vector3 position)
  177.     {
  178.         return new Vector2Int(GetCellCoordinate(position, Axis.X, Axis.X), GetCellCoordinate(position, Axis.Z, Axis.Y));
  179.     }
  180.  
  181.     private int GetCellCoordinate(Vector3 position, Axis worldAxis, Axis gridAxis)
  182.     {
  183.         //Convert from world space to Grid space
  184.         //-PlayingFieldExtents/2 is at 0,0
  185.         //+PlayingFieldExtents/2 is at grid.Length, grid.Length
  186.         int originCellIndex = PlayableAreaGrid.GetLength((int)gridAxis) / 2; //(0,0,0) in world space is in the middle of the grid
  187.         int resultingCoordinate = (int)(Mathf.Floor((position[(int)worldAxis] / PlayableGridCellSize))) + originCellIndex;
  188.         resultingCoordinate = Mathf.Clamp(resultingCoordinate, 0, PlayableAreaGrid.GetLength((int)gridAxis));
  189.         return (int)resultingCoordinate;
  190.     }
  191.  
  192.     void OnDrawGizmos()
  193.     {
  194.         //Used to draw some deubg display, so we can visualize what is on the grid, and the player safe area
  195.         if (!ShowDebugDraw || PlayableAreaGrid == null) return;
  196.         for (int i = 0; i < PlayableAreaGrid.GetLength(0); ++i)
  197.         {
  198.             for (int j = 0; j < PlayableAreaGrid.GetLength(1); ++j)
  199.             {
  200.                 PlayableGridCell cell = PlayableAreaGrid[i, j];
  201.                 Bounds cellBounds = cell.cellBounds;
  202.                 Gizmos.color = cell.isOccupied ? Color.red : Color.green;
  203.                 Gizmos.DrawCube(cellBounds.center, cellBounds.size - new Vector3(0.05f, 0, 0.05f));
  204.             }
  205.         }
  206.     }
  207. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement