[adapters] 增加小游戏适配部分源码

This commit is contained in:
SmallMain
2024-10-16 17:12:08 +08:00
parent 887d4a96c9
commit 07bf3b7a96
345 changed files with 38447 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
const screencanvas = $global.screencanvas;
const parser = cc.assetManager.parser;
const downloader = cc.assetManager.downloader;
function parseParameters (options, onProgress, onComplete) {
if (onComplete === undefined) {
var isCallback = typeof options === 'function';
if (onProgress) {
onComplete = onProgress;
if (!isCallback) {
onProgress = null;
}
}
else if (onProgress === undefined && isCallback) {
onComplete = options;
options = null;
onProgress = null;
}
if (onProgress !== undefined && isCallback) {
onProgress = options;
options = null;
}
}
options = options || Object.create(null);
return { options, onProgress, onComplete };
}
function doNothing (url, options, onComplete) {
onComplete(null, url);
}
downloader.downloadDomAudio = doNothing;
function downloadImage (url, options, onComplete) {
const parameters = parseParameters(options, undefined, onComplete);
options = parameters.options;
onComplete = parameters.onComplete;
const img = screencanvas.createImage();
const timer = setTimeout(() => {
clearEvent();
onComplete && onComplete(new Error(cc.debug.getError(4930, url)));
}, 8000);
function clearEvent () {
img.onload = null;
// img.onerror = null;
}
function loadCallback () {
clearEvent();
clearTimeout(timer);
onComplete && onComplete(null, img);
}
function errorCallback () {
clearEvent();
clearTimeout(timer);
onComplete && onComplete(new Error(cc.debug.getError(4930, url)));
}
img.onload = loadCallback;
// NOTE: crash when registering error callback
// img.onerror = errorCallback;
img.src = url;
return img;
}
downloader.downloadDomImage = downloadImage;
downloader.register({
// Audio
'.mp3' : doNothing,
'.ogg' : doNothing,
'.wav' : doNothing,
'.m4a' : doNothing,
// Image
'.png' : doNothing,
'.jpg' : doNothing,
'.bmp' : doNothing,
'.jpeg' : doNothing,
'.gif' : doNothing,
'.ico' : doNothing,
'.tiff' : doNothing,
'.image' : doNothing,
'.webp' : doNothing,
'.pvr': doNothing,
'.pkm': doNothing,
'.astc': doNothing,
});
parser.register({
// Audio
'.mp3' : doNothing,
'.ogg' : doNothing,
'.wav' : doNothing,
'.m4a' : doNothing,
// Image
'.png' : downloadImage,
'.jpg' : downloadImage,
'.bmp' : downloadImage,
'.jpeg' : downloadImage,
'.gif' : downloadImage,
'.ico' : downloadImage,
'.tiff' : downloadImage,
'.image' : downloadImage,
'.webp' : downloadImage,
});

View File

