This commit is contained in:
huanghaipeng 2025-10-24 14:05:35 +08:00
parent f2ce60dc3e
commit 647d3c8884
5 changed files with 510 additions and 26 deletions

View File

@ -401,6 +401,15 @@ export default class JiaZai extends cc.Component {
let top = this.node.getChildByName("Load").getChildByName("Top");
top.getChildByName("hammer").active = false;
}
// 加载广告
cc.fx.GameTool.preloadRewardedVideoAd().then((success) => {
if (success) {
console.log("HomeScene广告预加载初始化成功");
} else {
console.log("HomeScene广告预加载初始化失败");
}
});
}
checkDailyQuests() {

View File

@ -244,6 +244,15 @@ export default class MapConroler extends cc.Component {
this.Block_Color = GameManager._instance.Block_Color;
// this.particleEffects = GameManager._instance.particleEffects;
this.initMap();
// 加载广告
cc.fx.GameTool.preloadRewardedVideoAd().then((success) => {
if (success) {
console.log("GameScene广告预加载初始化成功");
} else {
console.log("GameScene广告预加载初始化失败");
}
});
}
//道具数量
setPropNum() {
@ -1889,11 +1898,26 @@ export default class MapConroler extends cc.Component {
//双倍领取金币
getDoubleCoin() {
cc.fx.GameConfig.GM_INFO.rewardAdCoin = 2;
console.log("领取双倍奖励", cc.fx.GameConfig.GM_INFO.rewardAdCoin);
}
//播放双倍金币广告
showDoubleCoin() {
let overData = {
ad_placement_name: "1001", //内部广告位名称
current_page: "GameScene" //所在页面
}
var callback = function (isType) {
if (isType) {
// 领取双倍奖励
console.log("领取双倍奖励");
this.getDoubleCoin();
} else {
}
}
cc.fx.GameTool.onShowVideo(callback, overData)
}
//判断游戏成功下一关

View File

@ -495,6 +495,15 @@ export default class SceneManager extends cc.Component {
}
}
openLoad() {
this.node.getChildByName("Loading").active = true;
this.node.getChildByName("Loading").getChildByName("load").stopAllActions();
this.node.getChildByName("Loading").getChildByName("load").runAction(cc.rotateTo(2, 1080).repeatForever());
}
closeLoad() {
this.node.getChildByName("Loading").active = false;
}
update(dt) {

View File

@ -264,6 +264,8 @@ export namespace MiniGameSdk {
class ADVideo {
private _adUid: string;
private _adVideo: any = null;
private _isLoaded: boolean = false;
private _isLoading: boolean = false;
get aduid() {
return this._adUid;
@ -273,6 +275,120 @@ export namespace MiniGameSdk {
this._adUid = adUid;
}
/**
* 广
*/
preload(): Promise<void> {
return new Promise((resolve, reject) => {
if (!isWechat() && !isBytedance()) {
resolve();
return;
}
// 每次预加载都创建新的实例
this._cleanup();
// 标记为正在加载
this._isLoading = true;
this._isLoaded = false;
let adInstance;
// 创建广告实例
if (isWechat()) {
try {
// @ts-ignore
adInstance = wx.createRewardedVideoAd({
adUnitId: this._adUid
});
} catch (e) {
console.error('Failed to create rewarded video ad:', e);
this._isLoading = false;
reject(e);
return;
}
} else if (isBytedance()) {
// @ts-ignore
adInstance = tt.createRewardedVideoAd({
adUnitId: this._adUid,
multiton: true,
multitonRewardMsg: ['多1次奖励', '再多一次奖励', '再多一次奖励'],
multitonRewardTimes: 3,
});
} else {
adInstance = null;
}
if (!adInstance) {
this._isLoading = false;
reject(new Error('Failed to create ad video instance'));
return;
}
// 设置超时处理
let loadTimeout: any = null;
const clearTimer = () => {
if (loadTimeout) {
clearTimeout(loadTimeout);
loadTimeout = null;
}
};
loadTimeout = setTimeout(() => {
console.log('Ad preload timeout');
this._isLoaded = false;
this._isLoading = false;
try {
adInstance.offLoad?.(onLoadHandler);
adInstance.offError?.(onErrorHandler);
} catch (e) {
console.log('Error removing listeners:', e);
}
this._cleanup();
resolve();
}, 5000); // 5秒加载超时
// 设置加载监听
const onLoadHandler = () => {
clearTimer();
console.log('Ad preload success');
this._adVideo = adInstance;
this._isLoaded = true;
this._isLoading = false;
try {
adInstance.offLoad?.(onLoadHandler);
} catch (e) {
console.log('Error removing load listener:', e);
}
resolve();
};
const onErrorHandler = (err: { errMsg: string, errCode: number }) => {
clearTimer();
console.log('Ad preload error:', err);
this._isLoaded = false;
this._isLoading = false;
try {
adInstance.offError?.(onErrorHandler);
} catch (e) {
console.log('Error removing error listener:', e);
}
this._cleanup();
resolve();
};
adInstance.onLoad(onLoadHandler);
adInstance.onError(onErrorHandler);
// 开始加载广告
adInstance.load().catch((err: any) => {
clearTimer();
console.log('Ad load error:', err);
this._isLoaded = false;
this._isLoading = false;
this._cleanup();
resolve();
});
});
}
/**
* 广广010~maxVideoCount
* @param onResult res是EAdVideoResult定义count是用户看了多少个视频广告
@ -280,8 +396,10 @@ export namespace MiniGameSdk {
* @param maxVideoCount 3
* @returns
*/
show(onResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3): void {
show(onResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3, video_data: any = null): void {
console.log("调用广告显示");
let callback = (state: EAdVideoResult, count: number) => {
// 确保广告实例被清理
onResult?.call(target, state, count);
}
@ -291,31 +409,71 @@ export namespace MiniGameSdk {
return;
}
// 每次调用都创建新的广告实例以确保可以重复调用
this._cleanup();
let onAdVideoClosed = (res: any) => {
this._adVideo?.offClose(onAdVideoClosed);
if (this._adVideo) {
try {
this._adVideo.offClose?.(onAdVideoClosed);
} catch (e) {
console.log('Error removing close listener:', e);
}
}
let result: EAdVideoResult;
let count: number;
if (isWechat()) {
if (res && res.isEnded || res === undefined) {
callback(EAdVideoResult.ACCEPT, 1);
result = EAdVideoResult.ACCEPT;
count = 1;
} else {
callback(EAdVideoResult.REJECT, 0);
result = EAdVideoResult.REJECT;
count = 0;
}
} else if (isBytedance()) {
let resConverted = res as { isEnded: boolean, count: number };
if (resConverted && resConverted.count > 0) {
callback(EAdVideoResult.ACCEPT, resConverted.count);
result = EAdVideoResult.ACCEPT;
count = resConverted.count;
} else {
callback(EAdVideoResult.REJECT, 0);
result = EAdVideoResult.REJECT;
count = 0;
}
}
// 确保在回调之前清理广告实例
this._cleanup();
callback(result, count);
}
let responseData = {
ad_type: "激励视频", //广告类型
ad_placement_name: video_data?.ad_placement_name || "", //内部广告位名称 //2000复活 道具 2001 2002 2003
ad_placement_id: "adunit-aa9a28e1631bf16f", //内部广告位ID
current_page: video_data?.current_page || "", //所在页面
error_detail_info: "", //错误信息
error_detail_code: "", //错误码
is_filled_success: false //是否完整播放
}
this._adVideo?.offClose(onAdVideoClosed);
if (isWechat()) {
// @ts-ignore
this._adVideo = wx.createRewardedVideoAd({
adUnitId: this._adUid
});
try {
// @ts-ignore
this._adVideo = wx.createRewardedVideoAd({
adUnitId: this._adUid
});
responseData.is_filled_success = true;
cc.fx.GameTool.shushu_Track("ad_response", responseData);
} catch (e) {
console.error('Failed to create rewarded video ad:', e);
responseData.is_filled_success = false;
responseData.error_detail_info = e.toString();
responseData.error_detail_code = e.errCode?.toString() || "";
cc.fx.GameTool.shushu_Track("ad_response", responseData);
this._cleanup();
callback(EAdVideoResult.ERROR, 0);
return;
}
} else if (isBytedance()) {
// @ts-ignore
this._adVideo = tt.createRewardedVideoAd({
@ -328,29 +486,99 @@ export namespace MiniGameSdk {
this._adVideo = null;
}
// 确保广告对象已创建
if (!this._adVideo) {
this._cleanup();
callback(EAdVideoResult.ERROR, 0);
return;
}
this._adVideo?.onLoad(() => {
this._adVideo.onLoad(() => {
console.log('Ad load success');
});
this._adVideo?.onError((err: { errMsg: string, errCode: number }) => {
this._adVideo.onError((err: { errMsg: string, errCode: number }) => {
console.log('Ad video error:', err);
if (this._adVideo) {
try {
this._adVideo.offError?.();
} catch (e) {
console.log('Error removing error listener:', e);
}
}
responseData.is_filled_success = false;
responseData.error_detail_info = err.toString();
responseData.error_detail_code = err.errCode?.toString() || "";
cc.fx.GameTool.shushu_Track("ad_response", responseData);
if (err.errCode) {
console.log('Ad video error code:', err.errCode);
}
// 出错后清理实例
this._cleanup();
callback(EAdVideoResult.ERROR, 0);
});
this._adVideo?.onClose(onAdVideoClosed);
this._adVideo.onClose(onAdVideoClosed);
this._adVideo?.show().catch(() => {
this._adVideo?.load().then(() =>
this._adVideo?.show()).catch((err: { errMsg: string, errCode: number }) => {
console.log('Catch video ad error:', err);
let showData = {
ad_type: "激励视频", //广告类型
ad_placement_name: video_data?.ad_placement_name || "", //内部广告位名称 //2000复活 道具 2001 2002 2003
ad_placement_id: "adunit-aa9a28e1631bf16f", //内部广告位ID
current_page: video_data?.current_page || "", //所在页面
error_detail_info: "", //错误信息
error_detail_code: "", //错误码
is_show_success: false //是否完整播放
}
// 尝试显示广告
this._adVideo.show().catch((err: { errMsg: string, errCode: number }) => {
console.log('Show video ad error:', err);
// 尝试加载广告后再显示
if (this._adVideo) {
this._adVideo.load().then(() => {
showData.is_show_success = true;
cc.fx.GameTool.shushu_Track("ad_show", showData);
cc.fx.GameConfig.GM_INFO.videoTime = Math.floor(Date.now() / 1000);
return this._adVideo?.show();
}).catch((loadErr: { errMsg: string, errCode: number }) => {
showData.is_show_success = false;
showData.error_detail_info = loadErr.errMsg;
showData.error_detail_code = loadErr.errCode.toString();
cc.fx.GameTool.shushu_Track("ad_show", showData);
console.log('Load and show video ad error:', loadErr);
if (loadErr.errCode) {
console.log('Load error code:', loadErr.errCode);
}
// 出错后清理实例
this._cleanup();
callback(EAdVideoResult.ERROR, 0);
});
} else {
this._cleanup();
callback(EAdVideoResult.ERROR, 0);
}
});
}
private _cleanup() {
if (this._adVideo) {
try {
// 移除所有事件监听器
this._adVideo.offLoad?.();
this._adVideo.offError?.();
this._adVideo.offClose?.();
} catch (e) {
console.log('Error removing ad event listeners:', e);
}
}
this._adVideo = null;
this._isLoaded = false;
this._isLoading = false;
}
destory() {
this._adVideo?.destory();
this._cleanup();
}
}
@ -381,10 +609,40 @@ export namespace MiniGameSdk {
private _interstitial: ADInterstitial;
private _banner: ADBanner;
private _customs: Record<string, ADCustom> = {};
private _preloadPromise: Promise<void> | null = null; // 用于跟踪预加载状态
private constructor() {
}
/**
* 广
* @param adUid 广ID
* @returns Promise<void>
*/
public preloadVideo(adUid: string): Promise<void> {
// 如果已有相同广告ID的实例先销毁
if (this._video && this._video.aduid !== adUid) {
this._video.destory();
this._video = null;
}
// 创建新实例(如果需要)
if (!this._video) {
this._video = new ADVideo(adUid);
}
// 执行预加载
this._preloadPromise = this._video.preload();
return this._preloadPromise;
}
/**
* 广
* @returns Promise<void>
*/
public isPreloadReady(): Promise<void> {
console.log("加载广告中...", this._preloadPromise)
return this._preloadPromise || Promise.resolve();
}
/**
* 广showBanner时才会显示
@ -491,14 +749,16 @@ export namespace MiniGameSdk {
* @param target onVideoResult的拥有者
* @param maxVideoCount 3count的结果永远是1或0
*/
public showVideo(adUid: string, onVideoResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3) {
if (this._video && this._video.aduid === adUid) {
this._video.show(onVideoResult, target, maxVideoCount);
} else {
this._video?.destory();
public showVideo(adUid: string, video_data, onVideoResult: (res: EAdVideoResult, count: number) => void, target?: any, maxVideoCount: number = 3) {
// 只有在广告ID不匹配时才重新创建实例
if (this._video && this._video.aduid !== adUid) {
this._video.destory();
this._video = new ADVideo(adUid);
} else if (!this._video) {
this._video = new ADVideo(adUid);
this._video.show(onVideoResult, target, maxVideoCount);
}
this._video.show(onVideoResult, target, maxVideoCount, video_data);
}
/**

View File

@ -1,4 +1,5 @@
import JiaZai from "../../JiaZai";
import MapConroler from "../../Map";
import Freeze from "../../prop/Freeze";
import SceneManager from "../../SceneManager";
@ -1507,7 +1508,188 @@ var GameTool = {
return null;
},
onShowVideo(callback: Function, videoData: any) {
console.log("调用广告");
if (typeof wx !== 'undefined' && wx !== null) {
let scene = null;
if (videoData.current_page == "HomeScene") {
const jiazaiNode = cc.find("Canvas"); // 假设 JiaZai 挂在 Canvas 节点
if (jiazaiNode) {
scene = jiazaiNode.getComponent(JiaZai);
if (scene) {
scene.openLoad();
}
}
}
else if (videoData.current_page == "GameScene") {
const canvasTemp = cc.find("Canvas"); // 假设 Canvas 节点
if (canvasTemp) {
scene = canvasTemp.getComponent("SceneManager");
if (scene) {
scene.openLoad();
}
}
}
let requestData = {
ad_type: "激励视频", //广告类型
ad_placement_name: videoData.ad_placement_name, //内部广告位名称 1001 双倍金币
ad_placement_id: "adunit-aa9a28e1631bf16f", //内部广告位ID
current_page: videoData.current_page, //所在页面
}
cc.fx.GameTool.shushu_Track("ad_request", requestData);
cc.fx.GameConfig.GM_INFO.videoTime = Math.floor(Date.now() / 1000);
// 添加超时处理
const timeoutId = setTimeout(() => {
if (scene) scene.closeLoad();
MiniGameSdk.API.showToast('广告加载超时,请稍后再试');
// 调用回调并传入错误状态
callback(false);
}, 6000); // 6秒超时
cc.fx.GameTool.waitForAdPreload().then(() => {
MiniGameSdk.AdvertManager.instance.showVideo('adunit-aa9a28e1631bf16f', videoData, (res: MiniGameSdk.EAdVideoResult, count: number) => {
if (timeoutId) clearTimeout(timeoutId);
console.log('用户看的视频广告个数是:', count);
console.log('用户观看视频广告结果:', res);
if (scene) scene.closeLoad();
let duration = Math.floor(Date.now() / 1000) - cc.fx.GameConfig.GM_INFO.videoTime;
if (duration <= 0) duration = 0;
let data = {
ad_type: "激励视频", //广告类型
ad_placement_name: videoData.ad_placement_name, //内部广告位名称 //2000复活 道具 2001 2002 2003
ad_placement_id: "adunit-aa9a28e1631bf16f", //内部广告位ID
current_page: videoData.current_page, //所在页面
ad_duration: duration, //广告展示时长
ad_play_duration: 30, //广告播放时长
is_complete_play: false //是否完整播放
}
switch (res) {
case MiniGameSdk.EAdVideoResult.ACCEPT:
data.is_complete_play = true;
MiniGameSdk.API.showToast('用户看完广告,可以奖励');
cc.fx.GameTool.shushu_Track("ad_close", data);
callback(true, "ad");
cc.fx.GameTool.preloadRewardedVideoAd(true);
break;
case MiniGameSdk.EAdVideoResult.REJECT:
data.is_complete_play = false;
MiniGameSdk.API.showToast('广告中断,未获得奖励');
cc.fx.GameTool.shushu_Track("ad_close", data);
callback(false);
cc.fx.GameTool.preloadRewardedVideoAd(true);
break;
case MiniGameSdk.EAdVideoResult.ERROR:
MiniGameSdk.API.showToast('广告加载失败,请稍后再试');
callback(false);
cc.fx.GameTool.preloadRewardedVideoAd(true);
break;
default:
// 其他情况,不作处理
break;
}
});
})
}
},
// 预加载激励视频广告
preloadRewardedVideoAd(force: boolean = false): Promise<boolean> {
console.log("开始预加载激励视频广告, force:", force);
// 如果不是强制重新加载,检查是否已经有预加载正在进行或已完成
if (!force && this._lastPreloadTime) {
const now = Date.now();
// 如果距离上次预加载不到5分钟不重复预加载
if (now - this._lastPreloadTime < 5 * 60 * 1000) {
console.log("广告预加载间隔时间不足,跳过本次预加载");
return Promise.resolve(true);
}
}
this._lastPreloadTime = Date.now();
return new Promise((resolve) => {
// 使用 setTimeout 确保在场景加载完成后再预加载广告
setTimeout(() => {
try {
// 预加载激励视频广告
const preloadPromise = MiniGameSdk.AdvertManager.instance.preloadVideo('adunit-aa9a28e1631bf16f');
// 添加超时处理避免预加载Promise永远处于pending状态
const preloadTimeout = setTimeout(() => {
console.log('预加载激励视频广告超时');
resolve(true);
}, 5000);// 5秒预加载超时
preloadPromise
.then(() => {
clearTimeout(preloadTimeout);
console.log('激励视频广告预加载成功');
resolve(true);
})
.catch((error) => {
clearTimeout(preloadTimeout);
console.error('预加载激励视频广告失败:', error);
resolve(true);
});
console.log('激励视频广告预加载已启动');
} catch (error) {
console.error('预加载激励视频广告失败:', error);
resolve(true);
}
}, 1000); // 延迟1秒预加载确保场景加载完成
});
},
//等待广告预加载完成
waitForAdPreload(): Promise<void> {
console.log("等待广告预加载完成...");
return new Promise((resolve) => {
const waitTimeout = setTimeout(() => {
console.log("等待广告预加载超时,继续执行");
resolve();
}, 5000); // 5秒等待超时
MiniGameSdk.AdvertManager.instance.isPreloadReady()
.then(() => {
clearTimeout(waitTimeout);
console.log("广告预加载已完成");
resolve();
})
.catch(() => {
clearTimeout(waitTimeout);
console.log("广告预加载出错,继续执行");
resolve();
});
});
},
// 适配
adaptation: function () {
// 获取屏幕尺寸
const screenSize = cc.winSize;
const screenWidth = screenSize.width;
const screenHeight = screenSize.height;
// 设计分辨率
const designWidth = 640;
const designHeight = 960;
// 计算屏幕和设计比例
const screenRatio = screenWidth / screenHeight;
const designRatio = designWidth / designHeight;
// console.log("屏幕尺寸:" + screenWidth + "x" + screenHeight + " 比例:" + screenRatio + " 设计比例:" + designRatio);
if (screenRatio > designRatio) {
// 平板设备使用0.7倍缩放
return 0.7;
} else {
// 其他设备使用正常1倍缩放
return 1;
}
},
};