Files
Sokoban/Assets/Scripts/Level/LevelBuilder.cs
2023-06-16 17:08:56 +03:00

201 lines
5.6 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Objects;
namespace Level
{
public class LevelBuilder : MonoBehaviour
{
// Static
private static LevelBuilder instance;
// Events
public delegate void LevelDestroyedHandler();
public event LevelDestroyedHandler LevelDestroyed;
public delegate void LevelInitializedHandler();
public event LevelInitializedHandler LevelInitialized;
// Public
public Sprite blockSprite;
public Sprite environmentSprite;
public Sprite groundSprite;
public GameObject spritePrefab;
public GameObject cratePrefab;
public Grid grid;
public LevelBuilderButtons levelBuilderButtons;
// Private
private int width;
private int height;
private LayoutCell[][] layout;
private Vector3Int firstCellPos;
private LevelSaveSystem levelSaveSystem = new LevelSaveSystem();
// Properties
public static LevelBuilder Instance => instance;
// Methods
private void Awake()
{
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
instance = this;
}
private void Update()
{
if (GameManager.Instance.currentState == GameState.Editing && Input.GetMouseButtonDown(0))
{
// Get the mouse position
Vector3 mousePosition = Input.mousePosition;
// Convert the mouse position to world space if needed
Vector3 worldMousePosition = Camera.main.ScreenToWorldPoint(mousePosition);
EditCellAt(worldMousePosition);
}
if (Input.GetKeyDown(KeyCode.T))
{
Save();
}
}
public void CreateLayout(int w, int h)
{
LevelDestroyed?.Invoke();
width = w;
height = h;
// Offset first cell by half of width and height
firstCellPos = new Vector3Int(-width / 2, -height / 2, 0);
layout = new LayoutCell[height][];
for (int y = 0; y < height; y++)
{
layout[y] = new LayoutCell[width];
for (int x = 0; x < width; x++)
{
Vector3Int cellPos = new Vector3Int(firstCellPos.x + x, firstCellPos.y + y, 0);
layout[y][x] = new LayoutCell(cellPos, new Vector2Int(x, y));
}
}
LevelInitialized?.Invoke();
}
public LevelData CreateLevelData()
{
LayoutCell.LayoutCellData[][] layoutData = new LayoutCell.LayoutCellData[height][];
for (int y = 0; y < height; y++)
{
layoutData[y] = new LayoutCell.LayoutCellData[width];
for (int x = 0; x < width; x++)
{
layoutData[y][x] = layout[y][x].cellData;
}
}
LevelData levelData = new LevelData();
levelData.layout = layoutData;
levelData.width = width;
levelData.height = height;
return levelData;
}
public void LoadLevelData(LevelData levelData)
{
CreateLayout(levelData.width, levelData.height);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
LayoutCell cell = layout[y][x];
cell.cellData = levelData.layout[y][x];
cell.UpdateSprites();
if (cell.cellData.cellContent == LayoutCell.LayoutCellData.CellContent.Crate)
{
cell.PlaceCrate();
}
else if (cell.cellData.cellContent == LayoutCell.LayoutCellData.CellContent.Player)
{
Player.Instance.Teleport(cell);
}
}
}
}
public void Save()
{
LevelData levelData = CreateLevelData();
Save(levelData);
}
public void Save(LevelData levelData)
{
levelSaveSystem.Save(levelData);
}
public void Load()
{
levelSaveSystem.Load();
}
public LayoutCell GetCellAtLayout(Vector2Int layoutPosition)
{
// Check that cell with these indices exists in array
// if (0 < layoutPosition.y < height && 0 < layoutPosition.x < width)
if (layoutPosition.y >= 0 && layoutPosition.y < height && layoutPosition.x >= 0 && layoutPosition.x < width)
{
return layout[layoutPosition.y][layoutPosition.x];
}
else
{
return null;
}
}
public LayoutCell WorldToLayoutCell(Vector3 worldPos)
{
Vector3Int cellPos = grid.WorldToCell(worldPos);
Vector2Int layoutPosition = ((Vector2Int) (cellPos - firstCellPos));
return GetCellAtLayout(layoutPosition);
}
private void EditCellAt(Vector3 worldPos)
{
LayoutCell layoutCell = WorldToLayoutCell(worldPos);
if (layoutCell == null)
{
return;
}
LevelBuilderButtons.PlacementOption placementOption = levelBuilderButtons.CurrentOption;
layoutCell.ChangeEnv(placementOption);
}
}
}