Add Audio

This commit is contained in:
2025-12-17 01:46:24 +08:00
parent 3786863b00
commit 9f2ef833b2
12 changed files with 116 additions and 2 deletions

View File

@@ -59,6 +59,8 @@ MonoBehaviour:
scoreValue: 10 scoreValue: 10
width: 7 width: 7
height: 7 height: 7
matchSfx: {fileID: 8300000, guid: 5eee8c96923a90d4a88dcd7369fcbc1a, type: 3}
bombExplodeSfx: {fileID: 8300000, guid: 9dcc9b1297952c446a5571fdb2fb7a2f, type: 3}
bombDelay: 2 bombDelay: 2
bombRadius: 2 bombRadius: 2
dropHeight: 2 dropHeight: 2

View File

@@ -0,0 +1,21 @@
using Services.Interfaces;
using UnityEngine;
namespace Presenter {
public class AudioPresenter {
private readonly IAudioService audioService;
public AudioPresenter(IAudioService audioService) {
this.audioService = audioService;
}
public void OnMatch(AudioClip clip) {
this.audioService.PlaySound(clip);
}
public void OnBombExplosion (AudioClip clip) {
this.audioService.PlaySound(clip);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 152ac95510fc404ebbeff098e3214802
timeCreated: 1765905002

View File

@@ -35,6 +35,8 @@ namespace Scopes
builder.Register<IBombService, BombService>(Lifetime.Scoped); builder.Register<IBombService, BombService>(Lifetime.Scoped);
builder.Register<AudioPresenter>(Lifetime.Scoped);
builder.Register<ScorePresenter>(Lifetime.Scoped); builder.Register<ScorePresenter>(Lifetime.Scoped);
builder.Register<IGameBoardService, GameBoardService>(Lifetime.Scoped).AsImplementedInterfaces(); builder.Register<IGameBoardService, GameBoardService>(Lifetime.Scoped).AsImplementedInterfaces();

View File

@@ -9,6 +9,9 @@ namespace Scopes {
{ {
builder.RegisterComponentInHierarchy<InputService>() builder.RegisterComponentInHierarchy<InputService>()
.As<IInputService>(); .As<IInputService>();
builder.Register<IAudioService, AudioService>(Lifetime.Scoped)
.AsImplementedInterfaces();
} }
} }
} }

View File

