Asroads'Blog 君子不器
头条小游戏录屏功能实现
发布于: 2019-05-18 更新于: 2024-03-02 分类于: game 阅读次数: 

小游戏平台开放越来越多,字节跳动因为有着今日头条和抖音两大软件,众多用户的体量,成为了小游戏开发者的一个青睐的平台,我们有几款小游戏成功移植到了字节跳动平台,这个平台很多语法和API 都很相似,但是在细微之处还是有很多差别的,比如对待分享这件事,对待录屏功能这个事情,目前游戏内必须实现录屏功能才能上线。

前期准备

  • 字节跳动录屏API
  • 小游戏页面操作实现逻辑
  • 美术素材按钮四个(录屏,暂停,分享,重录)

查看头条API

首先我们需要自己理解头条API 关于录屏的内容 大概是下面这几个接口 查看地址

游戏内逻辑实现

  1. 根据上面的需求我们知道,需要美术提供一份美术素材,程序这边需要根据需求实现交互逻辑

  2. 我们理解了API之后,我们要实现的内容大概是,一开始要展示录制按钮,然后用户可以点击或者触摸操作录屏,录制结束后,两种操作

    • 结束录屏,然后编辑分享出去
    • 结束录屏,不满意重新录制
  3. 分享后两种结果,成功或者失败,重新录制继续回到上面的步骤2

  4. 根据需求,我们知道我们需新建一个全局的 录制对象,然后根据用户操作,调用API即可

编码如下:TTMusicManager.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
module smile361 {

import Browser = Laya.Browser;

export class TTMusicManager {
static get Ins(): sm.TTMusicManager {
if (!this._Ins) {
this._Ins = new TTMusicManager();
this._Ins.tt = window.platform.Instance;
}
return this._Ins;
}

private static _Ins: TTMusicManager;
private tt: any;
private music: any;
private soundList:Array<any>=[];

// private sound: any;

public playMusic(res: string = SoundURL.BG_MUSIC) {
if (!Browser.onWeiXin) {
return;
}
if (this.music) {
this.stopMusic();
} else {
this.music = this.tt.createInnerAudioContext();
}
this.music.src = res;
this.music.loop = true;
this.music.obeyMuteSwitch = true;
this.music.volume = 0.5;
this.music.play();
this.music.onCanplay(()=>{
console.log("jsroads------:" + JSON.stringify("onCanplay"));
this.music.play();
});

}

public stopMusic() {
if (!Browser.onWeiXin) {
return;
}
if (this.music) {
this.music.volume = 0;
this.music.offCanplay(()=>{
});
this.music.stop();
this.music.destroy();
this.music = null;
}

}

public playSound(res: string = SoundURL.CLICK_SOUND) {
if (!Browser.onWeiXin) {
return;
}
let sound;
sound = this.tt.createInnerAudioContext();
sound.src = res;
sound.loop = false;
sound.obeyMuteSwitch = true;
sound.volume = 0.5;
sound.onCanplay(()=>{
sound.play();
});
sound.onStop(()=>{
this.search(sound);
sound.destroy();
});
sound.onEnded(()=>{
this.search(sound);
sound.destroy();
});
this.soundList.push(sound);
}

private search(sound){
let index = this.soundList.indexOf(sound);
if(index!=-1){
this.soundList.splice(index,1);
}
}

public stopSound() {
if (!Browser.onWeiXin) {
return;
}
if (this.soundList.length) {
this.soundList.forEach((value, index: number, array)=>{
value.destroy();
})
// this.sound.destroy();
// this.sound = null;
}

}
}
}