@@ -0,0 +1,171 @@
const game = cc.game;
const EventTarget = cc.EventTarget;
const State = {
ERROR: -1,
INITIALZING: 0,
PLAYING: 1,
PAUSED: 2,
STOPPED: 3,
}
function Audio (url, serializedDuration) {
this._nativeAudio = my.createInnerAudioContext();
this._et = new EventTarget();
this.reset();
this._setSrc(url);
const nativeAudio = this._nativeAudio;
this._serializedDuration = serializedDuration;
this._ensureLoaded(() => {
this._duration = nativeAudio.duration;
});
this._duration = 1;
this._onShow = () => {
if (this._blocked) {
this._nativeAudio.play();
}
this._blocked = false;
};
this._onHide = () => {
if (this.getState() === State.PLAYING) {
this._nativeAudio.pause();
this._blocked = true;
}
};
nativeAudio.onCanplay(() => { this._et.emit('load'); });
nativeAudio.onError((err) => { this._et.emit('error', err); });
nativeAudio.onEnded(() => {
this.finishCB && this.finishCB();
this._state = State.INITIALZING;
this._et.emit('ended');
});
nativeAudio.onStop(() => { this._et.emit('stop'); });
nativeAudio.onTimeUpdate(() => { this._currentTime = nativeAudio.currentTime; });
game.on(game.EVENT_SHOW, this._onShow);
game.on(game.EVENT_HIDE, this._onHide);
this.onError((err) => { cc.error(err); });
}
Audio.State = State;
Object.assign(Audio.prototype, {
reset () {
this.id = -1;
this.finishCB = null; // For audioEngine custom ended callback.
this._state = State.INITIALZING;
this._loop = false;
this._currentTime = 0;
this._volume = 1;
this._blocked = false;
this._loaded = false;
this.offLoad();
this.offError();
this.offEnded();
this.offStop();
},
destroy () {
this.reset();
game.off(game.EVENT_SHOW, this._onShow);
game.off(game.EVENT_HIDE, this._onHide);
// offCanplay offOnError offStop offEnded is not supported for now.
this._nativeAudio.destroy();
this._nativeAudio = null;
},
getSrc () { return this._src; },
// NOTE: don't set src twice, which is not supported on TAOBAO
_setSrc (path) {
if (this._src === path) {
return;
}
const nativeAudio = this._nativeAudio;
this._loaded = false;
nativeAudio.src = path;
this._src = path;
},
getState () { return this._state; },
getDuration () { return this._serializedDuration ? this._serializedDuration : this._duration; },
getCurrentTime () { return this._currentTime; },
seek (val) {
if (this._currentTime === val) {
return;
}
this._ensureLoaded(() => {
this._nativeAudio.seek(val);
this._currentTime = val;
});
},
getLoop () { return this._loop; },
setLoop (val) {
if (this._loop === val) {
return;
}
this._ensureLoaded(() => {
this._nativeAudio.loop = val;
this._loop = val;
});
},
getVolume () { return this._volume; },
setVolume (val) {
if (this._volume === val) {
return;
}
this._ensureLoaded(() => {
this._nativeAudio.volume = val;
this._volume = val;
});
},
play () {
if (this.getState() !== State.PLAYING) {
this._nativeAudio.play();
this._state = State.PLAYING;
}
},
resume () {
if (this.getState() === State.PAUSED) {
this._nativeAudio.play();
this._state = State.PLAYING;
}
},
pause () {
if (this.getState() === State.PLAYING) {
this._nativeAudio.pause();
this._state = State.PAUSED;
}
},
stop () {
// NOTE: On taobao, it is designed that audio is useless after stopping.
// this._nativeAudio.stop();
this._nativeAudio.pause();
this._nativeAudio.seek(0);
this._state = State.STOPPED;
},
onceLoad (cb) { this._et.once('load', cb); },
onLoad (cb) { this._et.on('load', cb); },
offLoad (cb = undefined) { this._et.off('load', cb); },
onError (cb) { this._et.on('error', cb); },
offError (cb = undefined) { this._et.off('error', cb); },
onEnded (cb) { this._et.on('ended', cb); },
offEnded (cb = undefined) { this._et.off('ended', cb); },
onStop (cb) { this._et.on('stop', cb); },
offStop (cb = undefined) { this._et.off('stop', cb); },
_ensureLoaded (cb) {
if (this._loaded) {
cb();
} else {
this.onceLoad(() => {
this._loaded = true;
cb();
});
}
}
});
module.exports = Audio;

View File

