如何在Space Cadet Pinball浏览器版中捕获事件并输出console.log
三维弹球浏览器移植版:添加声音日志与捕获游戏事件方案
问题背景
接触到Windows XP经典游戏三维弹球的浏览器移植项目,想要给游戏每一个发声动作添加console.log("Sound");输出,或者捕获球碰撞墙壁、触发机关这类事件,但找不到对应逻辑位置。找到代码第5297行的一段音频相关代码,删除后声音依然正常播放,没有任何影响。
这段被删除的代码为音频预加载逻辑:
audioPlugin["handle"] = function audioPlugin_handle(byteArray, name, onload, onerror) { var done = false; function finish(audio) { if (done) return; done = true; Module["preloadedAudios"][name] = audio; if (onload) onload(byteArray) } function fail() { if (done) return; done = true; Module["preloadedAudios"][name] = new Audio; if (onerror) onerror() } if (Browser.hasBlobConstructor) { try { var b = new Blob([byteArray], { type: Browser.getMimetype(name) }) } catch (e) { return fail() } var url = Browser.URLObject.createObjectURL(b); var audio = new Audio; audio.addEventListener("canplaythrough", function() { finish(audio) }, false); audio.onerror = function audio_onerror(event) { if (done) return; console.log("warning: browser could not fully decode audio " + name + ", trying slower base64 approach"); function encode64(data) { var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var PAD = "="; var ret = ""; var leftchar = 0; var leftbits = 0; for (var i = 0; i < data.length; i++) { leftchar = leftchar << 8 | data[i]; leftbits += 8; while (leftbits >= 6) { var curr = leftchar >> leftbits - 6 & 63; leftbits -= 6; ret += BASE[curr] } } if (leftbits == 2) { ret += BASE[(leftchar & 3) << 4]; ret += PAD + PAD } else if (leftbits == 4) { ret += BASE[(leftchar & 15) << 2]; ret += PAD } return ret } audio.src = "data:audio/x-" + name.substr(-3) + ";base64," + encode64(byteArray); finish(audio) }; audio.src = url; Browser.safeSetTimeout(function() { finish(audio) }, 1e4) } else { return fail() } }; Module["preloadPlugins"].push(audioPlugin);
为什么这段代码删除后没影响?
这段代码是音频资源预加载逻辑,仅负责把游戏音频文件转成Blob/Base64格式,存入Module.preloadedAudios供后续播放调用,本身不处理音频播放动作。删除它后,要么浏览器缓存已经保存了音频资源,要么游戏有 fallback 加载逻辑,所以声音依然能正常播放。
解决方案
1. 给所有声音播放添加日志输出
这是Emscripten编译的原生转JS项目,音频播放要么用HTML5 Audio对象,要么用Web Audio API,可通过重写原生播放方法全局捕获:
方法一:捕获HTML5 Audio播放
在浏览器控制台或者游戏代码开头插入以下代码:
// 重写Audio的play方法,添加日志 const originalAudioPlay = Audio.prototype.play; Audio.prototype.play = function() { console.log("Sound played:", this.src.split("/").pop()); // 输出音频文件名 return originalAudioPlay.apply(this, arguments); };
方法二:捕获Web Audio API播放(如果游戏用了这个)
如果游戏用Web Audio的BufferSource播放,重写start方法:
const originalBufferStart = AudioBufferSourceNode.prototype.start; AudioBufferSourceNode.prototype.start = function() { console.log("Web Audio sound triggered"); return originalBufferStart.apply(this, arguments); };
2. 捕获游戏事件(碰撞、机关触发)
游戏核心逻辑由原生代码编译而来,直接找JS里的事件可搜索关键词:
- 在格式化后的代码里搜索
collide、hit、trigger、contact这类碰撞/触发相关的关键词,找到对应逻辑块后插入console.log。 - 比如搜索到碰撞检测的函数后,在函数内部添加
console.log("Ball collided with wall/object");。
如果找不到明确的JS逻辑,还可以尝试:
- 查找Emscripten暴露的原生函数,通过
Module.ccall调用(需知道具体函数名); - 监控球的位置变化(搜索
ball相关的坐标更新代码),当位置突变时判定为碰撞并输出日志。
内容的提问来源于stack exchange,提问作者Антон Пружанов
相关产品推荐
相关产品推荐

