小游戏的文档 简介 · bilibili小游戏bilibili小游戏具有便捷、轻量、免安装的特点。游戏包由云端托管,在哔哩哔哩APP内投放和运行,体验流畅,安全可靠。https://miniapp.bilibili.com/small-game-doc/guide/intro/
没想过接入这个sdk比ios还难,ios不让用插屏广告与原生广告,被打回来了一次,去掉就行,还有截图必须是当前游戏的,不要糊弄。
哔哩哔哩官方目前的api还是有点乱的,官方自己都还在整合中。
必接项目如下:
1.检查并添加游戏启动埋点,否则可能无法通过审核。
上报小游戏启动成功埋点。 需要在游戏首页成功渲染时调用。【不是每个版本都需要调用这个接口】
laya 从 v2.6 - v2.13 版本,可以通过 layaIDE 支持直接导出 bilibili 小游戏,无需其他修改。
其他的引擎不同版本还是根据官方API修改。
2.小游戏配置 game.json 分包也在这里,后面还有那个实名认证。
{"version": "1.0.0","appId": "biligameccxxxxxxxxxxxxxxa4","deviceOrientation": "portrait","networkTimeout": {"request": 5000,"connectSocket": 5000,"uploadFile": 5000,"downloadFile": 5000},"subpackages": [{"name": "Scene","root": "res/Scene/"}]
}
3.音频必须做适配 切换前后台 音频的中断与恢复,被打回过
//背景音乐脚本
export default class GameSoundManager {//播放static playMusic(musicName) {if (window.bl) {if (!GameSoundManager.bgm) { GameSoundManager.bgm = bl.createInnerAudioContext();}// GameSoundManager.bgm.stop();GameSoundManager.bgm.src = "Sound/" + musicName + ".mp3";GameSoundManager.bgm.autoplay = true;GameSoundManager.bgm.loop = true;GameSoundManager.bgm.play();} else { Laya.SoundManager.playMusic("Sound/" + musicName + ".mp3", 0);}}//暂停static pauseMusic() { if (window.bl) {if (!GameSoundManager.bgm) { GameSoundManager.bgm = bl.createInnerAudioContext();}GameSoundManager.bgm.pause();}}
}
音效没必要的,主要针对背景音乐。在合适的地方调用,cocos的话,放在常驻节点上。
if (window.bl) {bl.onShow(res => {GameSoundManager.playMusic("BGM");});bl.onHide(res => {GameSoundManager.pauseMusic();});
}
4.侧边栏 必接
侧边栏礼包必须每天都可领取,同游戏内签到礼包。
先看看官方的API,侧边栏、桌面快捷方式等都会用到场景值。
小游戏开发者可以在 bl.getLaunchOptionsSync 和 bl.onShow 中获取上述场景值
场景值 | 类型 | 含义 |
10001 | string | 我的(首页Tab)-小游戏中心 |
10002 | string | 手机设备桌面快捷入口 |
10003 | string | 各分享渠道 |
021036 | string | 从侧边栏进入小游戏 |
侧边栏的步骤:
步骤 | 解释 |
步骤一: 启动监听,判断是否展示奖励入口 | 1. 游戏启动时通过bl.onShow监听启动信息; 【请确保在游戏启动时机(game.js运行时机)同步监听bl.onShow,若时机太晚收不到回调,会导致用户按操作从侧边栏返回游戏后,无法领取到奖励,造成用户客诉!】 2. 通过bl.checkScene判断当前宿主是否支持跳转侧边栏:
|
步骤二: 奖励展示 | 1. 用户点击奖励入口时,通过获取bl.onShow的最新启动状态,判断当前用户是否从侧边栏启动:
【判断是否从侧边栏启动时,应使用bl.onShow的最新返回值,否则用户从侧边栏热启动小游戏时,会由于返回值未更新而无法领取到奖励,造成用户客诉!】 2. 自动跳转侧边栏:可增加一个跳转按钮,按钮点击回调事件设置为:关闭当前奖励界面并调用bl.navigateToScene(能力已全量开放,无需配置白名单)。用户点击按钮时会自动跳转到侧边栏。 【平台强烈建议接入「自动跳转侧边栏」能力,可大幅度降低用户跳出小游戏后的流失率。】 |
步骤三: 测试,上线 | 开发者需在测试环境下完整跑通从侧边栏启动后领取奖励的链路,测试通过确认无误后发布上线。 |
第一步:监听是否可以显示桌面侧边栏按钮,这个与抖音api差不多
bl.onShow(res => {//兼容 与基础版本做对比 CompareVersion()这个方法就不写了,以前文章应该有的if (SdkUtil.CompareVersion(bl.getSystemInfoSync().SDKVersion, '3.99.5') >= 0) {console.log("检测版本号");bl.checkScene({scene: "sidebar",success: (res) => {if (res.isExist) {//显示入口有奖按钮this.goldButton.visible = true;} else {//隐藏入口有奖按钮this.goldButton.visible = false;}},fail: (res) => {//隐藏入口有奖按钮this.goldButton.visible = false;}});} else {//隐藏入口有奖按钮this.goldButton.visible = false;}
});
第二步:监听场景值是否从侧边栏进入。getUserData这个是我的读取本地存储的方法。
bl.onShow(res => {const scene = res.scene;if (scene == '021036' || bl.getLaunchOptionsSync().scene === "021036") {// 记住,合适的地方移除这个本地存储.// Laya.LocalStorage.removeItem("sidebar");// 从侧边栏进入,显示侧边栏奖励界面的领奖按钮Laya.LocalStorage.setItem("sidebar", "sidebar");if (this.enterPanel.visible) {//侧边栏奖励领取时间,在这里初始化一下,方便在其他地方调用到this.offlineSliderTime = PlayerData.getUserData("rewardSliderDate");this.offlineSliderTime = Date.now() - this.offlineSliderTime;this.offlineSliderTime = this.offlineSliderTime / 1000;const sidebar = Laya.LocalStorage.getItem("sidebar");if (sidebar) {this.getBtn.visible = true;//领奖按钮this.enterBtn.visible = false;//侧边栏跳转按钮} else {this.getBtn.visible = false;//领奖按钮this.enterBtn.visible = true;//侧边栏跳转按钮}}}
});
//当打开侧边栏界面的时候,打开侧边栏按钮事件。
openSiderBarPanel(){this.enterPanel.visible = true;//侧边栏奖励领取时间,在这里初始化一下,方便在其他地方调用到this.offlineSliderTime = PlayerData.getUserData("rewardSliderDate");this.offlineSliderTime = Date.now() - this.offlineSliderTime;this.offlineSliderTime = this.offlineSliderTime / 1000;const sidebar = Laya.LocalStorage.getItem("sidebar");if (sidebar) {this.getBtn.visible = true;//领奖按钮this.enterBtn.visible = false;//侧边栏跳转按钮} else {this.getBtn.visible = false;//领奖按钮this.enterBtn.visible = true;//侧边栏跳转按钮}
}
第二步:跳转侧边栏,按钮事件
navigateToScene() {if (window.bl) {bl.navigateToScene({scene: "sidebar",success: (res) => { },fail: (res) => { },});}
}
第三步:领取奖励,按钮事件
getReward(){if (this.offlineSliderTime < 60 * 60 * 24) {SdkUtil.ShowToast("今日奖励已经领取");return;}//保存领取奖励时间var offlineSliderTime = this.getDayZeroTime();PlayerData.setUserData("rewardSliderDate", offlineSliderTime);//保存用户领取的奖励PlayerData.setUserData("gold", PlayerData.getUserData("gold") + 2000);PlayerData.saveData();//弹窗提示SdkUtil.ShowToast("获取金币 +200");this.enterPanel.visible = false;//刷新你的奖励this.refreshXXX();//刷新界面
}
//13位时间戳,用于对比领奖时间
getDayZeroTime() {var nowDay = new Date();nowDay.setHours(0);nowDay.setMinutes(0);nowDay.setSeconds(0);nowDay.setMilliseconds(0);var nowDayTime = nowDay.getTime();return nowDayTime;
}
至于实名认证与桌面快捷方式的每日领奖,可以按着上面来写。
5.分包 哔哩哔哩工具上传的是zip的压缩包
整个小游戏所有分包大小不超过 20M
单个分包/主包大小不能超过 4M
也就是不压缩的实际包体吗,一般情况下,不用考虑远程问题。
6.实名认证 必接 只支持安卓
根据规定,所有游戏用户必须完成实名认证才能继续访问和参与游戏。
属性 | 类型 | 默认值 | 必填 | 说明 |
title | string | 是 | 提示的标题 | |
content | string | 是 | 提示的内容 | |
giftImgUrl | string | 否 | 提示的礼包图片(支持gif) | |
cancelText | string | '取消' | 否 | 取消按钮的文字,最多 5 个字符 |
confirmText | string | '确定' | 否 | 确认按钮的文字,最多 5 个字符 |
giftImgUrl我使用的站内图片地址,后台会配置好的,官方也给了远程的API,本地的不知道能用不,没尝试。
7.激励视频埋点上报,官方没说是否必须,放置万一吧。
// 用户点击观看视频广告时上报
bl.reportScene({sceneId:1007});
rewardedVideoAd.load().then(() => {
return rewardedVideoAd.show();
});
8.添加到桌面礼包「必接」。 侧边栏打开礼包「必接」上方写过了
按钮事件调用,主要是针对ios的,被打回过。
if (window.bl) {if (SdkUtil.CompareVersion(bl.getSystemInfoSync().SDKVersion, '3.99.4') >= 0) {//bl.checkShortcut接口只支持android平台if (bl.getSystemInfoSync().platform.toLowerCase().indexOf("android") != -1) {//检测桌面快捷方式是否存在bl.checkShortcut({success(res) {console.log("检查快捷方式"), console.log(res.status);if (res.status.exist) {//弹窗桌面礼包奖励界面UIManager.ShowUIPanel("Desk", false);} else {bl.addShortcut({success() {console.log("添加桌面成功");}, fail(err) {SdkUtil.ShowToast("从桌面ICON进入领取每日奖励");console.log("添加桌面失败", err.errMsg);},});}},fail(res) {SdkUtil.ShowToast("从桌面ICON进入领取每日奖励");console.log("检查快捷方式失败", res.errMsg);},});} else {//从手机设备桌面快捷入口启动的场景值if (bl.getLaunchOptionsSync().scene === "10002" || this.open_desk === true) {//弹出桌面礼包奖励页面UIManager.ShowUIPanel("Desk", false);} else {bl.addShortcut({success() {SdkUtil.ShowToast("从桌面ICON进入领取每日奖励");console.log("添加桌面成功");}, fail(err) {SdkUtil.ShowToast("从桌面ICON进入领取每日奖励");console.log("添加桌面失败", err.errMsg);},});}}} else {SdkUtil.ShowToast("请升级最新版本");}
}
//场景值吗,在两个地方可以拿到,最好还是判断一下
bl.onShow(res => {if (scene == '10002') {this.open_desk = true;}
});
9.埋点上报【主要防止万一】
bl.reportScene({});
sceneId | 说明 |
7 | 游戏可玩,比如进入游戏大厅 |
10 | 游戏新手教程完成 |
1007 | 激励视频广告,用户点击看广告 |
10.首屏渲染 index.js中,这个只正对哔哩哔哩小游戏,其它小游戏不要用【API中看到的】
var testRender = function () {var GameConfig = {};GameConfig.width = 640;GameConfig.height = 1136;GameConfig.scaleMode = "fixedwidth";GameConfig.screenMode = "none";GameConfig.alignV = "top";GameConfig.alignH = "left";Laya3D.init(GameConfig.width, GameConfig.height);Laya["Physics"] && Laya["Physics"].enable();Laya["DebugPanel"] && Laya["DebugPanel"].enable();Laya.stage.scaleMode = GameConfig.scaleMode;Laya.stage.screenMode = GameConfig.screenMode;Laya.stage.alignV = GameConfig.alignV;Laya.stage.alignH = GameConfig.alignH;var logoSprite = new Laya.Sprite();Laya.stage.addChild(logoSprite);logoSprite.y = 300;var handler = Laya.Handler.create(null, function () {logoSprite.removeSelf();});logoSprite.loadImage("First/logo.png", handler);var tTestText = new Laya.Text();tTestText.autoSize = true;tTestText.text = "正在努力加载中 ...";tTestText.bold = true;tTestText.font = "Microsoft YaHei";tTestText.color = "#FFFFFF";tTestText.fontSize = 20;tTestText.x = 300;tTestText.y = 700;Laya.stage.addChild(tTestText);//合理时间移除setTimeout(() => {tTestText.removeSelf();}, 2000);
};testRender();
11.分享功能
自定义图片路径,支持 PNG 及 JPG。建议图片分辨率 750*750
1、小游戏包内相对路径
2、blfile:// 协议路径
3、https:// 网络图片路径(暂不支持非 bilibili 图片服务器资源地址)
//SDK初始化时候调用
bundleShareActive() {if (window.bl) {bl.onShareAppMessage(() => {return {title: '啊啊啊啊',subTitle: '啊啊啊啊啊',imageUrl: 'XXXX'};});}
}
//分享按钮点击时候调用
bl.shareAppMessage({title: '啊啊啊啊',subTitle: '啊啊啊啊啊',imageUrl: 'xxxxxxxxxxxxx',biliContent: '一款超好玩得小游戏,快来和我一起玩吧!',success() {console.log('分享视频成功');if (callback != null) {callback(1);callback = null;}},fail(e) {console.log('分享视频失败' + JSON.stringify(e));if (callback != null) {callback(0);callback = null;}}
}
12.录制视频,暂时不需要接入,存在问题,也非必须。被打回过。
不用接入,视频分享存在问题,以后可能会必须接入,像抖音一样。
13.如果存在输入 需要敏感词检测
bl.sensitiveWordCheck(Object object)
14.震动
bl.vibrateShort({})
15.版权是必要的
16.隐私协议等,非必须。
其他一些api
bl.showLoading({title: '加载中',
})
setTimeout(function () {bl.hideLoading()
}, 2000)bl.showModal({title: '提示',content: '这是一个模态弹窗',success(res) {if (res.confirm) {console.log('用户点击确定')} else if (res.cancel) {console.log('用户点击取消')}}
})bl.exitMiniProgram({})
bl.getSystemInfoSync() 异步bl.getAppBaseInfo
0 哔哩哔哩
1 高能通
2 哔哩哔哩漫画