@@ -0,0 +1,389 @@
const Audio = require('./Audio');
let _instanceId = 0;
const _id2audio = {};
const _audioPool = [];
const _maxPoolSize = 32;
function handleVolume (volume) {
if (volume === undefined) {
// set default volume as 1
volume = 1;
}
else if (typeof volume === 'string') {
volume = Number.parseFloat(volume);
}
return volume;
};
function getOrCreateAudio (path, serializedDuration) {
let audio;
_audioPool.some((item, index) => {
if (item.getSrc() === path) {
audio = item;
_audioPool.splice(index, 1);
return true;
}
return false;
});
if (!audio) {
audio = new Audio(path, serializedDuration);
}
audio.id = ++_instanceId;
audio.onEnded(() => {
putOrDestroyAudio(audio);
});
return audio;
}
function putOrDestroyAudio (audio) {
if (_audioPool.includes(audio)) {
return;
}
delete _id2audio[audio.id];
audio.reset();
if (_audioPool.length < _maxPoolSize) {
_audioPool.push(audio);
} else {
audio.destroy();
}
}
const _maxPlayingAudio = 10;
cc.audioEngine = {
AudioState: Audio.State,
_maxPoolSize: 32,
_id2audio,
_pauseIDCache: [],
_play (clip, loop, volume) {
let path;
if (typeof clip === 'string') {
path = clip;
} else {
path = clip.nativeUrl;
}
let audio = getOrCreateAudio(path, clip.duration);
volume = handleVolume(volume);
audio.setLoop(loop || false);
audio.setVolume(volume);
audio.play();
return audio;
},
play: function (clip, loop, volume) {
const audio = this._play(clip, loop, volume);
this._id2audio[audio.id] = audio;
return audio.id;
},
setLoop: function (id, loop) {
const audio = this._id2audio[id];
if (audio) {
audio.setLoop(loop);
}
},
isLoop: function (id) {
const audio = this._id2audio[id];
if (audio) {
return audio.getLoop();
}
return false;
},
setVolume: function (id, volume) {
volume = handleVolume(volume);
const audio = this._id2audio[id];
if (audio) {
return audio.setVolume(volume);
}
},
getVolume: function (id) {
const audio = this._id2audio[id];
if (audio) {
return audio.getVolume();
}
return 1;
},
setCurrentTime: function (id, sec) {
const audio = this._id2audio[id];
if (audio) {
return audio.seek(sec);
}
},
getCurrentTime: function (id) {
const audio = this._id2audio[id];
if (audio) {
return audio.getCurrentTime();
}
return 0;
},
getDuration: function (id) {
const audio = this._id2audio[id];
if (audio) {
return audio.getDuration();
}
return 1;
},
getState: function (id) {
const audio = this._id2audio[id];
if (audio) {
return audio.getState();
}
return Audio.State.INITIALZING;
},
isPlaying: function(id) {
const audio = this._id2audio[id];
if (audio) {
return audio.getState() === Audio.State.PLAYING;
}
return false;
},
setFinishCallback: function (id, callback) {
const audio = this._id2audio[id];
if (audio) {
return audio.finishCB = callback;
}
},
pause: function (id) {
const audio = this._id2audio[id];
if (audio) {
audio.pause();
}
},
pauseAll: function () {
for (let id in this._id2audio) {
const audio = this._id2audio[id];
if (audio) {
audio.pause();
}
}
},
resume: function (id) {
const audio = this._id2audio[id];
if (audio) {
audio.resume();
}
},
resumeAll: function () {
for (let id in this._id2audio) {
const audio = this._id2audio[id];
if (audio) {
audio.resume();
}
}
},
stop: function (id) {
const audio = this._id2audio[id];
if (audio) {
audio.stop();
}
},
stopAll: function () {
for (let id in this._id2audio) {
const audio = this._id2audio[id];
if (audio) {
audio.stop();
}
}
},
setMaxAudioInstance: function (num) {
// NOT SUPPPORTED
},
getMaxAudioInstance: function () {
return _maxPlayingAudio;
},
uncache: function (clip) {
var filePath = clip;
if (typeof clip === 'string') {
// backward compatibility since 1.10
cc.warnID(8401, 'cc.audioEngine', 'cc.AudioClip', 'AudioClip', 'cc.AudioClip', 'audio');
filePath = clip;
}
else {
if (!clip) {
return;
}
filePath = clip.nativeUrl;
}
for (let id in _id2audio) {
const audio = this._id2audio[id];
if (audio && audio.getSrc() === filePath) {
audio.stop();
putOrDestroyAudio(audio);
}
}
},
uncacheAll: function () {
this.stopAll();
for (let id in _id2audio) {
const audio = _id2audio[id];
if (audio) {
audio.stop();
putOrDestroyAudio(audio);
}
}
},
_break: function () {
// DO NOTHING
},
_restore: function () {
// DO NOTHING
},
///////////////////////////////
// Classification of interface
_music: null,
_effectVolume: 1,
playMusic: function (clip, loop) {
if (this._music) {
if (this._music.getSrc() !== clip.nativeUrl) {
this._music.stop();
putOrDestroyAudio(this._music);
const audio = this._play(clip, loop);
this._music = audio;
} else {
this._music.stop();
this._music.play();
}
} else {
const audio = this._play(clip, loop);
this._music = audio;
}
return this._music.id;
},
stopMusic: function () {
this._music.stop();
},
pauseMusic: function () {
this._music.pause();
},
resumeMusic: function () {
this._music.resume();
},
getMusicVolume: function () {
if (this._music) {
return this._music.getVolume();
}
return 1;
},
setMusicVolume: function (volume) {
volume = handleVolume(volume);
if (this._music) {
this._music.setVolume(volume);
}
},
isMusicPlaying: function () {
return this._music.getState() === Audio.State.PLAYING;
},
playEffect: function (clip, loop) {
return this.play(clip, loop, this._effectVolume);
},
setEffectsVolume: function (volume) {
volume = handleVolume(volume);
var musicId = this._music.id;
this._effectVolume = volume;
for (var id in _id2audio) {
var audio = _id2audio[id];
if (!audio || audio.id === musicId) continue;
audio.setVolume(volume);
}
},
getEffectsVolume: function () {
return this._effectVolume;
},
pauseEffect: function (id) {
return this.pause(id);
},
pauseAllEffects: function () {
var musicId = this._music.id;
for (var id in _id2audio) {
var audio = _id2audio[id];
if (!audio || audio.id === musicId) continue;
audio.pause();
}
},
resumeEffect: function (id) {
this.resume(id);
},
resumeAllEffects: function () {
var musicId = this._music.id;
for (var id in _id2audio) {
var audio = _id2audio[id];
if (!audio || audio.id === musicId) continue;
audio.resume();
}
},
stopEffect: function (id) {
return this.stop(id);
},
stopAllEffects: function () {
var musicId = this._music.id;
for (var id in _id2audio) {
var audio = _id2audio[id];
if (!audio || audio.id === musicId) continue;
audio.stop();
}
}
};

