Create All Needed Scripts

This commit is contained in:
2025-12-14 09:23:38 +08:00
parent 980b26dd5e
commit 6fe70bd113
53 changed files with 1988 additions and 195 deletions

View File

@@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using Enums;
using Models.Interfaces;
using ScriptableObjects;
using Services.Interfaces;
using UnityEngine;
using Views;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
namespace Services {
public class GameBoardService : IGameBoardService {
private IGameBoard gameBoard;
private GameVariables gameVariables;
private IMatchService matchService;
private IScoreService scoreService;
private Transform gemsHolder;
public GameBoardService(IGameBoard gameBoard, GameVariables gameVariables, IMatchService matchService, IScoreService scoreSerivce, Transform gemsHolder) {
this.gameBoard = gameBoard;
this.gameVariables = gameVariables;
this.matchService = matchService;
this.scoreService = scoreSerivce;
this.gemsHolder = gemsHolder;
}
private int RandomGemTypeAsInt() {
GemType[] spawnableGems = Enum.GetValues(typeof(GemType))
.Cast<GemType>()
.Where(gType => gType != GemType.Bomb)
.ToArray();
return Random.Range(0, spawnableGems.Length);
}
public void Setup() {
for (int x = 0; x < this.gameBoard.Width; x++)
for (int y = 0; y < this.gameBoard.Height; y++)
{
Vector2 position = new Vector2(x, y);
GameObject backgroundTile = Object.Instantiate(this.gameVariables.bgTilePrefabs, position, Quaternion.identity);
backgroundTile.transform.SetParent(this.gemsHolder);
backgroundTile.name = "BG Tile - " + x + ", " + y;
int gemToUse = RandomGemTypeAsInt();
int iterations = 0;
while (this.matchService.MatchesAt(new Vector2Int(x, y), (GemType)gemToUse) && iterations < 100)
{
gemToUse = RandomGemTypeAsInt();
iterations++;
}
//ToDo: change gameVariables.gemsPrefabs[gemToUse] since gemToUse is index, if the order changes it wont work
SpawnGem(new Vector2Int(x, y), this.gameVariables.gemsPrefabs[gemToUse], (GemType)gemToUse);
}
}
public void SpawnGem(Vector2Int position, GemView gemPrefab, GemType gemType) {
if (Random.Range(0, 100f) < this.gameVariables.bombChance)
gemPrefab = this.gameVariables.bombPrefab;
GemView gemView = Object.Instantiate(gemPrefab, new Vector3(position.x, position.y + this.gameVariables.dropHeight, 0f), Quaternion.identity);
gemView.transform.SetParent(this.gemsHolder);
gemView.name = "Gem - " + position.x + ", " + position.y;
SetGem(new Vector2Int(position.x,position.y), new Gem(gemType, position));
}
public void SetGem(Vector2Int position, Gem gem) {
this.gameBoard.SetGemAt(new Vector2Int(position.x, position.y), gem);
}
public Gem GetGem(Vector2Int position) {
return this.gameBoard.GetGemAt(position);
}
public void DestroyMatches() {
for (int i = 0; i < this.matchService.CurrentMatches.Count; i++)
if (this.matchService.CurrentMatches[i] != null)
{
this.scoreService.ScoreCheck(this.matchService.CurrentMatches[i].ScoreValue);
DestroyMatchedGems(this.matchService.CurrentMatches[i].Position);
}
MoveGemsDown();
}
public async UniTask MoveGemsDown() {
await UniTask.Delay(2);
// why the delay though?
// yield return new WaitForSeconds(.2f);
int nullCounter = 0;
for (int x = 0; x < this.gameBoard.Width; x++)
{
for (int y = 0; y < this.gameBoard.Height; y++)
{
Gem currentGem = this.gameBoard.GetGemAt(new Vector2Int(x, y));
if (currentGem == null)
{
nullCounter++;
}
else if (nullCounter > 0)
{
currentGem.SetPosition(new Vector2Int(currentGem.Position.x, currentGem.Position.y - nullCounter));
SetGem(currentGem.Position, currentGem);
SetGem(new Vector2Int(x,y), null);
}
}
nullCounter = 0;
}
}
public async UniTask FillBoard() {
await UniTask.Delay(5);
RefillBoard();
await UniTask.Delay(5);
this.matchService.FindAllMatches();
if (this.matchService.CurrentMatches.Count > 0)
{
await UniTask.Delay(5);
DestroyMatches();
}
else
{
await UniTask.Delay(5);
// currentState = GameState.Move;
}
}
public void RefillBoard() {
for (int x = 0; x < this.gameBoard.Width; x++)
{
for (int y = 0; y < this.gameBoard.Height; y++)
{
Gem currentGem = this.gameBoard.GetGemAt(new Vector2Int(x,y));
if (currentGem == null) {
int gemToUse = RandomGemTypeAsInt();
SpawnGem(new Vector2Int(x, y), this.gameVariables.gemsPrefabs[gemToUse], (GemType)gemToUse);
}
}
}
CheckMisplacedGems();
}
public void CheckMisplacedGems() {
List<GemView> gemsViews = GemsViews();
for (int x = 0; x < this.gameBoard.Width; x++)
{
for (int y = 0; y < this.gameBoard.Height; y++)
{
Gem currentGem = this.gameBoard.GetGemAt(new Vector2Int(x,y));
GemView gemView = gemsViews.FirstOrDefault(gv => gv.Gem == currentGem);
if (gemView != null) {
gemsViews.Remove(gemView);
}
}
}
foreach (GemView g in gemsViews)
Object.Destroy(g.gameObject);
}
public void DestroyMatchedGems(Vector2Int position) {
List<GemView> gemsViews = GemsViews();
Gem currentGem = this.gameBoard.GetGemAt(position);
if (currentGem != null)
{
GemView gemView = gemsViews.FirstOrDefault(gv => gv.Gem == currentGem);
Object.Instantiate(this.gameVariables.destroyEffectPrefabs[(int)currentGem.Type], new Vector2(position.x, position.y), Quaternion.identity);
Object.Destroy(gemView!.gameObject);
SetGem(position, null);
}
}
private List<GemView> GemsViews() {
return this.gemsHolder.GetComponentsInChildren<GemView>().ToList();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1e52d701a54645898c36c3f407ac890f
timeCreated: 1765664126

View File

@@ -0,0 +1,19 @@
using Cysharp.Threading.Tasks;
using Enums;
using UnityEngine;
using Views;
namespace Services.Interfaces {
public interface IGameBoardService {
void Setup();
void SpawnGem(Vector2Int position, GemView gemPrefab, GemType gemType);
void SetGem(Vector2Int position, Gem gem);
Gem GetGem(Vector2Int position);
void DestroyMatches();
UniTask MoveGemsDown();
UniTask FillBoard();
void RefillBoard();
void CheckMisplacedGems();
void DestroyMatchedGems(Vector2Int position);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c63053069b7e4791a82ee7dd04eae86c
timeCreated: 1765662196

View File

@@ -0,0 +1,9 @@
using System;
using UnityEngine;
namespace Services.Interfaces {
public interface IInputService {
event Action<Vector2> OnPointerDown;
event Action<Vector2> OnPointerUp;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 73b706bb5eea4fdf9b1f4563aef578cd
timeCreated: 1765632542

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using UnityEngine;
using Enums;
namespace Services.Interfaces {
public interface IMatchService {
List<Gem> CurrentMatches { get; }
bool MatchesAt(Vector2Int positionToCheck, GemType gemTypeToCheck);
void FindAllMatches();
void CheckForBombs();
void MarkBombArea(Vector2Int bombPosition, int blastSize);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 513ff6c9b21549f088abcb4c83143771
timeCreated: 1765656570

View File

@@ -0,0 +1,5 @@
namespace Services.Interfaces {
public interface IScoreService {
void ScoreCheck(int value);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8d61c21960f14353b3f431434d3b4de2
timeCreated: 1765674663

View File

@@ -0,0 +1,99 @@
using System.Collections.Generic;
using System.Linq;
using Enums;
using Services.Interfaces;
using UnityEngine;
namespace Services {
public class MatchService : IMatchService {
private List<Gem> currentMatches = new List<Gem>();
public List<Gem> CurrentMatches => this.currentMatches;
private GameBoard gameBoard;
public MatchService(GameBoard gameBoard) {
this.gameBoard = gameBoard;
}
public bool MatchesAt(Vector2Int positionToCheck, GemType gemTypeToCheck) {
Gem[,] gems = this.gameBoard.GemsGrid;
if (positionToCheck.x > 1)
{
if (gems[positionToCheck.x - 1, positionToCheck.y].Type == gemTypeToCheck && gems[positionToCheck.x - 2, positionToCheck.y].Type == gemTypeToCheck)
return true;
}
if (positionToCheck.y > 1)
{
if (gems[positionToCheck.x, positionToCheck.y - 1].Type == gemTypeToCheck && gems[positionToCheck.x, positionToCheck.y - 2].Type == gemTypeToCheck)
return true;
}
return false;
}
public void FindAllMatches() {
this.currentMatches.Clear();
for (int x = 0; x < this.gameBoard.Width; x++)
for (int y = 0; y < this.gameBoard.Height; y++)
{
Gem currentGem = this.gameBoard.GemsGrid[x, y];
if (currentGem != null)
{
if (x > 0 && x < this.gameBoard.Width - 1)
{
Gem leftGem = this.gameBoard.GemsGrid[x - 1, y];
Gem rightGem = this.gameBoard.GemsGrid[x + 1, y];
//checking no empty spots
if (leftGem != null && rightGem != null)
{
//Match
if (leftGem.Type == currentGem.Type && rightGem.Type == currentGem.Type)
{
currentGem.isMatch = true;
leftGem.isMatch = true;
rightGem.isMatch = true;
this.currentMatches.Add(currentGem);
this.currentMatches.Add(leftGem);
this.currentMatches.Add(rightGem);
}
}
}
if (y > 0 && y < this.gameBoard.Height - 1)
{
Gem aboveGem = this.gameBoard.GemsGrid[x, y - 1];
Gem bellowGem = this.gameBoard.GemsGrid[x, y + 1];
//checking no empty spots
if (aboveGem != null && bellowGem != null)
{
//Match
if (aboveGem.Type == currentGem.Type && bellowGem.Type == currentGem.Type)
{
currentGem.isMatch = true;
aboveGem.isMatch = true;
bellowGem.isMatch = true;
this.currentMatches.Add(currentGem);
this.currentMatches.Add(aboveGem);
this.currentMatches.Add(bellowGem);
}
}
}
}
}
if (this.currentMatches.Count > 0) this.currentMatches = this.currentMatches.Distinct().ToList();
CheckForBombs();
}
public void CheckForBombs() {
throw new System.NotImplementedException();
}
public void MarkBombArea(Vector2Int bombPosition, int blastSize) {
throw new System.NotImplementedException();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0fca077f5e14456ab09ae9ea6bca7c61
timeCreated: 1765665318

View File

@@ -2,22 +2,23 @@ using System.Collections;
using System.Collections.Generic;
using Services.Interfaces;
using UnityEngine;
using Views;
namespace Services {
public class ObjectPoolService:IObjectPool<GameObject> {
private readonly GameObject prefab;
public class ObjectPoolService:IObjectPool<GemView> {
private readonly GemView prefab;
private readonly Transform parent;
private readonly int size;
private readonly Stack<GameObject> pool = new Stack<GameObject>();
private readonly Stack<GemView> pool = new Stack<GemView>();
public ObjectPoolService(GameObject prefab, Transform parent, int size = 5) {
public ObjectPoolService(GemView prefab, Transform parent, int size = 5) {
this.prefab = prefab;
this.parent = parent;
this.size = size;
}
public GameObject Get() {
public GemView Get() {
return this.pool.Count == 0 ? Object.Instantiate(this.prefab, this.parent) : this.pool.Pop();
}
@@ -27,7 +28,7 @@ namespace Services {
}
}
public void Release(GameObject gameObject) {
public void Release(GemView gameObject) {
this.pool.Push(gameObject);
}

View File

@@ -0,0 +1,11 @@
using System;
using Services.Interfaces;
namespace Services {
public class ScoreService : IScoreService {
private int score = 0;
public void ScoreCheck(int value) {
this.score += value;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b5bac284955046708f571939e29d9dff
timeCreated: 1765674722