feat: 接入激励视频
This commit is contained in:
673
软著源代码/12-微信SDK与音频成就配置.md
Normal file
673
软著源代码/12-微信SDK与音频成就配置.md
Normal file
@@ -0,0 +1,673 @@
|
||||
# 梗中作乐 V1.0 - 源代码文档(第 12 部分)
|
||||
|
||||
软件名称:梗中作乐
|
||||
版本号:V1.0
|
||||
|
||||
---
|
||||
|
||||
## 第 12 部分:微信 SDK、音频与成就配置
|
||||
|
||||
本部分包含微信小游戏 SDK 封装、音频播放管理器、成就称号配置常量。
|
||||
|
||||
### 12.1 微信 SDK 封装 (assets/scripts/utils/WxSDK.ts)
|
||||
|
||||
```typescript
|
||||
import { sys } from 'cc';
|
||||
|
||||
/**
|
||||
* 微信分享配置
|
||||
*/
|
||||
export interface WxShareConfig {
|
||||
/** 分享标题 */
|
||||
title: string;
|
||||
/** 分享图片 URL 或本地路径 */
|
||||
imageUrl?: string;
|
||||
/** 查询字符串,从这条转发消息进入后,可通过 wx.getLaunchOptionsSync 或 wx.onShow 获取 */
|
||||
query?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信朋友圈分享配置
|
||||
*/
|
||||
export interface WxShareTimelineConfig {
|
||||
/** 分享标题 */
|
||||
title: string;
|
||||
/** 分享图片 URL 或本地路径 */
|
||||
imageUrl?: string;
|
||||
/** 查询字符串 */
|
||||
query?: string;
|
||||
}
|
||||
|
||||
export interface WxPrivacySettingResult {
|
||||
/** true 表示需要用户确认隐私授权 */
|
||||
needAuthorization: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小游戏 SDK 工具类
|
||||
* 封装微信平台相关 API,非微信环境下静默降级
|
||||
*/
|
||||
export class WxSDK {
|
||||
/** 隐私授权请求进行中时复用同一个 Promise,避免启动链路重复弹窗 */
|
||||
private static _privacyAuthorizePromise: Promise<boolean> | null = null;
|
||||
|
||||
/**
|
||||
* 是否处于微信小游戏环境
|
||||
*/
|
||||
static isWechat(): boolean {
|
||||
return sys.platform === sys.Platform.WECHAT_GAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 wx 全局对象(仅微信环境下可用)
|
||||
*/
|
||||
static getWx(): any {
|
||||
if (!WxSDK.isWechat()) return null;
|
||||
return typeof wx !== 'undefined' ? wx : null;
|
||||
}
|
||||
|
||||
// ==================== 登录相关 ====================
|
||||
|
||||
/**
|
||||
* 微信登录,获取临时 code
|
||||
* @returns Promise<string> 登录 code
|
||||
*/
|
||||
static login(): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) {
|
||||
reject(new Error('非微信环境,无法调用 wx.login'));
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.login({
|
||||
success: (res: any) => {
|
||||
if (res.code) {
|
||||
console.log('[WxSDK] wx.login 成功,获取到 code');
|
||||
resolve(res.code);
|
||||
} else {
|
||||
console.error('[WxSDK] wx.login 失败:', res.errMsg);
|
||||
reject(new Error(res.errMsg || 'wx.login 失败'));
|
||||
}
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error('[WxSDK] wx.login 调用失败:', err);
|
||||
reject(new Error(err.errMsg || 'wx.login 调用失败'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 隐私授权相关 ====================
|
||||
|
||||
/**
|
||||
* 检查用户是否需要隐私授权。
|
||||
* 低版本或非微信环境没有隐私拦截能力,按已授权处理。
|
||||
*/
|
||||
static checkPrivacySetting(): Promise<WxPrivacySettingResult> {
|
||||
return new Promise((resolve) => {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) {
|
||||
resolve({ needAuthorization: false });
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof wxApi.getPrivacySetting !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持 getPrivacySetting');
|
||||
resolve({ needAuthorization: false });
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.getPrivacySetting({
|
||||
success: (res: any) => {
|
||||
const needAuthorization = !!res?.needAuthorization;
|
||||
console.log('[WxSDK] 隐私授权检查结果:', res);
|
||||
resolve({ needAuthorization });
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.warn('[WxSDK] 隐私授权检查失败:', err);
|
||||
resolve({ needAuthorization: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动触发微信小游戏隐私授权流程。
|
||||
* 已授权用户会直接 success;低版本或非微信环境直接视为通过。
|
||||
*/
|
||||
static requirePrivacyAuthorize(): Promise<boolean> {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) {
|
||||
console.warn('[WxSDK] 非微信环境,跳过隐私授权');
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (typeof wxApi.requirePrivacyAuthorize !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持 requirePrivacyAuthorize');
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
if (WxSDK._privacyAuthorizePromise) {
|
||||
return WxSDK._privacyAuthorizePromise;
|
||||
}
|
||||
|
||||
WxSDK._privacyAuthorizePromise = new Promise((resolve) => {
|
||||
wxApi.requirePrivacyAuthorize({
|
||||
success: () => {
|
||||
console.log('[WxSDK] 用户已授权隐私');
|
||||
resolve(true);
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.warn('[WxSDK] 用户拒绝或授权失败:', err);
|
||||
resolve(false);
|
||||
},
|
||||
complete: () => {
|
||||
WxSDK._privacyAuthorizePromise = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return WxSDK._privacyAuthorizePromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动阶段使用的隐私授权入口:主动调用 requirePrivacyAuthorize,
|
||||
* 让微信在合适时机触发官方隐私弹窗逻辑。
|
||||
*/
|
||||
static ensurePrivacyAuthorized(): Promise<boolean> {
|
||||
if (!WxSDK.isWechat()) {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
return WxSDK.requirePrivacyAuthorize();
|
||||
}
|
||||
|
||||
// ==================== 分享相关 ====================
|
||||
|
||||
/**
|
||||
* 开启转发/分享菜单
|
||||
* 调用后用户可通过右上角菜单进行转发
|
||||
* @param withShareTicket 是否带 shareTicket,用于获取群信息
|
||||
*/
|
||||
static showShareMenu(withShareTicket: boolean = true): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
wxApi.showShareMenu({
|
||||
withShareTicket,
|
||||
menus: ['shareAppMessage', 'shareTimeline'],
|
||||
success: () => {
|
||||
console.log('[WxSDK] showShareMenu 成功');
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.warn('[WxSDK] showShareMenu 失败', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置被动分享(右上角菜单 "转发给朋友")的内容
|
||||
* 需要在页面加载后尽早调用,只需调用一次
|
||||
* @param config 分享配置
|
||||
*/
|
||||
static onShareAppMessage(config: WxShareConfig): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
wxApi.onShareAppMessage(() => ({
|
||||
title: config.title,
|
||||
imageUrl: config.imageUrl ?? '',
|
||||
query: config.query ?? ''
|
||||
}));
|
||||
|
||||
console.log('[WxSDK] onShareAppMessage 已设置');
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置分享到朋友圈的内容
|
||||
* @param config 朋友圈分享配置
|
||||
*/
|
||||
static onShareTimeline(config: WxShareTimelineConfig): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
if (typeof wxApi.onShareTimeline !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持 onShareTimeline');
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.onShareTimeline(() => ({
|
||||
title: config.title,
|
||||
imageUrl: config.imageUrl ?? '',
|
||||
query: config.query ?? ''
|
||||
}));
|
||||
|
||||
console.log('[WxSDK] onShareTimeline 已设置');
|
||||
}
|
||||
|
||||
/**
|
||||
* 主动触发转发(拉起分享面板)
|
||||
* @param config 分享配置
|
||||
*/
|
||||
static shareAppMessage(config: WxShareConfig): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
wxApi.shareAppMessage({
|
||||
title: config.title,
|
||||
imageUrl: config.imageUrl ?? '',
|
||||
query: config.query ?? ''
|
||||
});
|
||||
|
||||
console.log('[WxSDK] shareAppMessage 已触发');
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键初始化分享功能
|
||||
* 开启分享菜单 + 设置被动分享内容 + 设置朋友圈分享内容
|
||||
* @param config 分享配置
|
||||
*/
|
||||
static initShare(config: WxShareConfig): void {
|
||||
if (!WxSDK.isWechat()) {
|
||||
console.log('[WxSDK] 非微信环境,跳过分享初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
WxSDK.showShareMenu();
|
||||
WxSDK.onShareAppMessage(config);
|
||||
WxSDK.onShareTimeline({
|
||||
title: config.title,
|
||||
imageUrl: config.imageUrl,
|
||||
query: config.query
|
||||
});
|
||||
|
||||
console.log('[WxSDK] 分享功能初始化完成');
|
||||
}
|
||||
|
||||
// ==================== 震动相关 ====================
|
||||
|
||||
/**
|
||||
* 触发短震动(15ms)
|
||||
* 用于轻量级反馈,如按钮点击
|
||||
*/
|
||||
static vibrateShort(): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
wxApi.vibrateShort({
|
||||
type: 'medium',
|
||||
success: () => {
|
||||
console.log('[WxSDK] 短震动成功');
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.warn('[WxSDK] 短震动失败', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发长震动(400ms)
|
||||
* 用于重要反馈,如错误提示
|
||||
*/
|
||||
static vibrateLong(): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
wxApi.vibrateLong({
|
||||
success: () => {
|
||||
console.log('[WxSDK] 长震动成功');
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.warn('[WxSDK] 长震动失败', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 激励视频广告 ====================
|
||||
|
||||
/** 激励视频广告实例(复用) */
|
||||
private static _rewardedVideoAd: any = null;
|
||||
|
||||
/**
|
||||
* 展示激励视频广告
|
||||
* 用户看完广告后返回 true,中途退出或失败返回 false
|
||||
* 非微信环境直接返回 true(开发模式直接通过)
|
||||
* @param adUnitId 广告单元 ID(默认使用项目配置的 ID)
|
||||
* @returns Promise<boolean> 是否看完广告
|
||||
*/
|
||||
static showRewardedVideoAd(adUnitId: string = ''): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) {
|
||||
console.log('[WxSDK] 非微信环境,跳过激励视频广告');
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof wxApi.createRewardedVideoAd !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持激励视频广告');
|
||||
resolve(true);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 复用或创建广告实例
|
||||
if (!WxSDK._rewardedVideoAd) {
|
||||
WxSDK._rewardedVideoAd = wxApi.createRewardedVideoAd({
|
||||
adUnitId: adUnitId,
|
||||
});
|
||||
}
|
||||
|
||||
const ad = WxSDK._rewardedVideoAd;
|
||||
|
||||
// 定义关闭回调(一次性)
|
||||
const onClose = (res: any) => {
|
||||
ad.offClose(onClose);
|
||||
if (res && res.isEnded) {
|
||||
console.log('[WxSDK] 激励视频广告观看完成');
|
||||
resolve(true);
|
||||
} else {
|
||||
console.log('[WxSDK] 激励视频广告中途退出');
|
||||
resolve(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 定义错误回调(一次性)
|
||||
const onError = (err: any) => {
|
||||
ad.offError(onError);
|
||||
ad.offClose(onClose);
|
||||
console.error('[WxSDK] 激励视频广告错误:', err);
|
||||
resolve(false);
|
||||
};
|
||||
|
||||
ad.onClose(onClose);
|
||||
ad.onError(onError);
|
||||
|
||||
// 先尝试 show,如果广告未加载则先 load
|
||||
ad.show().catch(() => {
|
||||
ad.load().then(() => ad.show()).catch((loadErr: any) => {
|
||||
ad.offClose(onClose);
|
||||
ad.offError(onError);
|
||||
console.error('[WxSDK] 激励视频广告加载失败:', loadErr);
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('[WxSDK] 激励视频广告异常:', err);
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 启动参数 ====================
|
||||
|
||||
/**
|
||||
* 从启动参数中获取分享码
|
||||
* @returns 分享码,不存在则返回 null
|
||||
*/
|
||||
static getShareCodeFromLaunch(): string | null {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return null;
|
||||
|
||||
try {
|
||||
const options = wxApi.getLaunchOptionsSync();
|
||||
const code = WxSDK.extractShareCodeFromQuery(options?.query);
|
||||
if (code) {
|
||||
console.log('[WxSDK] 检测到分享码:', code);
|
||||
return code;
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[WxSDK] 获取启动参数失败:', err);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从查询对象(来自 launch options 或 onShow 回调)中提取 shareCode
|
||||
*/
|
||||
static extractShareCodeFromQuery(query: Record<string, any> | null | undefined): string | null {
|
||||
const code = query?.shareCode;
|
||||
return typeof code === 'string' && code.length > 0 ? code : null;
|
||||
}
|
||||
|
||||
// ==================== 前后台生命周期 ====================
|
||||
|
||||
/**
|
||||
* 监听小游戏切到前台事件。
|
||||
* 同一个回调可重复注册多次:内部用 wx.onShow,请确保业务层做幂等处理或在卸载时调用 offAppShow。
|
||||
* @param callback 切前台时触发,包含本次显示对应的 query / scene 等参数
|
||||
*/
|
||||
static onAppShow(callback: (res: { query?: Record<string, any>; scene?: number; path?: string } | undefined) => void): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
if (typeof wxApi.onShow !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持 onShow');
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.onShow(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消监听小游戏切到前台事件
|
||||
*/
|
||||
static offAppShow(callback: (res: any) => void): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
if (typeof wxApi.offShow === 'function') {
|
||||
wxApi.offShow(callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听小游戏切到后台事件
|
||||
*/
|
||||
static onAppHide(callback: () => void): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
if (typeof wxApi.onHide !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持 onHide');
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.onHide(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消监听小游戏切到后台事件
|
||||
*/
|
||||
static offAppHide(callback: () => void): void {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) return;
|
||||
|
||||
if (typeof wxApi.offHide === 'function') {
|
||||
wxApi.offHide(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 隐私授权相关 ====================
|
||||
|
||||
/**
|
||||
* 检查用户是否已授权隐私
|
||||
* @returns Promise<{ needAuthorization: boolean }> needAuthorization 为 false 表示已授权
|
||||
*/
|
||||
export async function checkPrivacySetting(): Promise<{ needAuthorization: boolean }> {
|
||||
return WxSDK.checkPrivacySetting();
|
||||
}
|
||||
|
||||
/**
|
||||
* 引导用户进行隐私授权
|
||||
* 调用后会弹出微信隐私授权弹窗
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
export async function requirePrivacyAuthorize(): Promise<void> {
|
||||
const authorized = await WxSDK.requirePrivacyAuthorize();
|
||||
if (!authorized) {
|
||||
throw new Error('隐私授权失败');
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 用户信息相关 ====================
|
||||
|
||||
/**
|
||||
* 用户信息(头像、昵称)
|
||||
*/
|
||||
export interface WxUserInfo {
|
||||
avatarUrl: string;
|
||||
nickName: string;
|
||||
country?: string;
|
||||
province?: string;
|
||||
city?: string;
|
||||
gender?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户头像和昵称(需要用户主动授权)
|
||||
* @returns Promise<WxUserInfo>
|
||||
*/
|
||||
export async function getUserProfile(): Promise<WxUserInfo> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const wxApi = WxSDK.getWx();
|
||||
if (!wxApi) {
|
||||
// 非微信环境,返回 mock 数据
|
||||
console.warn('[WxSDK] 非微信环境,返回 mock 用户信息');
|
||||
resolve({
|
||||
avatarUrl: '',
|
||||
nickName: '微信用户'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof wxApi.getUserProfile !== 'function') {
|
||||
console.warn('[WxSDK] 当前微信版本不支持 getUserProfile');
|
||||
reject(new Error('当前微信版本不支持 getUserProfile'));
|
||||
return;
|
||||
}
|
||||
|
||||
wxApi.getUserProfile({
|
||||
desc: '用于完善用户资料',
|
||||
success: (res: any) => {
|
||||
if (res.userInfo) {
|
||||
console.log('[WxSDK] 获取用户信息成功');
|
||||
resolve({
|
||||
avatarUrl: res.userInfo.avatarUrl,
|
||||
nickName: res.userInfo.nickName,
|
||||
country: res.userInfo.country,
|
||||
province: res.userInfo.province,
|
||||
city: res.userInfo.city,
|
||||
gender: res.userInfo.gender
|
||||
});
|
||||
} else {
|
||||
console.error('[WxSDK] 获取用户信息失败: 无 userInfo');
|
||||
reject(new Error('获取用户信息失败'));
|
||||
}
|
||||
},
|
||||
fail: (err: any) => {
|
||||
console.error('[WxSDK] 获取用户信息失败:', err);
|
||||
reject(new Error(err.errMsg || '获取用户信息失败'));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 12.2 音频管理器 (assets/scripts/utils/AudioManager.ts)
|
||||
|
||||
```typescript
|
||||
import { AudioClip, AudioSource, Node } from 'cc';
|
||||
|
||||
/**
|
||||
* 音效管理器
|
||||
* 统一管理全局按钮点击等通用音效,避免页面各自维护 AudioSource。
|
||||
*/
|
||||
export class AudioManager {
|
||||
private static _instance: AudioManager | null = null;
|
||||
|
||||
private _clickAudio: AudioClip | null = null;
|
||||
private _hostNode: Node | null = null;
|
||||
private _audioSource: AudioSource | null = null;
|
||||
|
||||
static get instance(): AudioManager {
|
||||
if (!this._instance) {
|
||||
this._instance = new AudioManager();
|
||||
}
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
private constructor() {}
|
||||
|
||||
init(clickAudio: AudioClip | null, hostNode: Node | null): void {
|
||||
this._clickAudio = clickAudio;
|
||||
this._hostNode = hostNode;
|
||||
this._audioSource = null;
|
||||
}
|
||||
|
||||
playButtonClick(): void {
|
||||
this._playOneShot(this._clickAudio);
|
||||
}
|
||||
|
||||
private _playOneShot(clip: AudioClip | null): void {
|
||||
if (!clip) {
|
||||
return;
|
||||
}
|
||||
|
||||
const audioSource = this._ensureAudioSource();
|
||||
audioSource?.playOneShot(clip);
|
||||
}
|
||||
|
||||
private _ensureAudioSource(): AudioSource | null {
|
||||
if (this._audioSource?.isValid) {
|
||||
return this._audioSource;
|
||||
}
|
||||
|
||||
if (!this._hostNode?.isValid) {
|
||||
console.warn('[AudioManager] 未初始化宿主节点,无法播放音效');
|
||||
return null;
|
||||
}
|
||||
|
||||
this._audioSource = this._hostNode.getComponent(AudioSource) ?? this._hostNode.addComponent(AudioSource);
|
||||
return this._audioSource;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 12.3 成就称号配置 (assets/scripts/config/AchievementTitleConfig.ts)
|
||||
|
||||
```typescript
|
||||
export interface AchievementTitleConfigItem {
|
||||
readonly seriesName: string;
|
||||
readonly levelName: string;
|
||||
readonly clearsToNext: number;
|
||||
}
|
||||
|
||||
const createSeries = (seriesName: string, levelCount: number, clearsToNext: number): AchievementTitleConfigItem[] => {
|
||||
return Array.from({ length: levelCount }, (_, index) => ({
|
||||
seriesName,
|
||||
levelName: `${seriesName}${index + 1}级`,
|
||||
clearsToNext
|
||||
}));
|
||||
};
|
||||
|
||||
export const ACHIEVEMENT_TITLE_CONFIG: readonly AchievementTitleConfigItem[] = [
|
||||
...createSeries('冷场小白', 2, 3),
|
||||
...createSeries('尬笑学生', 2, 3),
|
||||
...createSeries('浅梗游民', 3, 4),
|
||||
...createSeries('热梗新秀', 6, 5),
|
||||
...createSeries('笑点刺客', 6, 5),
|
||||
...createSeries('爆梗高手', 8, 6),
|
||||
...createSeries('幽默大师', 10, 8),
|
||||
...createSeries('爆笑领主', 10, 8),
|
||||
...createSeries('梗王之王', 20, 8)
|
||||
];
|
||||
|
||||
export const INFINITE_ACHIEVEMENT_TITLE = {
|
||||
seriesName: '幽默始祖',
|
||||
levelNamePrefix: '幽默始祖',
|
||||
clearsToNext: 8
|
||||
} as const;
|
||||
```
|
||||
Reference in New Issue
Block a user