View File

@@ -0,0 +1,139 @@
(function(){
if (!(cc && cc.AudioClip && cc.AudioSource)) {
return;
}
const Audio = require('./Audio');
const AudioClip = cc.AudioClip;
const proto = cc.AudioSource.prototype;
Object.defineProperties(proto, {
isPlaying: {
get () {
var state = this.audio.getState();
return state === cc._Audio.State.PLAYING;
}
},
clip: {
get: function () {
return this._clip;
},
set: function (value) {
if (value === this._clip) {
return;
}
if (!(value instanceof AudioClip)) {
return cc.error('Wrong type of AudioClip.');
}
this._clip = value;
this.audio.stop();
this.audio.destroy();
this.audio = new Audio(value.nativeUrl, value.duration);
},
},
volume: {
get: function () {
return this._volume;
},
set: function (value) {
value = misc.clamp01(value);
this._volume = value;
if (!this._mute) {
this.audio.setVolume(value);
}
return value;
},
},
mute: {
get: function () {
return this._mute;
},
set: function (value) {
if (this._mute === value) {
return;
}
this._mute = value;
this.audio.setVolume(value ? 0 : this._volume);
return value;
},
},
loop: {
get: function () {
return this._loop;
},
set: function (value) {
this._loop = value;
this.audio.setLoop(value);
return value;
}
},
})
Object.assign(proto, {
onLoad: function () {
if(this.audio && this.audio instanceof Audio)
return;
if (this._clip) {
this.audio = new Audio(this._clip.nativeUrl, this._clip.duration);
}
},
onEnable: function () {
if (this.playOnLoad && this._firstlyEnabled) {
this._firstlyEnabled = false;
this.play();
}
},
onDisable: function () {
this.stop();
},
onDestroy: function () {
this.audio.destroy();
},
play: function () {
if ( !this._clip ) return;
var audio = this.audio;
audio.setVolume(this._mute ? 0 : this._volume);
audio.setLoop(this._loop);
audio.seek(0);
audio.play();
},
stop: function () {
this.audio.stop();
},
pause: function () {
this.audio.pause();
},
resume: function () {
this.audio.resume();
},
rewind: function(){
this.audio.seek(0);
},
getCurrentTime: function () {
return this.audio.getCurrentTime();
},
setCurrentTime: function (time) {
this.audio.seek(time);
return time;
},
getDuration: function () {
return this.audio.getDuration();
}
});
})();

View File