@@ -7,10 +7,16 @@ namespace ScriptableObjects {
[Header("Prefabs")] [Header("Prefabs")]
public GameObject bgTilePrefabs; public GameObject bgTilePrefabs;
public GemTypeValues[] gemsPrefabs; public GemTypeValues[] gemsPrefabs;
[Header("Board Setup")] [Header("Board Setup")]
public int width; public int width;
public int height; public int height;
[Header("Audio")]
public AudioClip matchSfx;
public AudioClip bombExplodeSfx;
[Header("Bomb")] [Header("Bomb")]
[Tooltip("How long before the gems around the bomb explode")] [Tooltip("How long before the gems around the bomb explode")]
public float bombDelay = 0.1f; public float bombDelay = 0.1f;

View File

@@ -0,0 +1,43 @@
using System;
using Services.Interfaces;
using UnityEngine;
using VContainer.Unity;
namespace Services
{
public sealed class AudioService : IAudioService, IInitializable, IDisposable
{
private readonly float volume = 1f;
private GameObject gameObject;
private AudioSource source;
public void Initialize()
{
this.gameObject = new GameObject("AudioService");
UnityEngine.Object.DontDestroyOnLoad(this.gameObject);
this.source = this.gameObject.AddComponent<AudioSource>();
this.source.playOnAwake = false;
this.source.loop = false;
this.source.volume = this.volume;
}
public void PlaySound(AudioClip clip)
{
if (clip == null) return;
if (this.source == null) return; // In case called before Initialize in some edge setup
this.source.PlayOneShot(clip);
}
public void Dispose()
{
if (this.gameObject != null)
{
UnityEngine.Object.Destroy(this.gameObject);
this.gameObject = null;
this.source = null;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6f530c8e01a54246bfc83a74bbbb1fc1
timeCreated: 1765904827

View File

@@ -21,6 +21,7 @@ namespace Services {
private readonly GameVariables gameVariables; private readonly GameVariables gameVariables;
private readonly IMatchService matchService; private readonly IMatchService matchService;
private readonly IScoreService scoreService; private readonly IScoreService scoreService;
private readonly AudioPresenter audioPresenter;
private readonly IBombService bombService; private readonly IBombService bombService;
private readonly IObjectPool<GemView> objectPool; private readonly IObjectPool<GemView> objectPool;
private readonly Transform gemsHolder; private readonly Transform gemsHolder;
@@ -32,7 +33,7 @@ namespace Services {
private GameState currentState = GameState.Move; private GameState currentState = GameState.Move;
#endregion #endregion
public GameBoardService(IGameBoard gameBoard, GameVariables gameVariables, IMatchService matchService, IScoreService scoreSerivce, IBombService bombService, IObjectPool<GemView> objectPool, Transform gemsHolder, ScorePresenter scorePresenter) { public GameBoardService(IGameBoard gameBoard, GameVariables gameVariables, IMatchService matchService, IScoreService scoreSerivce, IBombService bombService, IObjectPool<GemView> objectPool, Transform gemsHolder, ScorePresenter scorePresenter, AudioPresenter audioPresenter) {
this.gameBoard = gameBoard; this.gameBoard = gameBoard;
this.gameVariables = gameVariables; this.gameVariables = gameVariables;
this.matchService = matchService; this.matchService = matchService;
@@ -41,6 +42,7 @@ namespace Services {
this.objectPool = objectPool; this.objectPool = objectPool;
this.gemsHolder = gemsHolder; this.gemsHolder = gemsHolder;
this.scorePresenter = scorePresenter; this.scorePresenter = scorePresenter;
this.audioPresenter = audioPresenter;
} }
public void Tick() { public void Tick() {
@@ -224,6 +226,19 @@ namespace Services {
return; return;
} }
bool willBreakAnyNonBombGem = false;
foreach (Vector2Int pos in matchPositions) {
Gem gem = GetGem(pos);
if (gem == null) continue;
if (gem.Type == GemType.Bomb) continue;
willBreakAnyNonBombGem = true;
break;
}
if (willBreakAnyNonBombGem)
this.audioPresenter.OnMatch(this.gameVariables.matchSfx);
foreach (Vector2Int pos in matchPositions.Distinct().ToList()) { foreach (Vector2Int pos in matchPositions.Distinct().ToList()) {
Gem gem = GetGem(pos); Gem gem = GetGem(pos);
if (gem == null) continue; if (gem == null) continue;
@@ -248,6 +263,9 @@ namespace Services {
Gem gem = GetGem(pos); Gem gem = GetGem(pos);
if (gem == null) if (gem == null)
return UniTask.CompletedTask; return UniTask.CompletedTask;
if (gem.Type == GemType.Bomb)
this.audioPresenter.OnBombExplosion(this.gameVariables.bombExplodeSfx);
this.scoreService.ScoreCheck(gem.ScoreValue); this.scoreService.ScoreCheck(gem.ScoreValue);
DestroyMatchedGems(pos); DestroyMatchedGems(pos);

View File

@@ -0,0 +1,7 @@
using UnityEngine;
namespace Services.Interfaces {
public interface IAudioService {
void PlaySound(AudioClip clip);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d04aef7bff08494fbae7a04db1fcda22
timeCreated: 1765904685

View File

@@ -1,3 +1,4 @@
using Presenter;
using Services.Interfaces; using Services.Interfaces;
using UnityEngine; using UnityEngine;
using VContainer.Unity; using VContainer.Unity;
@@ -10,12 +11,14 @@ namespace Services
private readonly IObjectPool<GemView> gemViewPool; private readonly IObjectPool<GemView> gemViewPool;
private readonly IGameBoardService gameBoardService; private readonly IGameBoardService gameBoardService;
private readonly IInputService inputService; private readonly IInputService inputService;
private readonly AudioPresenter audioPresenter;
public LevelEntryPoint(IObjectPool<GemView> gemViewPool, IGameBoardService gameBoardService, IInputService inputService) public LevelEntryPoint(IObjectPool<GemView> gemViewPool, IGameBoardService gameBoardService, IInputService inputService, AudioPresenter audioPresenter)
{ {
this.gemViewPool = gemViewPool; this.gemViewPool = gemViewPool;
this.gameBoardService = gameBoardService; this.gameBoardService = gameBoardService;
this.inputService = inputService; this.inputService = inputService;
this.audioPresenter = audioPresenter;
} }
public void Start() public void Start()