Gameplay-Edit

This commit is contained in:
2023-06-16 09:26:12 +03:00
commit 36f90ddd64
185 changed files with 30364 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
using System;
using UnityEngine;
public enum GameState
{
Editing,
Gameplay
}
public class GameManager : MonoBehaviour
{
// Static
private static GameManager instance;
// Events
public event GameStateChangedHandler GameStateChanged;
public delegate void GameStateChangedHandler(GameState newState);
// Public
public GameState currentState { get; private set; } = GameState.Editing;
// Properties
public static GameManager Instance => instance;
// Methods
private void Awake()
{
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
instance = this;
}
// Used by button OnClick
public void SetPlayState()
{
SetState(GameState.Gameplay);
}
// Use by button OnClick
public void SetEditState()
{
SetState(GameState.Editing);
}
public void SetState(GameState newState)
{
currentState = newState;
GameStateChanged?.Invoke(currentState);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d2b306f779dc7e14589ea33028d955cc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4697d71e01541c5449d81ad975d69704
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,142 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Objects;
namespace Level
{
public class LayoutCell
{
[System.Serializable]
public struct LayoutCellData
{
public enum CellContent
{
None,
Block,
Player,
Crate
}
public CellContent cellContent;
public bool isTarget;
public Vector3Int cellPos;
}
// Public
public LayoutCellData cellData;
public Vector3 worldPos;
public Crate crate;
public Vector2Int layoutPosition;
// Private
private SpriteRenderer bgSpriteRenderer;
private SpriteRenderer envSpriteRenderer;
// Properties
public bool IsFree
{
get
{
return cellData.cellContent == LayoutCellData.CellContent.None;
}
}
private Grid grid => LevelBuilder.Instance.grid;
private Sprite blockSprite => LevelBuilder.Instance.blockSprite;
private Sprite environmentSprite => LevelBuilder.Instance.environmentSprite;
private Sprite groundSprite => LevelBuilder.Instance.groundSprite;
private GameObject spritePrefab => LevelBuilder.Instance.spritePrefab;
private GameObject cratePrefab => LevelBuilder.Instance.cratePrefab;
public LayoutCell(Vector3Int cellPos, Vector2Int layoutPos)
{
layoutPosition = layoutPos;
// Init data
cellData = new LayoutCellData
{
cellContent = LayoutCellData.CellContent.None,
isTarget = false,
cellPos = cellPos
};
worldPos = grid.GetCellCenterWorld(cellPos);
// Init sprite objects
GameObject bgObject = GameObject.Instantiate(spritePrefab, worldPos, Quaternion.identity);
bgSpriteRenderer = bgObject.GetComponent<SpriteRenderer>();
bgSpriteRenderer.sprite = groundSprite;
GameObject envObject = GameObject.Instantiate(spritePrefab, worldPos, Quaternion.identity);
envSpriteRenderer = envObject.GetComponent<SpriteRenderer>();
envSpriteRenderer.sortingOrder = 1;
// Subscribe to destroy event
LevelBuilder.Instance.LevelDestroyed += Destroy;
}
public void ChangeEnv(LevelBuilderButtons.PlacementOption placementOption)
{
// Clean previous contents
cellData.cellContent = LayoutCellData.CellContent.None;
cellData.isTarget = false;
if (crate)
{
GameObject.Destroy(crate.gameObject);
}
// Place new object
if (placementOption == LevelBuilderButtons.PlacementOption.Block)
{
cellData.cellContent = LayoutCellData.CellContent.Block;
}
else if (placementOption == LevelBuilderButtons.PlacementOption.Environment)
{
cellData.isTarget = true;
}
else if (placementOption == LevelBuilderButtons.PlacementOption.Crate)
{
cellData.cellContent = LayoutCellData.CellContent.Crate;
GameObject crateObject = GameObject.Instantiate(cratePrefab, worldPos, Quaternion.identity);
crate = crateObject.GetComponent<Crate>();
crate.layoutPosition = layoutPosition;
}
else if (placementOption == LevelBuilderButtons.PlacementOption.Player)
{
Player.Instance.Teleport(this);
}
UpdateSprites();
}
public void UpdateSprites()
{
if (cellData.cellContent == LayoutCellData.CellContent.Block)
{
envSpriteRenderer.sprite = blockSprite;
}
else if (cellData.isTarget)
{
envSpriteRenderer.sprite = environmentSprite;
}
else
{
envSpriteRenderer.sprite = null;
}
}
public void Destroy()
{
GameObject.Destroy(bgSpriteRenderer.gameObject);
GameObject.Destroy(envSpriteRenderer.gameObject);
LevelBuilder.Instance.LevelDestroyed -= Destroy;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a9b573e03b4aad44bf34e4e06c9b347
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
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;
// 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);
}
}
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 LayoutCell GetCellAt(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 GetCellAt(layoutPosition);
}
private void EditCellAt(Vector3 worldPos)
{
LayoutCell layoutCell = WorldToLayoutCell(worldPos);
if (layoutCell == null)
{
return;
}
LevelBuilderButtons.PlacementOption placementOption = levelBuilderButtons.CurrentOption;
layoutCell.ChangeEnv(placementOption);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16bd348cc0368794a840f6eb88061349
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 24f46fbe6d71d844cb51d8cffe0b101a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Level;
using DG.Tweening;
namespace Objects
{
public class Crate : MonoBehaviour
{
public Vector2Int layoutPosition; // Index in layout
private void Start()
{
LevelBuilder.Instance.LevelDestroyed += Destroy;
}
private void OnDestroy()
{
LevelBuilder.Instance.LevelDestroyed -= Destroy;
}
public void Move(Vector2Int direction)
{
LayoutCell currentCell = LevelBuilder.Instance.GetCellAt(layoutPosition);
LayoutCell targetCell = LevelBuilder.Instance.GetCellAt(layoutPosition + direction);
if (targetCell != null && targetCell.IsFree)
{
// Free previous cell
currentCell.cellData.cellContent = LayoutCell.LayoutCellData.CellContent.None;
currentCell.crate = null;
// Occupy new cell
targetCell.cellData.cellContent = LayoutCell.LayoutCellData.CellContent.Crate;
targetCell.crate = this;
// Update position
layoutPosition = layoutPosition + direction;
// Move object
transform.DOMove(targetCell.worldPos, 1f);
}
}
private void Destroy()
{
Destroy(gameObject);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d65016f694ed8e34282e3a79cfa62449
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,126 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Level;
using DG.Tweening;
namespace Objects
{
public class Player : MonoBehaviour
{
private static Player instance;
public Vector2Int layoutPosition;
private bool isMoving = false;
public static Player Instance => instance;
public bool CanMove
{
get
{
return !isMoving && GameManager.Instance.currentState == GameState.Gameplay;
}
}
private void Awake()
{
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
instance = this;
}
private void Start()
{
LevelBuilder.Instance.LevelInitialized += OnLevelInitialized;
LevelBuilder.Instance.LevelDestroyed += OnLevelDestroy;
}
private void Update()
{
if (CanMove)
{
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Move(Vector2Int.down);
}
else if (Input.GetKeyDown(KeyCode.UpArrow))
{
Move(Vector2Int.up);
}
else if (Input.GetKeyDown(KeyCode.LeftArrow))
{
Move(Vector2Int.left);
}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{
Move(Vector2Int.right);
}
}
}
public void Teleport(LayoutCell targetCell)
{
LayoutCell currentCell = LevelBuilder.Instance.GetCellAt(layoutPosition);
// Free previous cell
currentCell.cellData.cellContent = LayoutCell.LayoutCellData.CellContent.None;
// Occupy new cell
targetCell.cellData.cellContent = LayoutCell.LayoutCellData.CellContent.Player;
// Update position
layoutPosition = targetCell.layoutPosition;
transform.position = targetCell.worldPos;
}
public void Move(Vector2Int direction)
{
LayoutCell currentCell = LevelBuilder.Instance.GetCellAt(layoutPosition);
LayoutCell targetCell = LevelBuilder.Instance.GetCellAt(layoutPosition + direction);
if (targetCell != null && targetCell.IsFree)
{
// Free previous cell
currentCell.cellData.cellContent = LayoutCell.LayoutCellData.CellContent.None;
// Occupy new cell
targetCell.cellData.cellContent = LayoutCell.LayoutCellData.CellContent.Player;
// Update position
layoutPosition = layoutPosition + direction;
// Move object
isMoving = true;
transform.DOMove(targetCell.worldPos, 1f).OnComplete(() => isMoving = false);
}
else if (targetCell != null && targetCell.cellData.cellContent == LayoutCell.LayoutCellData.CellContent.Crate)
{
targetCell.crate.Move(direction);
}
}
private void OnLevelInitialized()
{
gameObject.SetActive(true);
Teleport(LevelBuilder.Instance.GetCellAt(new Vector2Int(0, 0)));
}
private void OnLevelDestroy()
{
gameObject.SetActive(false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: df890f9d39fcb764c833db6539805676
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/Scripts/UI.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b7c682febf3e55243a9db90e25bd60b0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,93 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using Level;
public class InitializeLevelUI : MonoBehaviour
{
[SerializeField] private GameObject uiContainer;
[SerializeField] private TextMeshProUGUI widthText;
[SerializeField] private TextMeshProUGUI heightText;
private int width = 5;
private int height = 5;
// Properties
private int Width
{
get
{
return width;
}
set
{
width = value;
widthText.text = width.ToString();
}
}
private int Height
{
get
{
return height;
}
set
{
height = value;
heightText.text = height.ToString();
}
}
private void Awake()
{
uiContainer.SetActive(false);
Width = 5;
Height = 5;
}
private void Start()
{
GameManager.Instance.GameStateChanged += OnGameStateChanged;
}
public void ToggleUI()
{
uiContainer.SetActive(!uiContainer.activeSelf);
}
public void ChangeWidth(int delta)
{
Width += delta;
Width = Mathf.Clamp(Width, 3, 100);
}
public void ChangeHeight(int delta)
{
Height += delta;
Height = Mathf.Clamp(Height, 3, 100);
}
public void Initialize()
{
LevelBuilder.Instance.CreateLayout(Width, Height);
uiContainer.SetActive(false);
}
private void OnGameStateChanged(GameState newState)
{
if (newState == GameState.Gameplay)
{
uiContainer.SetActive(false);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7aa653a1aba48a849a597b58214e4c9b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace Level
{
public class LevelBuilderButtons : MonoBehaviour
{
public enum PlacementOption
{
None,
Block,
Ground,
Crate,
Player,
Environment
}
[System.Serializable]
public struct PlacementOptionButton
{
public GameObject gameObject;
public Image bgImage;
public Button button;
public PlacementOption placementOption;
}
// Private
[SerializeField] private GameObject buttonsContainer;
[SerializeField] private PlacementOptionButton[] placementOptionButtons;
[SerializeField] private Color defaultColor;
[SerializeField] private Color selectedColor;
private PlacementOption currentOption;
// Properties
public PlacementOption CurrentOption => currentOption;
private void Awake()
{
foreach (PlacementOptionButton placementOptionButton in placementOptionButtons)
{
placementOptionButton.button.onClick.AddListener(() => ChangeActiveOption(placementOptionButton.placementOption));
placementOptionButton.bgImage.color = defaultColor;
}
buttonsContainer.SetActive(false);
}
private void Start()
{
GameManager.Instance.GameStateChanged += OnGameStateChanged;
}
public void ToggleUI()
{
buttonsContainer.SetActive(!buttonsContainer.activeSelf);
}
private void ChangeActiveOption(PlacementOption placementOption)
{
currentOption = placementOption;
foreach (PlacementOptionButton placementOptionButton in placementOptionButtons)
{
if (placementOptionButton.placementOption == placementOption)
{
placementOptionButton.bgImage.color = selectedColor;
}
else
{
placementOptionButton.bgImage.color = defaultColor;
}
}
}
private void OnGameStateChanged(GameState newState)
{
if (newState == GameState.Gameplay)
{
buttonsContainer.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fa2c862b0463c9f4da607f6306396ef9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

52
Assets/Scripts/UI/Menu.cs Normal file
View File

@@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Level;
public class Menu : MonoBehaviour
{
[SerializeField] private GameObject menuDropdown;
[SerializeField] private GameObject[] buttonsToInitialize; // Buttons that rely on initialized level to work
[SerializeField] private GameObject editingButtonsContainer;
[SerializeField] private GameObject gameplayButtonsContainer;
[SerializeField] private GameObject startMenu;
private void Awake()
{
menuDropdown.SetActive(false);
foreach (GameObject button in buttonsToInitialize)
{
button.SetActive(false);
}
}
private void Start()
{
LevelBuilder.Instance.LevelInitialized += OnLevelInitialized;
GameManager.Instance.GameStateChanged += OnGameStateChanged;
}
public void ToggleMenu()
{
menuDropdown.SetActive(!menuDropdown.activeSelf);
}
private void OnLevelInitialized()
{
foreach (GameObject button in buttonsToInitialize)
{
button.SetActive(true);
}
startMenu.SetActive(false);
}
private void OnGameStateChanged(GameState newState)
{
editingButtonsContainer.SetActive(newState == GameState.Editing);
gameplayButtonsContainer.SetActive(newState == GameState.Gameplay);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0f29c9409f712ca4a98a87976c634e49
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: