Optimization and Documentation
This commit is contained in:
@@ -25,7 +25,7 @@ namespace Services
|
||||
public void PlaySound(AudioClip clip)
|
||||
{
|
||||
if (clip == null) return;
|
||||
if (this.source == null) return; // In case called before Initialize in some edge setup
|
||||
if (this.source == null) return; // In case it's called before Initialize in some edge setup
|
||||
|
||||
this.source.PlayOneShot(clip);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace Services
|
||||
private Vector2Int lastSwapTo;
|
||||
|
||||
private BombSpawnRequest? pendingBombSpawn;
|
||||
public BombSpawnRequest? PendingBombSpawn => this.pendingBombSpawn;
|
||||
|
||||
public BombService(GameVariables gameVariables, IGameBoard gameBoard) {
|
||||
this.gameVariables = gameVariables;
|
||||
@@ -34,7 +33,7 @@ namespace Services
|
||||
ClearPendingBombs();
|
||||
}
|
||||
|
||||
public UniTask<List<Vector2Int>> GetInitialBombs(List<Vector2Int> protectedPositions, List<Vector2Int> bombCandidates) {
|
||||
public UniTask<List<Vector2Int>> GetInitialBombs(List<Vector2Int> protectedPositions, HashSet<Vector2Int> bombCandidates) {
|
||||
HashSet<Vector2Int> initialBombs = new HashSet<Vector2Int>();
|
||||
foreach (Vector2Int p in bombCandidates) {
|
||||
if (!GemUtils.IsInBounds(p, this.gameBoard)) continue;
|
||||
@@ -52,10 +51,10 @@ namespace Services
|
||||
|
||||
public List<Vector2Int> ApplyPendingBombSpawns(Action<Vector2Int, GemType, bool> spawnGem) {
|
||||
List<Vector2Int> positions = new List<Vector2Int>();
|
||||
BombSpawnRequest? bombSpawnRequest = PendingBombSpawn;
|
||||
BombSpawnRequest? bombSpawnRequest = this.pendingBombSpawn;
|
||||
|
||||
if (bombSpawnRequest != null) {
|
||||
BombSpawnRequest bombRequest = PendingBombSpawn.GetValueOrDefault();
|
||||
BombSpawnRequest bombRequest = this.pendingBombSpawn.GetValueOrDefault();
|
||||
positions.Add(bombRequest.Position);
|
||||
spawnGem(bombRequest.Position, bombRequest.Color, true);
|
||||
}
|
||||
@@ -84,7 +83,7 @@ namespace Services
|
||||
if (currentMatches == null || !currentMatches.Contains(pivotGem))
|
||||
return;
|
||||
|
||||
// Only create a bomb if pivot is part of a straight 4+ line of the SAME color.
|
||||
// Only create a bomb if the pivot is part of a straight 4+ line of the SAME color.
|
||||
int longestLine = GetLongestMatchedLineThroughPivot(pivot, pivotGem.MatchColor);
|
||||
if (longestLine < 4)
|
||||
return;
|
||||
@@ -181,7 +180,7 @@ namespace Services
|
||||
}
|
||||
}
|
||||
|
||||
// Destroy everything for this wave (non-bombs in range + the detonating bombs themselves)
|
||||
// Destroy everything for this wave (non-bombs in range and the detonating bombs themselves)
|
||||
foreach (Vector2Int p in toDestroyNow)
|
||||
await destroyAtAsync(p);
|
||||
|
||||
@@ -216,21 +215,21 @@ namespace Services
|
||||
|
||||
private int CountSameColorInDirection(Vector2Int start, Vector2Int direction, GemType color) {
|
||||
int count = 0;
|
||||
Vector2Int oivot = start + direction;
|
||||
Vector2Int pivot = start + direction;
|
||||
|
||||
while (oivot.x >= 0 && oivot.x < this.gameBoard.Width && oivot.y >= 0 && oivot.y < this.gameBoard.Height) {
|
||||
Gem g = this.gameBoard.GetGemAt(oivot);
|
||||
while (pivot.x >= 0 && pivot.x < this.gameBoard.Width && pivot.y >= 0 && pivot.y < this.gameBoard.Height) {
|
||||
Gem g = this.gameBoard.GetGemAt(pivot);
|
||||
if (g == null || g.Type == GemType.Bomb || g.MatchColor != color)
|
||||
break;
|
||||
|
||||
count++;
|
||||
oivot += direction;
|
||||
pivot += direction;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public void ClearPendingBombs() {
|
||||
private void ClearPendingBombs() {
|
||||
this.pendingBombSpawn = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using ScriptableObjects;
|
||||
using Services.Interfaces;
|
||||
using Structs;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Utils;
|
||||
using VContainer.Unity;
|
||||
using Views;
|
||||
@@ -30,7 +29,6 @@ namespace Services {
|
||||
private readonly ScorePresenter scorePresenter;
|
||||
private readonly AudioPresenter audioPresenter;
|
||||
|
||||
private readonly Transform gemsHolder;
|
||||
private readonly Transform backgroundHolder;
|
||||
#endregion
|
||||
|
||||
@@ -49,7 +47,6 @@ namespace Services {
|
||||
IScoreService scoreService,
|
||||
ScorePresenter scorePresenter,
|
||||
AudioPresenter audioPresenter,
|
||||
Transform gemsHolder,
|
||||
Transform backgroundHolder) {
|
||||
this.gameVariables = gameVariables;
|
||||
this.gameBoard = gameBoard;
|
||||
@@ -59,10 +56,12 @@ namespace Services {
|
||||
this.scoreService = scoreService;
|
||||
this.scorePresenter = scorePresenter;
|
||||
this.audioPresenter = audioPresenter;
|
||||
this.gemsHolder = gemsHolder;
|
||||
this.backgroundHolder = backgroundHolder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Global tick. Update replacement of VContainer-managed objects.
|
||||
/// </summary>
|
||||
public void Tick() {
|
||||
foreach (GemPresenter gemPresenter in gemPresenters) {
|
||||
gemPresenter.Tick(this.gameVariables.gemSpeed);
|
||||
@@ -71,8 +70,9 @@ namespace Services {
|
||||
this.scorePresenter.Tick(this.gameVariables.scoreSpeed);
|
||||
}
|
||||
|
||||
//Instantiates background tiles and calls SpawnGems
|
||||
//Uses MatchService.MatchesAt to avoid matching Gems
|
||||
/// <summary>
|
||||
/// Initiates the game board by placing gems randomly.
|
||||
/// </summary>
|
||||
public void Setup() {
|
||||
List<Gem> gemsToSpawn = new List<Gem>();
|
||||
for (int x = 0; x < this.gameBoard.Width; x++)
|
||||
@@ -91,9 +91,22 @@ namespace Services {
|
||||
gemsToSpawn.Add(SetGemAt(position.ToVector2Int(), gemToUse));
|
||||
}
|
||||
|
||||
SpawnCascade(gemsToSpawn);
|
||||
SpawnCascade(gemsToSpawn).Forget();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Gem object and place it on the GameBoard.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// Position on the GameBoard to place the Gem.
|
||||
/// </param>
|
||||
/// <param name="gemType">
|
||||
/// Type of Gem to create.
|
||||
/// </param>
|
||||
/// <param name="isBomb">
|
||||
/// Whether the Gem is a Bomb or not.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private Gem SetGemAt(Vector2Int position, GemType gemType, bool isBomb = false) {
|
||||
GemTypeValues gemValue = GemUtils.GetGemValues(gemType, this.gameVariables.gemsPrefabs);
|
||||
Gem gem = new Gem(isBomb ? GemType.Bomb : gemType, position, gemValue, gemType);
|
||||
@@ -102,6 +115,15 @@ namespace Services {
|
||||
return gem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a GemView object and binds it to the Gem object.
|
||||
/// </summary>
|
||||
/// <param name="gem">
|
||||
/// Gem to bind to the GemView.
|
||||
/// </param>
|
||||
/// <param name="isBomb">
|
||||
/// Whether the Gem is a Bomb or not.
|
||||
/// </param>
|
||||
private void SpawnGemGameObject(Gem gem, bool isBomb = false) {
|
||||
GemView gemView = this.objectPool.Get(isBomb ? GemType.Bomb : gem.Type, gem.Position, isBomb ? 0 : this.gameVariables.dropHeight);
|
||||
gemView.name = "Gem - " + gem.Position.x + ", " + gem.Position.y + ' ' + gem.Type;
|
||||
@@ -112,6 +134,18 @@ namespace Services {
|
||||
this.gemToView.Add(gem, gemView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls SetGemAt and SpawnGemGameObject.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// Position on the GameBoard to place the Gem.
|
||||
/// </param>
|
||||
/// <param name="gemType">
|
||||
/// Type of Gem to create.
|
||||
/// </param>
|
||||
/// <param name="isBomb">
|
||||
/// Whether the Gem is a Bomb or not.
|
||||
/// </param>
|
||||
private void SetAndSpawnGem(Vector2Int position, GemType gemType, bool isBomb) {
|
||||
if(isBomb)
|
||||
ReleaseMatchedGems(position);
|
||||
@@ -119,13 +153,28 @@ namespace Services {
|
||||
SpawnGemGameObject(SetGemAt(position, gemType, isBomb), isBomb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a background tile at the given position. Only for setup.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// Position on the GameBoard to place the tile.
|
||||
/// </param>
|
||||
private void SpawnBackgroundTile(Vector2 position) {
|
||||
GameObject backgroundTile = Object.Instantiate(this.gameVariables.bgTilePrefabs, position, Quaternion.identity);
|
||||
backgroundTile.transform.SetParent(this.backgroundHolder);
|
||||
backgroundTile.name = "BG Tile - " + position.x + ", " + position.y;
|
||||
}
|
||||
|
||||
//Listens to InputService OnSwapRequest
|
||||
/// <summary>
|
||||
/// Attempts to swap two gems on the GameBoard.
|
||||
/// </summary>
|
||||
/// <param name="from">
|
||||
/// Original position of the gem to swap.
|
||||
/// </param>
|
||||
/// <param name="to">
|
||||
/// Destination position of the gem to swap.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public async UniTask<bool> TrySwap(Vector2Int from, Vector2Int to) {
|
||||
if (this.currentState != GameState.Move)
|
||||
return false;
|
||||
@@ -158,10 +207,17 @@ namespace Services {
|
||||
return true;
|
||||
}
|
||||
|
||||
public async UniTask<bool> TrySwitch(Vector2Int position) {
|
||||
/// <summary>
|
||||
/// For debug purposes. Switches the Gem at the given position to a different GemType.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// Position of the Gem to switch.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public void TrySwitch(Vector2Int position) {
|
||||
Gem gem = this.gameBoard.GetGemAt(position);
|
||||
if(gem == null)
|
||||
return false;
|
||||
return;
|
||||
|
||||
GemType[] normalTypes = Enum.GetValues(typeof(GemType))
|
||||
.Cast<GemType>()
|
||||
@@ -169,7 +225,7 @@ namespace Services {
|
||||
.ToArray();
|
||||
|
||||
if (normalTypes.Length == 0)
|
||||
return false;
|
||||
return;
|
||||
|
||||
bool nextIsBomb;
|
||||
GemType nextTypeOrMatchColor;
|
||||
@@ -198,12 +254,20 @@ namespace Services {
|
||||
}
|
||||
}
|
||||
|
||||
// Replace both model+view by releasing current and respawning at same position.
|
||||
// Replace both model+view by releasing current and respawning at the same position.
|
||||
ReleaseMatchedGems(position);
|
||||
SpawnGemGameObject(SetGemAt(position, nextTypeOrMatchColor, nextIsBomb), nextIsBomb);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for TrySwap. Swaps the Gems in the GameBoard.
|
||||
/// </summary>
|
||||
/// <param name="from">
|
||||
/// Original position of the gem to swap.
|
||||
/// </param>
|
||||
/// <param name="to">
|
||||
/// Destination position of the gem to swap.
|
||||
/// </param>
|
||||
private void ApplySwap(Vector2Int from, Vector2Int to) {
|
||||
Gem fromGem = this.gameBoard.GetGemAt(from);
|
||||
Gem toGem = this.gameBoard.GetGemAt(to);
|
||||
@@ -216,22 +280,23 @@ namespace Services {
|
||||
this.gameBoard.SetGemAt(to, fromGem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all matches on the GameBoard.
|
||||
/// </summary>
|
||||
/// <param name="protectedPositions">
|
||||
/// Gems we don't want to instantly destroy.
|
||||
/// </param>
|
||||
private async UniTask DestroyMatchesAsync(List<Vector2Int> protectedPositions) {
|
||||
List<Vector2Int> matchPositions = await this.matchService.GetMatchPositionsAsync(protectedPositions);
|
||||
HashSet<Vector2Int> matchPositions = await this.matchService.GetMatchPositionsAsync(protectedPositions);
|
||||
List<Vector2Int> initialBombs = await this.bombService.GetInitialBombs(protectedPositions, matchPositions);
|
||||
|
||||
HashSet<Vector2Int> uniqueMatchPositions = new HashSet<Vector2Int>(matchPositions);
|
||||
List<Vector2Int> bombCandidates = uniqueMatchPositions.ToList();
|
||||
List<Vector2Int> initialBombs = await this.bombService.GetInitialBombs(protectedPositions, bombCandidates);
|
||||
|
||||
// If a bomb is part of the match, do NOT destroy matching pieces immediately.
|
||||
// Let the bomb's manhattan-distance explosion destroy them in sequence.
|
||||
if (initialBombs.Count > 0) {
|
||||
await this.bombService.DetonateChainAsync(
|
||||
initialBombs,
|
||||
DestroyAtAsync,
|
||||
this.gameBoard);
|
||||
|
||||
foreach (Vector2Int p in uniqueMatchPositions)
|
||||
foreach (Vector2Int p in matchPositions)
|
||||
await DestroyAtAsync(p);
|
||||
|
||||
await UniTask.Delay(this.gameVariables.fillBoardDelayMs);
|
||||
@@ -242,7 +307,7 @@ namespace Services {
|
||||
|
||||
// For audio SFX
|
||||
bool willBreakAnyNonBombGem = false;
|
||||
foreach (Vector2Int pos in uniqueMatchPositions) {
|
||||
foreach (Vector2Int pos in matchPositions) {
|
||||
Gem g = this.gameBoard.GetGemAt(pos);
|
||||
if (g != null && g.Type != GemType.Bomb) {
|
||||
willBreakAnyNonBombGem = true;
|
||||
@@ -253,18 +318,25 @@ namespace Services {
|
||||
this.audioPresenter.OnMatch(this.gameVariables.matchSfx);
|
||||
|
||||
// For score counting
|
||||
foreach (Vector2Int pos in uniqueMatchPositions) {
|
||||
foreach (Vector2Int pos in matchPositions) {
|
||||
Gem gem = this.gameBoard.GetGemAt(pos);
|
||||
if (gem == null) continue;
|
||||
if (gem.Type == GemType.Bomb) continue;
|
||||
|
||||
this.scoreService.ScoreCheck(gem.ScoreValue);
|
||||
this.scoreService.AddScore(gem.ScoreValue);
|
||||
ReleaseMatchedGems(pos);
|
||||
}
|
||||
await UniTask.Delay(this.gameVariables.fillBoardDelayMs);
|
||||
await MoveGemsDown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys the Gem at the given position.
|
||||
/// </summary>
|
||||
/// <param name="pos">
|
||||
/// Position of the Gem to destroy.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private UniTask DestroyAtAsync(Vector2Int pos) {
|
||||
Gem gem = this.gameBoard.GetGemAt(pos);
|
||||
if (gem == null)
|
||||
@@ -273,11 +345,17 @@ namespace Services {
|
||||
if (gem.Type == GemType.Bomb)
|
||||
this.audioPresenter.OnBombExplosion(this.gameVariables.bombExplodeSfx);
|
||||
|
||||
this.scoreService.ScoreCheck(gem.ScoreValue);
|
||||
this.scoreService.AddScore(gem.ScoreValue);
|
||||
ReleaseMatchedGems(pos);
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the GemView to the Object Pool and sets the Position in the GameBoard to null.
|
||||
/// </summary>
|
||||
/// <param name="position">
|
||||
/// Position of the Gem to release.
|
||||
/// </param>
|
||||
private void ReleaseMatchedGems(Vector2Int position) {
|
||||
Gem currentGem = this.gameBoard.GetGemAt(position);
|
||||
if (currentGem != null)
|
||||
@@ -291,11 +369,13 @@ namespace Services {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves Gems Down to free spaces.
|
||||
/// </summary>
|
||||
private async UniTask MoveGemsDown() {
|
||||
List<FallMove> moves = new List<FallMove>();
|
||||
while (true) {
|
||||
moves.Clear();
|
||||
// Build moves from a snapshot of the current grid state (no mid-wave chaining)
|
||||
for (int x = 0; x < this.gameBoard.Width; x++)
|
||||
{
|
||||
for (int y = 1; y < this.gameBoard.Height; y++)
|
||||
@@ -333,6 +413,9 @@ namespace Services {
|
||||
await FillBoard();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the GameBoard with gems. If there are resulting matches, process them.
|
||||
/// </summary>
|
||||
private async UniTask FillBoard() {
|
||||
await RefillBoard();
|
||||
|
||||
@@ -340,13 +423,15 @@ namespace Services {
|
||||
if (this.matchService.CurrentMatches.Count > 0) {
|
||||
await UniTask.Delay(this.gameVariables.fillBoardDelayMs);
|
||||
|
||||
// In cascades, there is no "creating slot" bomb protection.
|
||||
await DestroyMatchesAsync(new List<Vector2Int>());
|
||||
} else {
|
||||
this.currentState = GameState.Move;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refills the GameBoard with gems.
|
||||
/// </summary>
|
||||
private async UniTask RefillBoard() {
|
||||
List<Gem> gemsToSpawn = new List<Gem>();
|
||||
for (int x = 0; x < this.gameBoard.Width; x++)
|
||||
@@ -358,13 +443,13 @@ namespace Services {
|
||||
GemType gemToUse = RandomUtils.RandomGemType();
|
||||
|
||||
int iterations = 0;
|
||||
while (this.matchService.MatchesAt(new Vector2Int(x, y), (GemType)gemToUse) && iterations < 100)
|
||||
while (this.matchService.MatchesAt(new Vector2Int(x, y), gemToUse) && iterations < 100)
|
||||
{
|
||||
gemToUse = RandomUtils.RandomGemType();
|
||||
iterations++;
|
||||
}
|
||||
|
||||
gemsToSpawn.Add(SetGemAt(new Vector2Int(x,y), (GemType)gemToUse));
|
||||
gemsToSpawn.Add(SetGemAt(new Vector2Int(x,y), gemToUse));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -372,6 +457,12 @@ namespace Services {
|
||||
await SpawnCascade(gemsToSpawn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns gems in cascade.
|
||||
/// </summary>
|
||||
/// <param name="gemsToSpawn">
|
||||
/// List of gems to spawn.
|
||||
/// </param>
|
||||
private async UniTask SpawnCascade(List<Gem> gemsToSpawn)
|
||||
{
|
||||
List<IGrouping<int, Gem>> groups = gemsToSpawn
|
||||
@@ -392,6 +483,12 @@ namespace Services {
|
||||
this.currentState = GameState.Move;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the Presenter for the given GemView from the list to avoid calling its Tick method.
|
||||
/// </summary>
|
||||
/// <param name="gemView">
|
||||
/// GemView to remove from the List of presenters.
|
||||
/// </param>
|
||||
private void RemovePresenterFor(GemView gemView) {
|
||||
if (gemView is null) {
|
||||
return;
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Services {
|
||||
|| touch.phase == TouchPhase.Moved
|
||||
|| touch.phase == TouchPhase.Stationary;
|
||||
|
||||
// Ended/Canceled => not down (we still report position)
|
||||
// Ended/Canceled => not down (we still report the position)
|
||||
if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
|
||||
isDown = false;
|
||||
|
||||
|
||||
@@ -10,14 +10,51 @@ using UnityEngine;
|
||||
namespace Services.Interfaces
|
||||
{
|
||||
public interface IBombService {
|
||||
public BombSpawnRequest? PendingBombSpawn { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Caches last swap action.
|
||||
/// </summary>
|
||||
/// <param name="from">
|
||||
/// Original location of the gem.
|
||||
/// </param>
|
||||
/// <param name="to">
|
||||
/// Destination location of the gem.
|
||||
/// </param>
|
||||
void SetLastSwap(Vector2Int from, Vector2Int to);
|
||||
|
||||
/// <summary>
|
||||
/// Try to spawn a bomb at the last swap location.
|
||||
/// </summary>
|
||||
/// <param name="currentMatches">
|
||||
/// List of current matches.
|
||||
/// </param>
|
||||
void DetectBombSpawnFromLastSwap(HashSet<Gem> currentMatches);
|
||||
List<Vector2Int> ApplyPendingBombSpawns(Action<Vector2Int, GemType, bool> spawnGem);
|
||||
UniTask<List<Vector2Int>> GetInitialBombs(List<Vector2Int> protectedPositions, List<Vector2Int> bombCandidates);
|
||||
|
||||
/// <summary>
|
||||
/// Get a List of bombs that we will detonate.
|
||||
/// </summary>
|
||||
/// <param name="protectedPositions">
|
||||
/// Protected positions, bombs that we don't want to destroy.
|
||||
/// </param>
|
||||
/// <param name="bombCandidates">
|
||||
/// Possible bombs.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
UniTask<List<Vector2Int>> GetInitialBombs(List<Vector2Int> protectedPositions, HashSet<Vector2Int> bombCandidates);
|
||||
|
||||
/// <summary>
|
||||
/// Detonate the bomb(s) part of the match. If there are other bombs within the radius, they will be detonated too sequentially.
|
||||
/// </summary>
|
||||
/// <param name="initialBombs">
|
||||
/// List of bombs to detonate.
|
||||
/// </param>
|
||||
/// <param name="destroyAtAsync">
|
||||
/// Destroy function reference.
|
||||
/// </param>
|
||||
/// <param name="gameBoard">
|
||||
/// Gameboard reference.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
UniTask DetonateChainAsync(
|
||||
IReadOnlyList<Vector2Int> initialBombs,
|
||||
Func<Vector2Int, UniTask> destroyAtAsync,
|
||||
|
||||
@@ -6,6 +6,6 @@ namespace Services.Interfaces {
|
||||
void Setup();
|
||||
|
||||
UniTask<bool> TrySwap(Vector2Int from, Vector2Int to);
|
||||
UniTask<bool> TrySwitch(Vector2Int position);
|
||||
void TrySwitch(Vector2Int position);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,25 @@ using Structs;
|
||||
namespace Services.Interfaces {
|
||||
public interface IMatchService {
|
||||
HashSet<Gem> CurrentMatches { get; }
|
||||
UniTask<List<Vector2Int>> GetMatchPositionsAsync(List<Vector2Int> protectedPositions);
|
||||
/// <summary>
|
||||
/// Get positions of all matches that are not protected.
|
||||
/// </summary>
|
||||
/// <param name="protectedPositions">
|
||||
/// Protected positions, bombs that we don't want to destroy.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
UniTask<HashSet<Vector2Int>> GetMatchPositionsAsync(List<Vector2Int> protectedPositions);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if there are any matches at the given position and type.
|
||||
/// </summary>
|
||||
/// <param name="positionToCheck">
|
||||
/// Position on the gameBoard to check.
|
||||
/// </param>
|
||||
/// <param name="gemTypeToCheck">
|
||||
/// Type of gem to check.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
bool MatchesAt(Vector2Int positionToCheck, GemType gemTypeToCheck);
|
||||
void FindAllMatches();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@ namespace Services.Interfaces {
|
||||
public interface IScoreService {
|
||||
event Action<int> OnScoreChanged;
|
||||
int Score { get; }
|
||||
void ScoreCheck(int value);
|
||||
void AddScore(int value);
|
||||
}
|
||||
}
|
||||
@@ -50,8 +50,8 @@ namespace Services {
|
||||
return false;
|
||||
}
|
||||
|
||||
public UniTask<List<Vector2Int>> GetMatchPositionsAsync(List<Vector2Int> protectedPositions) {
|
||||
List<Vector2Int> matchPositions = new List<Vector2Int>(this.currentMatches.Count);
|
||||
public UniTask<HashSet<Vector2Int>> GetMatchPositionsAsync(List<Vector2Int> protectedPositions) {
|
||||
HashSet<Vector2Int> matchPositions = new HashSet<Vector2Int>();
|
||||
List<Gem> matches = this.currentMatches.ToList();
|
||||
for (int i = 0; i < matches.Count; i++) {
|
||||
Gem match = matches[i];
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Services {
|
||||
private int score = 0;
|
||||
public int Score => this.score;
|
||||
public event Action<int> OnScoreChanged;
|
||||
public void ScoreCheck(int value) {
|
||||
public void AddScore(int value) {
|
||||
this.score += value;
|
||||
|
||||
OnScoreChanged?.Invoke(this.score);
|
||||
|
||||
Reference in New Issue
Block a user