qq小游戏开发
视频演讲稿:
Laya商业教程
LAYA版本2.5,开发语言ts
我们以官方的2d案例为模板,对接QQSDK
QQ平台案例功能点:
banner,激励视频,插屏,游戏盒子,积木广告,分享功能
我们在模板上添加了2个按钮,开始游戏和分数翻倍
并且订阅了点击事件
导入TS类库到scirpt目录
打开banner广告
GameControl.ts
onEnable方法增加以下代码
BannerAndVideo1.OpenBanner(this, null);
真机运行结果
点击更多游戏,显示游戏盒子
GameUI.ts
moregameClcik() {
//qqsdk
BannerAndVideo1.createAppBox();
}
真机运行结果
游戏结束时打开积木盒子和banner
stopGame()
BannerAndVideo1.OpenBanner(this);
BannerAndVideo1.CreateBlockAd();
游戏开始时清除广告组件
startGame()
//qqsdk
BannerAndVideo1.Clear();
BannerAndVideo1.ClearBlockAd();
设置分享页面,预加载激励视频
在游戏的初始化方法里
GameControl.ts
constructor()
//预加载激励视频
BannerAndVideo1.InitVideo();
设置点击右上角三个点出现分享菜单
if (Laya.Browser.onQQMiniGame)
Laya.Browser.window.qq.showShareMenu({
showShareItems: [‘qq’, ‘qzone’, ‘wechatFriends’, ‘wechatMoment’]
})
插屏
激励视频,分数翻倍
gameui.ts
scoreMul2Click()
BannerAndVideo1.ShowVideo(this, this.onvideoEnd)
onvideoEnd(isok) {
console.log(this);
if (isok) {
Platform.ShowToast('奖励X2');
this._score *= 2;
this.scoreLbl.changeText("分数:" + this._score);
}
else
Platform.ShowToast('看完视频才有奖励');
}
插屏广告
进行视频演示最后结果
QQ小游戏开发者文档
https://q.qq.com/wiki/develop/game/API/
现在进行广告组件的讲解,广告组件的全部代码在文章末尾
为了能在真机能成功测试,开发者务必准备好广告ID和APPID
在API调用前都会先做兼容处理,防止空指针异常,比如低版本的QQ是不支持游戏盒子和积木广告的
在打开banner时,因为广告组件异步加载的,用了canshowbanner来约束是否显示
主要是为了避免关闭广告之后还进行显示
插屏广告的调用结果会有调用失败的可能,因为平台底层限制了调用频率且在游戏开始1分钟后才能调用
本期讲解完毕;
课程资料可在进Q群下载
QQ广告类
import { EventMgr } from “…/JFrameWork/EventMgr”;
import { EventType } from “…/JFrameWork/EventType”;
import { Platform } from “./plaftform”;
export default class BannerAndVideo1 {
private static curVideo;
private static curbanner;
private static curBannerId = 0;
private static bannerAdUnitId = ["8f8220b835c41349f98a008150a3da91"];
private static videlAdUnitId = ["d59e4671547cd398036f971156a57458"];
private static InterstitialAdID = 'cab9d10be16322dd3f82c04b5f1aa75d';
private static adboxId = '5ba0a0206e90d902331b8926b5e06e39';
private static BlockAdId = '9b9fc1fb33ad3d3c1ed0063c1adf4e9c';
//banner:8f8220b835c41349f98a008150a3da91
// 视频:d59e4671547cd398036f971156a57458
//插屏:cab9d10be16322dd3f82c04b5f1aa75d
//盒子:5ba0a0206e90d902331b8926b5e06e39
//积木广告:9b9fc1fb33ad3d3c1ed0063c1adf4e9c
//视屏广告是否加载成功
private static videoLoadCom: boolean = false;
private static videoCallback: Function;
private static videoCallder;
//预先加载视屏广告
public static InitVideo() {
if (Laya.Browser.onQQMiniGame != true)
return;
let videoId = BannerAndVideo1.videlAdUnitId[0];
console.log('初始化视频', videoId);
//激励视频广告组件。激励视频广告组件是一个原生组件,并且是一个全局单例
//https://q.qq.com/wiki/develop/game/API/ad/RewardedVideoAd.html#load
if (BannerAndVideo1.curVideo == null) {
BannerAndVideo1.curVideo = Laya.Browser.window.qq.createRewardedVideoAd({ adUnitId: videoId });
BannerAndVideo1.curVideo.onLoad(() => {
console.log('激励视频 广告加载成功');
this.videoLoadCom = true;
});
BannerAndVideo1.curVideo.onError(err => {
console.log("激励视屏加载失败:" + err);
this.videoLoadCom = false;
});
console.log('订阅失败关闭事件');
BannerAndVideo1.curVideo.onClose(res => {
console.log("激励视频关闭:" + res.isEnded);
let isEnd = (res && res.isEnded || res === undefined);
if (isEnd) {
this.videoCallback && this.videoCallback.call(BannerAndVideo1.videoCallder, true)
}
else { this.videoCallback && this.videoCallback.call(BannerAndVideo1.videoCallder, false) }
// this.curVideo.offClose();
// EventMgr.instance.event(EventType.AD_VIDEO_CLOSE_EVENT);
});
}
BannerAndVideo1.curVideo.load();
}
public static ShowVideo(callder, callback: Function) {
//qq
if (Laya.Browser.onQQMiniGame != true) {
callback.call(callder, false);
return;
}
BannerAndVideo1.videoCallder = callder;
if (BannerAndVideo1.videoLoadCom) {
console.log("showVideoAd:" + BannerAndVideo1.videoLoadCom);
BannerAndVideo1.videoCallback = callback;
BannerAndVideo1.curVideo.show().catch(err => {
console.log(err);
Platform.ShowToast('视频拉取失败,请重试');
callback.call(callder, false);
});
}
else {
console.log("没能拉取激励视频");
callback.call(callder, false);
//WXSdk.Game_Share(callback);
}
}
static canshowbanner = true;
static bannerOnLoadCount = 0;
static firstReigstBannerEvent = false;
static banner_errCb;
static banner_onloadCb;
static banner_onResizeCb;
/**打开banner
* https://q.qq.com/wiki/develop/game/API/ad/BannerAd.html
*/
public static OpenBanner(callder, callVack: Function = null, iswait: boolean = false) {
if (Laya.Browser.onQQMiniGame != true) return;
BannerAndVideo1.bannerOnLoadCount = 0;
//估计banner也是全局单例,产生了冗余的回调事件
if (this.curbanner) {
this.curbanner.offResize(BannerAndVideo1.banner_onResizeCb);
this.curbanner.offLoad(BannerAndVideo1.banner_onloadCb);
this.curbanner.offError(BannerAndVideo1.banner_errCb);
this.curbanner.destroy();
}
BannerAndVideo1.canshowbanner = true;
//this.curBannerId++;
// if (this.curBannerId > 1) this.curBannerId = 0;
let idd = BannerAndVideo1.bannerAdUnitId[0];
let info = Laya.Browser.window.qq.getSystemInfoSync();
let topvalue = info.windowHeight;
//let widthvalue = info.windowWidth;
console.log("baner adUnitId:" + idd);
//750x160
let newBanner = Laya.Browser.window.qq.createBannerAd({
adUnitId: '8f8220b835c41349f98a008150a3da91',
style: {
width: 460,
left: 0,
top: 0
}
})
BannerAndVideo1.banner_errCb = (err) => {
console.log('banner err');
console.log(err);
callVack.call(null);
};
newBanner.onError(BannerAndVideo1.banner_errCb);
BannerAndVideo1.banner_onloadCb = () => {
BannerAndVideo1.bannerOnLoadCount += 1;
console.log("新的", BannerAndVideo1.bannerOnLoadCount);
this.curbanner = newBanner;
if (this.canshowbanner && !iswait) {
console.log("banner show");
this.curbanner.show();
}
else {
console.log("banner hide");
this.curbanner.hide();
}
}
newBanner.onLoad(BannerAndVideo1.banner_onloadCb);
BannerAndVideo1.banner_onResizeCb = (size) => {
let info = Laya.Browser.window.qq.getSystemInfoSync();
// console.log(info);
// 底部居中显示
newBanner.style.top = info.windowHeight - size.height;
// newBanner.style.width = info.windowWidth;
// newBanner.style.top = info.windowHeight - this.curbanner.style.realHeight - 5;
// console.log('style.top');
// console.log(newBanner.style.top);
// realHeight
console.log(size);
console.log(newBanner.style);
console.log(Laya.stage.height, info.windowHeight, newBanner.style.realHeight);
//var hight: number = Laya.stage.height / info.windowHeight * newBanner.style.realHeight;
var hight: number = Laya.stage.height / info.windowHeight * size.height;
if (callVack != null) {
callVack.call(callder, hight);
}
}
/**IOS下无法关闭 所以设置在顶端 */
newBanner.onResize(BannerAndVideo1.banner_onResizeCb);
}
static Clear() {
Laya.timer.clearAll(BannerAndVideo1);
Laya.Tween.clearAll(BannerAndVideo1);
BannerAndVideo1.canshowbanner = false;
if (Laya.Browser.onQQMiniGame != true) return;
//创建新的 BannerAd,销毁旧的 BannerAd
//每个 BannerAd 实例在创建后会去拉取一次广告数据并进行渲染,
//在此之后不再更新。如果想要展示其他内容的 BannerAd,
//需要创建新的 BannerAd 并将之前的 BannerAd 进行销毁。
if (BannerAndVideo1.curbanner) {
console.log('banner hide');
//BannerAndVideo1.curbanner.style.top = 3000;
// if (GameSample.commonData.OnIOS) {
// this.ClearOpenBanner_OnIos();
// }
// else
BannerAndVideo1.curbanner.hide();
}
}
public static showbanner() {
console.log('showbanner');
// if (!GameSetting.isWx) return;
if (Laya.Browser.onQQMiniGame != true) return;
BannerAndVideo1.canshowbanner = true;
this.OpenBanner(this, null, false);
// if (BannerAndVideo1.curbanner) BannerAndVideo1.curbanner.show();
}
static CheatBanner(btn: Laya.UIComponent, viewHeight: number, yposAdd: number, complete: Function = null) {
let ischeat = false;
if (ischeat == false) {
console.log("ignorecheat");
BannerAndVideo1.OpenBanner(this, null);
}
else {
btn.bottom = NaN;
btn.y = viewHeight - btn.height - 40;
BannerAndVideo1.OpenBanner(this, (height) => {
if (!height) {
return;
} else {
// btn.y = Laya.stage.height - btn.height - 100;
console.log("cheatstart", "bottom:100");
btn.mouseEnabled = false;
var end = viewHeight - height - btn.height - 20 + yposAdd;
// let end=yposAdd
// console.log("y:" + end);
// console.log(UseModule.CurrentAccount.CurAccountData.cheattime);
Laya.timer.once(1000, this, () => {
btn.mouseEnabled = true;
this.showbanner();
Laya.Tween.to(btn, { y: end }, 500, null, Laya.Handler.create(this, () => {
if (complete != null) {
complete();
}
}))
})
}
}, true);
}
}
// 广告盒子组件。广告盒子组件是一个原生组件,层级比普通组件高。
//广告盒子是一个单例(小游戏端是全局单例,小程序端是页面内单例,在小程序端的单例对象不允许跨页面使用)。
//默认是隐藏的调用 AppBox.load()加载数据,AppBox.show() 将其显示。 AppBox.destroy()销毁实例,销毁后需要重新调用qq.createAppBox()创建实例。
static curVideoadBox;
/**盒子组件 */
public static createAppBox() {
if (Laya.Browser.onQQMiniGame != true) return;
//兼容低版本QQ
if (Laya.Browser.window.qq['createAppBox'] == null) {
console.log('当前版本不支盒子组件');
return;
}
BannerAndVideo1.curVideoadBox = Laya.Browser.window.qq.createAppBox({ adUnitId: BannerAndVideo1.adboxId })
BannerAndVideo1.curVideoadBox.load().then(
(res) => {
console.log('appbox成功') // resolved
BannerAndVideo1.curVideoadBox.show()
}
)
.catch(
(res) => {
console.log('appbox reject') // reject
console.log(res)
}
)
}
private static _InterstitialAdObj;
/**插屏
*
* 插屏广告组件默认是隐藏的,因此可以提前创建,
* 以提前初始化组件。建议在小程序页面的 onReady 事件回调中创建广告实例,并在该页面的生命周期内重复调用该广告实例。
插屏广告组件是自动拉取广告并进行更新的,即在调用qq.createInterstitialAd
之后会立马触发一次load。在组件创建后会拉取一次广告,用户关闭广告后会去拉取下一条广告,即在用户关闭广告之后,会立马触发一次load。
*/
public static CreateInterstitialAd() {
if (Laya.Browser.onQQMiniGame != true) return;
//兼容低版本QQ
if (Laya.Browser.window.qq['createInterstitialAd'] == null) {
console.log('当前QQ版本不支持插屏');
return
}
BannerAndVideo1._InterstitialAdObj = Laya.Browser.window.qq.createInterstitialAd({
adUnitId: 'cab9d10be16322dd3f82c04b5f1aa75d'
});
console.log('插屏创建成功');
BannerAndVideo1._InterstitialAdObj.onLoad((res) => {
console.log('m_InterstitialAd成功') // resolved
BannerAndVideo1._InterstitialAdObj.show()
})
BannerAndVideo1._InterstitialAdObj.onError((res) => {
console.log('m_InterstitialAd erro') // resolved
console.log(res)
})
}
private static _BlockAd;
/**积木盒子 */
public static CreateBlockAd() {
if (Laya.Browser.onQQMiniGame != true) return;
//兼容低版本QQ
if (Laya.Browser.window.qq['createBlockAd'] == null) {
console.log('当前QQ版本不支持积木');
return
}
BannerAndVideo1._BlockAd = Laya.Browser.window.qq.createBlockAd({
adUnitId: this.BlockAdId,
size: 5,
orientation: 'landscape',
style: {
left: 16,
top: 16
}
})
console.log('CreateBlockAd.show');
BannerAndVideo1._BlockAd.show();
BannerAndVideo1._BlockAd.onLoad((res) => {
//console.log('CreateBlockAd onload show');
console.log(res);
BannerAndVideo1._BlockAd.show()
});
BannerAndVideo1._BlockAd.onError((res) => {
console.log('_BlockAd error', res)
console.log(res)
});
BannerAndVideo1._BlockAd.onResize(size => {
console.log('_BlockAd onResize');
console.log(size);
let info = Laya.Browser.window.qq.getSystemInfoSync();
// console.log(info);
// 底部居中显示
// BannerAndVideo1._BlockAd.style.top = info.windowHeight - size.height;
//中间显示
let scale = 0.5;
//top scale 0
//
//bottom 1
// console.log('windowHeight', info.windowHeight);
//相对屏幕中间 上移动200
//width number 积木广告的真实宽度
BannerAndVideo1._BlockAd.style.top = info.windowHeight * scale - 200;
// console.log(BannerAndVideo1._BlockAd.style);
//console.log(BannerAndVideo1._BlockAd);
BannerAndVideo1._BlockAd.style.left = info.windowWidth * 0.5 - size.width * 0.5;
})
// BannerAndVideo1._BlockAd.load();
}
public static ClearBlockAd() {
if (Laya.Browser.onQQMiniGame != true) return;
console.log('ClearBlockAd 积木');
if (BannerAndVideo1._BlockAd != null)
BannerAndVideo1._BlockAd.hide();
}
}