代码包总大小不能超过 30M,单个分包不限制大小,主包不超过 6M。
laya、cocos creator等游戏开发工具,并没有为快手小游戏做单独的处理,所以出包快手小游戏,需要先出包微信小游戏,当然sdk用的是快手的。
只是出包出的是微信的,然后用快手小游戏开发者工具上传开发者后台。
appId: "ks69608xxxxxxxxxxxxx",
rewardedVideoId: "23xxxxxxxx_01",
interstitialId: "23xxxxxxxx_02",
bannerId: "23xxxxxxxx_03",
bannerAd: null,
recorder: null, //游戏录制对象
videoPath: 0, //游戏录制ID
//初始化快手SDK
initSDK(){
SdkUtil.recorderInit();
},
// 对比版本号
compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i]);
const num2 = parseInt(v2[i]);
if (num1 > num2) {
return 1;
} else if (num1 < num2) {
return -1;
}
}
return 0;
},
//加载子包
loadSubpackage(callback) {
if (window.ks) {
let loadSubpackage = (name, callback) => {
let loadTask = ks.loadSubpackage({
name: name,
success: (res) => {
callback();
},
fail: (res) => {
SdkUtil.ShowToast('当前加载分包包失败: ' + name);
console.log('当前加载分包包失败:',JSON.stringify(res));
},
complete: () => { }
});
loadTask.onProgressUpdate(res => {
console.log('下载进度', res.progress);
console.log('已经下载的数据长度', res.totalBytesWritten);
console.log('预期需要下载的数据总长度', res.totalBytesExpectedToWrite);
})
};
let loadArrayBao = (baoarray, callback) => {
let index = 0;
let endCallBack = function () {
index++;
if (index >= baoarray.length) {
//全部分包资源加载完毕;
callback();
} else {
loadSubpackage(baoarray[index], endCallBack);
}
};
loadSubpackage(baoarray[index], endCallBack);
};
loadArrayBao(["resources"], () => {
if (callback != null) {
callback();
callback = null;
}
});
} else {
if (callback != null) {
callback();
callback = null;
}
}
},
//获取全局唯一的游戏画面录制对象
recorderInit() {
if (window.ks) {
SdkUtil.recorder = window.ks.getGameRecorder();
// 设置录屏相关监听
SdkUtil.recorder.on('start', () => {
// start 事件的回调函数的执行表示录制的真正开始
console.log('录屏开始');
})
// 监听录屏过程中的错误,需根据错误码处理对应逻辑
SdkUtil.recorder.on('error', (err) => {
// 录屏过程中,当收到onError的回调时,表明录制过程中存在异常,调试时可以根据err.code定位异常的原因
// 相关errorCode含义见录屏相关错误码定义
})
// stop 事件的回调函数
SdkUtil.recorder.on('stop', res => {
if (res && res.videoID) {
// 当录制成功时,会产生一个videoID,用于发布录屏(recorder.publishVideo)接口使用
console.log(`videoID is ${res.videoID}`)
console.log(`录屏停止,录制成功`)
SdkUtil.videoPath = res.videoID;
} else {
/****注意:没有videoID时不可展示分享录屏按钮,审核会过此case****/
/****测试方法:点击右上角"..."按钮打开设置页面,关闭录屏开关,录屏不会产生videoID****/
// 没有videoID时,可以通过onError回调获取录制失败的原因
console.log(`录屏停止,录制失败`)
}
})
// pause 事件的回调函数
SdkUtil.recorder.on('pause', () => {
console.log('暂停录制')
})
// resume 事件的回调函数
SdkUtil.recorder.on('resume', () => {
console.log('继续录制')
})
// abort 事件的回调函数,表示录制中的游戏画面已经被舍弃
SdkUtil.recorder.on('abort', () => {
console.log('废弃已录制视频')
SdkUtil.videoPath = 0;
})
}
},
recorderStart() {
if (window.ks) {
if (!SdkUtil.recorder)
SdkUtil.recorder = window.ks.getGameRecorder();
SdkUtil.recorder.stop();
SdkUtil.recorder.start();
}
},
//结束录制游戏画面。结束录制后可以发起分享。
recorderOver() {
if (window.ks) {
// 在合适的时机,可以调用recorder.stop()来停止录制
if (!SdkUtil.recorder)
SdkUtil.recorder = window["ks"].getGameRecorder();
SdkUtil.recorder.stop()
}
},
//放弃录制游戏画面。此时已经录制的内容会被丢弃。
recorderAbort() {
if (window.ks) {
// 在合适的时机,可以调用recorder.abort()来舍弃已经在录制的视频
if (!SdkUtil.recorder)
SdkUtil.recorder = window["ks"].getGameRecorder();
SdkUtil.recorder.abort()
SdkUtil.videoPath = 0;
}
},
shareGame(callback) {
console.log("*************调用分享游戏视频*************");
if (window["ks"]) {
if (SdkUtil.videoPath != 0) {
SdkUtil.recorder.publishVideo({
video: SdkUtil.videoPath,
callback: (error) => {
if (error != null && error != undefined) {
console.log("分享录屏失败: " + JSON.stringify(error));
if (callback != null) {
callback(0);
callback = null;
}
return;
}
console.log("分享录屏成功");
if (callback != null) {
callback(1);
callback = null;
}
}
});
} else {
window["ks"].shareAppMessage({
success() {
if (callback != null) {
callback(1);
callback = null;
}
console.log(`分享成功`);
},
fail(e) {
console.log(`分享失败 ` + JSON.stringify(e));
if (callback != null) {
callback(0);
callback = null;
}
},
complete() { }
});
}
} else {
if (callback != null) {
callback(1);
callback = null;
}
}
},
showBannerAd() {
//快手安卓版本>=12.10.30,iOS版本>=12.10.40 platform version
//每次调用该方法创建 banner 广告都会返回一个全新的实例,全局只会存在一个Banner广告实例。
if (window.ks) {
if ((SdkUtil.compareVersion(ks.getSystemInfoSync().version, '12.10.30') >= 0 && (ks.getSystemInfoSync().platform.indexOf("android") != -1)) ||
SdkUtil.compareVersion(ks.getSystemInfoSync().version, '12.10.40') >= 0 && (ks.getSystemInfoSync().platform.indexOf("ios") != -1)) {
const { windowWidth, windowHeight } = ks.getSystemInfoSync();
const targetBannerAdWidth = 350;
SdkUtil.bannerAd = ks.createBannerAd({
adUnitId: SdkUtil.bannerId,
adIntervals: 30,
style: {
left: (windowWidth - targetBannerAdWidth) / 4,
with: targetBannerAdWidth,
top: windowHeight - 120,
height: 120
}
});
SdkUtil.bannerAd.onError((err) => {
console.log("banner广告加载失败" + JSON.stringify(err));
});
SdkUtil.bannerAd.onLoad(() => {
console.log('banner广告加载成功,调用播放');
});
SdkUtil.bannerAd.show().then(() => {
console.log('banner广告展示成功');
});
SdkUtil.bannerAd.onResize((size) => {
console.log("现在的尺寸 " + size.width + ":" + size.height);
SdkUtil.bannerAd.style.left = (windowWidth - size.width) / 2;
SdkUtil.bannerAd.style.top = windowHeight - size.height;
SdkUtil.bannerAd.style.width = size.width;
SdkUtil.bannerAd.style.height = size.height;
});
}
}
},
closeBannerAd() {
console.log("*************隐藏banner广告*************");
if (window["ks"]){
if ((SdkUtil.compareVersion(ks.getSystemInfoSync().version, '12.10.30') >= 0 && (ks.getSystemInfoSync().platform.indexOf("android") != -1)) ||
SdkUtil.compareVersion(ks.getSystemInfoSync().version, '12.10.40') >= 0 && (ks.getSystemInfoSync().platform.indexOf("ios") != -1)) {
if (SdkUtil.bannerAd) {
SdkUtil.bannerAd.hide();
//会报错 SdkUtil.bannerAd.destory() is not a function
// if (SdkUtil.bannerAd != null) {
// SdkUtil.bannerAd.destory();
// SdkUtil.bannerAd = null;
// }
}
}
}
},
showInterstitialAd() {
console.log("*************显示插屏广告*************");
if (window.ks) {
let interstitialAd = window.ks.createInterstitialAd({
adUnitId: SdkUtil.interstitialId
});
if (interstitialAd) {
interstitialAd.onClose((res) => {
// 插屏广告关闭事件
console.log(`插屏广告关闭事件, 结果 ` + JSON.stringify(res));
})
interstitialAd.onError((res) => {
// 插屏广告Error事件
console.log(`插屏广告错误事件, 结果 ` + JSON.stringify(res));
})
//-20037 插屏播放失败
interstitialAd.show().then(() => {
// 插屏广告展示成功
console.log(`插屏广告展示成功`);
}).catch((error) => {
// 插屏广告展示失败
console.log(`插屏广告展示失败, 结果 ` + JSON.stringify(error));
})
} else {
console.log("创建插屏广告组件失败");
}
}
},
showRewardedVideoAd(callback) {
console.log("*************显示激励视频广告*************");
if (window["ks"]) {
let rewardedVideoAd = window.ks.createRewardedVideoAd({
adUnitId: SdkUtil.rewardedVideoId
});
if (rewardedVideoAd) {
rewardedVideoAd.onClose(res => {
// 用户点击了【关闭广告】按钮
if (res && res.isEnded) {
// 正常播放结束,可以下发游戏奖励
window["SdkUtil"].ShowToast("奖励已经发放!");
if (callback != null) {
callback(1);
callback = null;
}
} else {
window["SdkUtil"].ShowToast("观看视频失败!");
// 播放中途退出,不下发游戏奖励
if (callback != null) {
callback(0);
callback = null;
}
}
})
rewardedVideoAd.onError(res => {
window["SdkUtil"].ShowToast("创建激励视频组件失败!");
console.log(`激励视频错误事件, 结果 ` + JSON.stringify(res));
// 激励视频广告Error事件
if (callback != null) {
callback(0);
callback = null;
}
})
rewardedVideoAd.show().then(() => {
// 激励视频展示成功
console.log(`激励视频播放成功`);
}).catch((error) => {
// 激励视频展示失败
console.log(`激励视频播放失败, 结果 ` + JSON.stringify(error));
});
} else {
console.log("创建激励视频组件失败");
window["SdkUtil"].ShowToast("创建激励视频组件失败!");
if (callback != null) {
callback(0);
callback = null;
}
}
} else {
window["SdkUtil"].ShowToast("奖励已经发放!");
if (callback != null) {
callback(1);
callback = null;
}
}
},
以上是常用的api,至于震动、陀螺仪、支付等,自己可以去官网开放平台查看。
注意一点
/
//文件 landscape //横屏 portrait 竖屏
//但正真起作用的是 在游戏渠道审批时基本信息填写的 横竖屏设置 哪一项
//subpackages这一项必须小写 Laya出包必须修改这一项
game.json
{
"deviceOrientation": "portrait",
"showStatusBar": false,
"networkTimeout": {
"request": 10000,
"connectSocket": 10000,
"uploadFile": 10000,
"downloadFile": 10000
},
"subpackages": [
{
"name": "resources",
"root": "subpackages/resources"
}
]
}