JSNES 官网 https://jsnes.org/
var jsnes = require("./nes/index.js");
var sysinfo = wx.getSystemInfoSync();
var SCREEN_WIDTH = 360;
var SCREEN_HEIGHT = 640;
var FRAMEBUFFER_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT;
var canvas_ctx, image;
var framebuffer_u8, framebuffer_u32;
var AUDIO_BUFFERING = 512;
var SAMPLE_COUNT = 4 * 1024;
var SAMPLE_MASK = SAMPLE_COUNT - 1;
var audio_samples_L = new Float32Array(SAMPLE_COUNT);
var audio_samples_R = new Float32Array(SAMPLE_COUNT);
var audio_write_cursor = 0,
audio_read_cursor = 0;
var nes = null;
/**
* 游戏主函数
*/
export default class Main {
constructor() {
// 维护当前 requestAnimationFrame 的 id
this.aniId = 0
this.restart()
}
restart() {
let ctx = canvas.getContext('2d')
canvas_ctx = ctx;
image = canvas_ctx.getImageData(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
canvas_ctx.fillStyle = "black";
canvas_ctx.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
// Allocate framebuffer array.
var buffer = new ArrayBuffer(image.data.length);
framebuffer_u8 = new Uint8ClampedArray(buffer);
framebuffer_u32 = new Uint32Array(buffer);
nes = new jsnes.NES({
onFrame: function (framebuffer_24) {
for (var i = 0; i < FRAMEBUFFER_SIZE; i++) framebuffer_u32[i] = 0xFF000000 | framebuffer_24[i];
}
});
this.bindLoop = this.loop.bind(this)
window.cancelAnimationFrame(this.aniId);
let that = this;
this.nes_load_url(() => {
console.log('load_succ');
that.aniId = window.requestAnimationFrame(
that.bindLoop,
canvas_ctx
)
/*
setTimeout(() => {
that.keyboard(nes.buttonDown, 13);
that.keyboard(nes.buttonUp, 13);
console.log('start');
}, 1000);
*/
});
}
keyboard(callback, keyCode) {
var player = 1;
switch (keyCode) {
case 38: // UP
callback(player, jsnes.Controller.BUTTON_UP); break;
case 40: // Down
callback(player, jsnes.Controller.BUTTON_DOWN); break;
case 37: // Left
callback(player, jsnes.Controller.BUTTON_LEFT); break;
case 39: // Right
callback(player, jsnes.Controller.BUTTON_RIGHT); break;
case 65: // 'a' - qwerty, dvorak
case 81: // 'q' - azerty
callback(player, jsnes.Controller.BUTTON_A); break;
case 83: // 's' - qwerty, azerty
case 79: // 'o' - dvorak
callback(player, jsnes.Controller.BUTTON_B); break;
case 9: // Tab
callback(player, jsnes.Controller.BUTTON_SELECT); break;
case 13: // Return
callback(player, jsnes.Controller.BUTTON_START); break;
default: break;
}
}
// 实现游戏帧循环
loop() {
this.aniId = window.requestAnimationFrame(
this.bindLoop,
canvas_ctx
)
//ctx.clearRect(0, 0, canvas.width, canvas.height)
image.data.set(framebuffer_u8);
console.log(image);
canvas_ctx.putImageData(image, 0, 0);
nes.frame();
}
nes_load_data(rom_data, callback) {
nes.loadROM(rom_data);
callback && callback();
}
nes_load_url(callback) {
let that = this;
var url = 'https://localhost/test/InterglacticTransmissing.nes';
wx.request({
url: url,
data: 'ArrayBuffer',
dataType:"text",
header: {
//'content-type': 'text/plain; charset=x-user-defined' // 默认值
},
success: function (res) {
that.nes_load_data(res.data, callback);
}
})
}
}
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.