2048游戏开发笔记4 & 音效 cocos3.8.7

滑动音效

TypeScript 复制代码
//AudioMgr.ts
import { Node, AudioSource, AudioClip, resources, director } from 'cc';
/**
 * @en
 * this is a sington class for audio play, can be easily called from anywhere in you project.
 * @zh
 * 这是一个用于播放音频的单件类,可以很方便地在项目的任何地方调用。
 */ 
export class AudioMgr {
    private static _inst: AudioMgr;
    public static get inst(): AudioMgr {
        if (this._inst == null) {
            this._inst = new AudioMgr();
        }
        return this._inst;
    }

    private _audioSource: AudioSource;
    constructor() {
        //@en create a node as audioMgr
        //@zh 创建一个节点作为 audioMgr
        let audioMgr = new Node();
        audioMgr.name = '__audioMgr__';

        //@en add to the scene.
        //@zh 添加节点到场景
        director.getScene().addChild(audioMgr);

        //@en make it as a persistent node, so it won't be destroied when scene change.
        //@zh 标记为常驻节点,这样场景切换的时候就不会被销毁了
        director.addPersistRootNode(audioMgr);

        //@en add AudioSource componrnt to play audios.
        //@zh 添加 AudioSource 组件,用于播放音频。
        this._audioSource = audioMgr.addComponent(AudioSource);
    }

    public get audioSource() {
        return this._audioSource;
    }

    /**
     * @en
     * play short audio, such as strikes,explosions
     * @zh
     * 播放短音频,比如 打击音效,爆炸音效等
     * @param sound clip or url for the audio
     * @param volume 
     */
    playOneShot(sound: AudioClip | string, volume: number = 1.0) {
        if (sound instanceof AudioClip) {
            this._audioSource.playOneShot(sound, volume);
        }
        else {
            resources.load(sound, (err, clip: AudioClip) => {
                if (err) {
                    console.log(err);
                }
                else {
                    this._audioSource.playOneShot(clip, volume);
                }
            });
        }
    }

    /**
     * @en
     * play long audio, such as the bg music
     * @zh
     * 播放长音频,比如 背景音乐
     * @param sound clip or url for the sound
     * @param volume 
     */
    play(sound: AudioClip | string, volume: number = 1.0) {
        if (sound instanceof AudioClip) {
            this._audioSource.stop();
            this._audioSource.clip = sound;
            this._audioSource.loop=true;
            this._audioSource.play();
            this.audioSource.volume = volume;
        }
        else {
            resources.load(sound, (err, clip: AudioClip) => {
                if (err) {
                    console.log(err);
                }
                else {
                    this._audioSource.stop();
                    this._audioSource.clip = clip;
                    this._audioSource.loop=true;
                    this._audioSource.play();
                    this.audioSource.volume = volume;
                }
            });
        }
    }

    /**
     * stop the audio play
     */
    stop() {
        this._audioSource.stop();
    }

    /**
     * pause the audio play
     */
    pause() {
        this._audioSource.pause();
    }

    /**
     * resume the audio play
     */
    resume(){
        this._audioSource.play();
    }
}
TypeScript 复制代码
 // 声明音频资源属性
    @property(AudioClip)
    clickAudio:AudioClip = null;


private emitSwipeEvent(direction: SwipeDirection) {
         // 播放滑动音效(方向有效才播)
        if (direction !== SwipeDirection.None && this.clickAudio) {
            AudioMgr.inst.playOneShot(this.clickAudio);
        }

        if (this.chessboardNode) {
            this.chessboardNode.emit('swipe', direction);
            console.log(`已向棋盘发送滑动事件 - 方向: ${this.getDirectionText(direction)}`); // 事件发送日志
        } else {
            console.warn("未设置chessboardNode,无法发送滑动事件"); // 警告日志
        }
    }

✅ 实现效果

只要玩家滑动了(方向有效),就会播放一次 click.mp3,不重复、不卡顿。

✅ 音频资源声明
TypeScript 复制代码
@property(AudioClip)
clickAudio: AudioClip = null;
  • 在编辑器里把 click.mp3 拖到这个字段上,才能播放。

✅ 播放时机:滑动方向确定后
TypeScript 复制代码
private emitSwipeEvent(direction: SwipeDirection) {
    // ✅ 播放滑动音效(方向有效才播)
    if (direction !== SwipeDirection.None && this.clickAudio) {
        // 关键
        AudioMgr.inst.playOneShot(this.clickAudio);
    }

}

✅ 为什么这样写?

关键点 说明
direction !== SwipeDirection.None 防止轻微触摸 也播音效,只播有效滑动
playOneShot 不打断其他音效,播完就结束,不循环
AudioMgr.inst.playOneShot(...) 用单例管理器,全局唯一音频源,不依赖场景节点

✅ 总结

方向有效 → 播放一次 click.mp3 → 不卡顿、不重叠、不依赖场景。


完整源码

cocos3.8.72048游戏完整源码资源-CSDN下载

相关推荐
chenzhou__2 小时前
LinuxC语言并发程序笔记(第二十天)
linux·c语言·笔记·学习
北顾南栀倾寒3 小时前
[杂学笔记]C++编译过程、静态链接库与动态链接库的区别、动态多态的实现机制、虚拟地址空间分布与C++内存分布、volatile的作用以及使用场景
笔记
星轨初途5 小时前
数据结构二叉树之链式结构(3)(下)
c语言·网络·数据结构·经验分享·笔记·后端
智者知已应修善业6 小时前
【51单片机LED贪吃蛇】2023-3-27
c语言·c++·经验分享·笔记·嵌入式硬件·51单片机
charlie11451419110 小时前
从 0 开始:在 WSL + VSCode 上利用 Maven 构建 Java Spring Boot 工程
java·笔记·vscode·后端·学习·maven·springboot
思成不止于此16 小时前
【C++ 数据结构】二叉搜索树:原理、实现与核心操作全解析
开发语言·数据结构·c++·笔记·学习·搜索二叉树·c++40周年
碧海潮生_CC17 小时前
【CUDA笔记】03 CUDA GPU 架构与一般的程序优化思路(下)
笔记·架构·cuda
钟屿17 小时前
Back to Basics: Let Denoising Generative Models Denoise 论文阅读学习
论文阅读·人工智能·笔记·学习·计算机视觉
d111111111d18 小时前
SPI通信协议--在STM32中介绍(学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习
愚昧之山绝望之谷开悟之坡18 小时前
业务接待-公务接待-商务接待
笔记