@@ -0,0 +1,92 @@
(function () {
if (!(cc && cc.EditBox)) {
return;
}
const EditBox = cc.EditBox;
const js = cc.js;
const KeyboardReturnType = EditBox.KeyboardReturnType;
const MAX_VALUE = 65535;
function getKeyboardReturnType (type) {
switch (type) {
case KeyboardReturnType.DEFAULT:
case KeyboardReturnType.DONE:
return 'done';
case KeyboardReturnType.SEND:
return 'send';
case KeyboardReturnType.SEARCH:
return 'search';
case KeyboardReturnType.GO:
return 'go';
case KeyboardReturnType.NEXT:
return 'next';
}
return 'done';
}
const BaseClass = EditBox._ImplClass;
function MiniGameEditBoxImpl () {
BaseClass.call(this);
}
js.extend(MiniGameEditBoxImpl, BaseClass);
EditBox._ImplClass = MiniGameEditBoxImpl;
Object.assign(MiniGameEditBoxImpl.prototype, {
init (delegate) {
if (!delegate) {
cc.error('EditBox init failed');
return;
}
this._delegate = delegate;
},
beginEditing () {
// In case multiply register events
if (this._editing) {
return;
}
let delegate = this._delegate;
this._showPrompt();
this._editing = true;
delegate.editBoxEditingDidBegan();
},
endEditing () {
cc.warn(`Can't support to end editing.`);
},
_showPrompt () {
let self = this;
let delegate = this._delegate;
let multiline = (delegate.inputMode === EditBox.InputMode.ANY);
let maxLength = (delegate.maxLength < 0 ? MAX_VALUE : delegate.maxLength);
if (multiline) {
cc.warn(`Multiline editing is not supported`);
}
my.prompt({
title: '',
message: delegate.placeholder,
// placeholder: delegate.placeholder,
okButtonText: getKeyboardReturnType(delegate.returnType),
cancelButtonText: 'cancel',
success: (result) => {
if (result.ok) {
let inputValue = result.inputValue;
inputValue = (maxLength <= inputValue.length) ? inputValue.substring(0, maxLength) : inputValue;
if (delegate._string !== inputValue) {
delegate.editBoxTextChanged(inputValue);
}
delegate.editBoxEditingReturn();
}
self._editing = false;
delegate.editBoxEditingDidEnded();
},
});
},
});
})();

View File

@@ -0,0 +1,55 @@
if (cc && cc.Label) {
const gfx = cc.gfx;
const Label = cc.Label;
// shared label canvas
let _sharedLabelCanvas = my.createCanvas();
let _sharedLabelCanvasCtx = _sharedLabelCanvas.getContext('2d');
let canvasData = {
canvas: _sharedLabelCanvas,
context: _sharedLabelCanvasCtx,
};
cc.game.on(cc.game.EVENT_ENGINE_INITED, function () {
Object.assign(Label._canvasPool, {
get() {
return canvasData;
},
put() {
// do nothing
}
});
});
let _originUpdateMaterial = Label.prototype._updateMaterialWebgl;
// fix ttf font black border
Object.assign(Label.prototype, {
_updateMaterialWebgl () {
_originUpdateMaterial.call(this);
// init blend factor
let material = this._materials[0];
if (!this._frame || !material) {
return;
}
let dstBlendFactor = cc.macro.BlendFactor.ONE_MINUS_SRC_ALPHA;
let srcBlendFactor;
if (!(__globalAdapter.isDevTool || this.font instanceof cc.BitmapFont)) {
// Premultiplied alpha on runtime
srcBlendFactor = cc.macro.BlendFactor.ONE;
}
else {
srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA;
}
// set blend func
material.effect.setBlend(
true,
gfx.BLEND_FUNC_ADD,
srcBlendFactor, dstBlendFactor,
gfx.BLEND_FUNC_ADD,
srcBlendFactor, dstBlendFactor,
);
},
});
}

View File

@@ -0,0 +1,2 @@
// NOTE: can't cache file on Taobao iOS end
cc.assetManager.cacheManager.cacheEnabled = cc.sys.os !== cc.sys.OS_IOS;

View File

@@ -0,0 +1,6 @@
require('./AudioEngine');
require('./AudioSource');
require('./AssetManager');
require('./cache-manager');
require('./Label');
require('./Editbox');