0x00 CHIP8簡介
我們根據CHIP8的Wiki可以了解到CHIP8是一種解釋性的編程語言。最初被應用是在1970年代中期。CHIP8的程序運行在CHIP8虛擬機中,它的出現讓電子游戲編程變得簡單些了(相對于那個年代來說)。用CHIP8實現的電子游戲有,比如小蜜蜂,俄羅斯方塊,吃豆人等。更多可以前往CHIP8的Wiki了解。
0x01 創建CHIP8對象
我們假設CHIP8是由處理器、鍵盤、顯示屏與揚聲器組成,其中CPU是CHIP8核心,那么代碼應該像這樣的:
<!DOCTYPE html><html><head> <title>創建Chip8對象</title></head><body> <script> (function () { function CPU() {/*...*/ }; function Screen() {/*...*/ }; function Keyboard() {/*...*/ }; function Speaker(){/*...*/ }; window.CHIP8 = function () { var c8 = new CPU(); c8.screen = new Screen(); c8.speaker = new Speaker(); c8.input = new Keyboard(); return c8; }; })(); </script></body></html>
0x02 編寫簡單的顯示屏
根據CHIP8的Wiki可以了解到,CHIP8顯示分辨率是64X32的像素,并且是單色的。某像素點為1則屏幕上顯示相應像素點,為0則不顯示。但某個像素點由有到無則進位標識被設置為1,可以用來進行沖撞檢測。
那么代碼應該像這樣:
function Screen() { this.rows = 32;//32行 this.columns = 64;//64列 this.resolution = this.rows * this.columns;//分辨率 this.bitMap = new Array(this.resolution);//像素點陣 this.clear = function () { this.bitMap = new Array(this.resolution); } this.render = function () { };//顯示渲染 this.setPixel = function (x, y) {//在屏幕坐標(x,y)進行計算與顯示 // 顯示溢出處理 if (x > this.columns - 1) while (x > this.columns - 1) x -= this.columns; if (x < 0) while (x < 0) x += this.columns; if (y > this.rows - 1) while (y > this.rows - 1) y -= this.rows; if (y < 0) while (y < 0) y += this.rows; //獲取點陣索引 var location = x + (y * this.columns); //反向顯示,假設二值顏色黑白分別用1、0代表,那么值為1那么就將值設置成0,同理0的話變成1 this.bitMap[location] = this.bitMap[location] ^ 1; return !this.bitMap[location]; } };
編寫好顯示模塊我們編寫顯示屏來測試顯示模塊(在線查看屏幕測試):
var chip8 = CHIP8(); chip8.screen.render = function () {//自定義實現顯示渲染 var boxs = document.getElementById("boxs"); boxs.innerHTML = ""; for (var i of this.bitMap) { var d = document.createElement("span"); d.style = "width: 5px;height: 5px;float: left;"; d.style.backgroundColor = i ? "#000" : "#fff"; boxs.appendChild(d); } };/** 測試 **/chip8.screen.setPixel(2, 2);//設置x,y坐標像素chip8.screen.render(); chip8.screen.setPixel(2, 2);//設置x,y坐標像素
0x03 編寫揚聲器
這里需要參考 Web APIs:
API https://developer.mozilla.org/en-US/docs/Web/API/AudioContext API https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode
示例 https://mdn.github.io/violent-theremin/
示例 https://codepen.io/gregh/pen/LxJEaj
揚聲器也十分簡單:
function Speaker() { var contextClass = (window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.oAudioContext || window.msAudioContext) , context , oscillator , gain; if (contextClass) { context = new contextClass(); gain = context.createGain(); gain.connect(context.destination); } //播放聲音 this.play = function (frequency) { //API https://developer.mozilla.org/en-US/docs/Web/API/OscillatorNode //示例 https://mdn.github.io/violent-theremin/ if (context && !oscillator) { oscillator = context.createOscillator(); oscillator.frequency.value = frequency || 440;//聲音頻率 oscillator.type = oscillator.TRIANGLE;//波形這里用的是三角波 查看示例:https://codepen.io/gregh/pen/LxJEaj oscillator.connect(gain); oscillator.start(0); } } //停止播放 this.clear = this.stop = function () { if (oscillator) { oscillator.stop(0); oscillator.disconnect(0); oscillator = null; } } };
編寫好揚聲器我們可以對揚聲器進行測試(在線查看揚聲器測試):
<!DOCTYPE html><html><head> <title>編寫揚聲器</title></head><body> 頻率: <input type="range" id="frequency" value="440" min="100" max="1000"> <label id="showfv">(440)</label> <button id="play_btn">播放</button> <script> (function () { function CPU() {/*...*/ }; function Screen() {/*...*/ };//略... function Keyboard() {/*...*/ }; function Speaker() {/*...*/};//略... window.CHIP8 = function () { var c8 = new CPU(); c8.screen = new Screen(); c8.speaker = new Speaker(); c8.input = new Keyboard(); return c8; }; })(); var chip8 = CHIP8(); //======= var f = document.getElementById("frequency"); var isPlay = false; var play_btn = document.getElementById("play_btn"); f.onchange = function () { var v = Number(this.value); document.getElementById("showfv").innerHTML = "(" + v + ")"; if (isPlay) { chip8.speaker.stop(); chip8.speaker.play(v); } }; play_btn.onclick = function () { isPlay = !isPlay; this.innerHTML = isPlay ? '停止' : '播放'; if (!isPlay) chip8.speaker.stop(); else chip8.speaker.play(f.value); }; </script></body></html>
相信看了本文案例你已經掌握了方法,更多精彩請關注Gxl網其它相關文章!
相關閱讀:
ES6的字符串模板詳解
ES6的變量的作用域與聲明詳解
怎樣利用插件工具將ES6的代碼轉化成ES5
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com