TTRecordView.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
module smile361 {
import RecordViewUI = ui.smui.RecordViewUI;
import Event = Laya.Event;
import Handler = Laya.Handler;
export class TTRecordView extends RecordViewUI {
public static get Ins(): TTRecordView {
if (!this._Ins) this._Ins = new TTRecordView();
return this._Ins;
}

private static _Ins: TTRecordView;
private count: number = 0;

constructor() {
super();
this.onAwake();
}

show(): void {
this.pos(0,GameConfig.height-120);
AppLayerManager.Ins.addToShowLayer(this);
}

public onAwake() {
this.on(Event.MOUSE_DOWN, this, this.downHandler);
this.on(Event.MOUSE_UP, this, this.upHandler);
this.on(Event.MOUSE_OUT, this, this.outHandler);
this.on(Event.MOUSE_OVER, this, this.overHandler);
this.on(Event.MOUSE_MOVE, this, this.moveHandler);
this.on(Event.DRAG_START, this, this.startHandler);
this.on(Event.DRAG_END, this, this.endHandler);
this.on(Event.DRAG_MOVE, this, this.dragHandler);
this.recordBtn.on(Event.CLICK, this, () => {
console.log("smile------recordBtn:" + JSON.stringify("click"));
this.record();
});
this.stopBtn.on(Event.CLICK, this, () => {
console.log("smile------stopBtn:" + JSON.stringify("stop"));
if (this.count < 4) {
GameManager.Ins.showWarnTips("录制视频必须大于3秒");
return;
}
Laya.timer.clear(this, this.showRecord);
TTGameRecorderManager.Ins.stop();
this.setBtnVisible(false, true, true, false);
});
this.reRecordBtn.on(Event.CLICK, this, () => {
console.log("smile------reRecordBtn:" + JSON.stringify("click"));
this.record();
});
this.shareBtn.on(Event.CLICK, this, () => {
console.log("smile------shareBtn:" + JSON.stringify("shareRecordVideo"));
ShareMessage.shareRecordVideo(TTGameRecorderManager.Ins.videoPath, Handler.create(this, (bool) => {
console.log("smile------:" + JSON.stringify("share success"));
this.setBtnVisible(true, false, false, false);
}));
});
this.setBtnVisible(true, false, false, false);
}

record() {
if (!TTGameRecorderManager.Ins.isRecord) {
this.count = 0;
this.timeText.text = GameTimeTrans.getRemainTimeBySecond(0);
TTGameRecorderManager.Ins.start();
Laya.timer.loop(1000, this, this.showRecord);
this.setBtnVisible(false, false, false, true);
} else {
Laya.timer.clear(this, this.showRecord);
console.log("smile------:" + JSON.stringify("OK"));
}
}

setBtnVisible(record: boolean, reRecord: boolean, share: boolean, stop: boolean) {
this.recordBtn.visible = record;
this.reRecordBtn.visible = reRecord;
this.shareBtn.visible = share;
this.stopBtn.visible = stop;
}

private downHandler() {
this.alpha = 1.0;
Laya.Tween.clearAll(this);
this.startDrag(null, false, 50, 50, null, true, 1);
}

private upHandler() {

this.stopDrag();

}

private moveHandler() {
// this.startDrag(null, false, 10, 50, null, true, 1);
if (this.x < 0) {
this.x = 0;
}
if (this.x > (GameConfig.width - 100)) {
this.x = GameConfig.width - 100;
}
if (this.y < 0) {
this.y = 0;
}
if (this.y > (GameConfig.height - 100)) {
this.y = GameConfig.height - 100;
}
}

private startHandler() {

}

private endHandler() {
this.tweenToTrans();
}

private dragHandler() {
}

private outHandler() {

}

private overHandler() {

}

public onEnable() {

}

private tweenToTrans() {
let x = GameConfig.width - 200;
if (this.x <= (GameConfig.width - this.width) / 2) {
x = 0;
}
Laya.Tween.to(this, {x: x}, 300);
}

private showRecord() {
this.count++;
let str = GameTimeTrans.getRemainTimeBySecond(this.count);
this.timeText.text = str;
if (this.count >= TTGameRecorderManager.RECORD_TIME) {
this.setBtnVisible(false, true, true, false);
Laya.timer.clear(this, this.showRecord);
TTGameRecorderManager.Ins.stop();
}
}
}
}
  1. 以上代码写好后,我们需要编辑我们的素材,上面的 TTRecordView 是继承自 我们的UI素材 TTRecordView的,大家根据里面的变量,使用美术素材按钮,取好名字即可。
  2. 需要注意的有以下几点,第一录屏功能目前截止笔者编写文章的时候,依旧不能支持开发者工具,需要在真机环境下调试,第二个是 录屏功能的时间录制不能低于3秒,需要给出提示,否则平台不给过审。
  3. 关于平台的文件,目前为了多个平台运行,我们可以写一个单独的文件
1
2
3
4
class TTPlatform {
Instance = tt;
}
window.platform = new TTPlatform();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
declare interface Platform {
Instance;
}

class DebugPlatform implements Platform {
Instance = {};
}

if (!window.platform) {
window.platform = new DebugPlatform();
}
declare let platform: Platform;
declare interface Window {
platform: Platform;
}
  1. 这个我们做平台移植的时候,就不需要再项目内各个地方都要修改一次。

以上就是关于微头条小游戏在头条平台的录屏功能的代码实现。

--- 本文结束 The End ---