言歸正傳,游戲的界面如下:
其實游戲本身應該是挺簡單的,以下根據幾個模塊解說一下:
一:用戶界面
游戲中有圖片和<canvas>繪制的矩形、圓形。在開始編寫前應該準備好游戲所需要的圖片。我自己用PS簡單畫了幾個,然后用VC寫個小程序將圖片進行反色、放縮處理就得到了全部圖片:例如自己畫了幾個:
其次關于界面押分、啟動、投幣、得分、積分等,首先需要<canvas>標簽:
<canvas id="mycanvas" width="900" height="650" onclick="dealclick(con)" onmousemove="dealmove(con)" style="border:1px solid yellow;"> Your brower does not support canvas of HTML5! </canvas>
<span style="font-size:18px;"> </span>
*****創建顯示線條框架的函數***************/ function showFrame(con, x, y, space) { con.beginPath(); con.lineWidth = 1; con.moveTo(x, y-1); con.lineTo(x + space * 7, y-1); con.moveTo(x, y + space); con.lineTo(x + space * 7, y + space); con.moveTo(x, y + space * 6-1); con.lineTo(x + space * 7-1, y + space * 6); con.moveTo(x, y + space * 7); con.lineTo(x + space * 7, y + space * 7); con.moveTo(x, y); con.lineTo(x, y + space * 7); con.moveTo(x+space , y); con.lineTo(x + space, y + space * 7); con.moveTo(x + space * 6, y); con.lineTo(x + space * 6, y + space * 7); con.moveTo(x + space * 7, y); con.lineTo(x + space * 7, y + space * 7); con.closePath(); con.stroke(); } /********************************************/ /****創建顯示某個特定圖片的函數*************/ function showImage(i, flag,x,y,con) //1為西瓜,0為小西瓜,2為黑西瓜,3為黑小西瓜 { var img = new Image(); switch (i) { case 1: if (flag == 1) img.src = "蘋果.png"; else if (flag == 0) img.src = "小蘋果.png"; else if (flag == 3) img.src = "黑蘋果.bmp"; else img.src = "黑小蘋果.bmp"; break; case 2: if (flag == 1) img.src = "橙子.png"; else if (flag == 0) img.src = "小橙子.png"; else if (flag == 3) img.src = "黑橙子.bmp"; else img.src = "黑小橙子.bmp"; break; case 3: if (flag == 1) img.src = "芒果.png"; else if (flag == 0) img.src = "小芒果.png"; else if (flag == 3) img.src = "黑芒果.bmp"; else img.src = "黑小芒果.bmp"; break; case 4: if (flag == 1) img.src = "鈴鐺.png"; else if (flag == 0) img.src = "小鈴鐺.png"; else if (flag == 3) img.src = "黑鈴鐺.bmp"; else img.src = "黑小鈴鐺.bmp"; break; case 5: if (flag == 1) img.src = "西瓜.png"; else if (flag == 0) img.src = "小西瓜.png"; else if (flag == 3) img.src = "黑西瓜.bmp"; else img.src = "黑小西瓜.bmp"; break; case 6: if (flag == 1) img.src = "雙星.png"; else if (flag == 0) img.src = "小雙星.png"; else if (flag == 3) img.src = "黑雙星.bmp"; else img.src = "黑小雙星.bmp"; break; case 7: if (flag == 1) img.src = "雙七.png"; else if (flag == 0) img.src = "小雙七.png"; else if (flag == 3) img.src = "黑雙七.bmp"; else img.src = "黑小雙七.bmp"; break; case 8: if (flag == 1) img.src = "大王.png"; else if (flag == 0) img.src = "小王.png"; else if (flag == 3) img.src = "黑大王.bmp"; else img.src = "黑小王.bmp"; break; case 9: if (flag == 1) img.src = "機會.png"; else img.src = "黑機會.bmp"; default: break; } img.onload = function () { con.drawImage(img, x, y); } } /********************************************************************/ /**************顯示得分與積分***********************/ function showScore(con, win_score, score) { con.save(); con.font = "40px impact"; con.fillStyle = "red"; con.fillText("得分", 160, 35); con.fillText("積分", 400, 35); con.fillStyle = "#3DD369"; con.fillRect(160, 42, 74, 35); con.fillRect(400, 42, 74, 35); var str = win_score.toString(); con.font = "30 宋體"; con.fillStyle = "red"; con.fillText(str, 160, 70); str = score.toString(); con.fillText(str, 400, 70); con.restore(); } /**************創建顯示大小的函數**************/ function showBigSmall(con) //大小 { con.save(); con.beginPath(); var g = con.createRadialGradient(230, 320, 0, 230, 320, 20); //創建漸變顏色 g.addColorStop(0.2, "#C8EE2B"); //黃 g.addColorStop(0.8, "#BCC1AC"); // con.fillStyle = g; con.arc(230, 320, 20, 0, Math.PI * 2, true); con.fill(); con.closePath(); con.restore(); con.save(); con.beginPath(); var g1 = con.createRadialGradient(370, 320, 0, 370, 320, 20); //創建漸變顏色 g1.addColorStop(0.2, "#C8EE2B"); //黃 g1.addColorStop(0.8, "#BCC1AC"); // con.fillStyle = g1; con.arc(370, 320, 20, 0, Math.PI * 2, true); con.fillStyle = ""; con.fill(); con.closePath(); con.fillStyle = "black"; con.font = "30px 楷體"; con.fillText("大", 215, 330); con.fillText("小", 355, 330); con.restore(); } /*******創建顯示投幣與退幣的函數****************/ function showGiveQuit(con) //投與退 { con.save(); con.beginPath(); var g = con.createRadialGradient(200, 260, 0, 200, 260, 15); //創建漸變顏色 g.addColorStop(0.2, "#C8EE2B"); //黃 g.addColorStop(0.8, "#BCC1AC"); // con.fillStyle = g; con.arc(200, 260, 15, 0, Math.PI * 2, true); con.fill(); con.closePath(); con.restore(); con.save(); con.beginPath(); var g1 = con.createRadialGradient(400, 260, 0, 400, 260, 15); //創建漸變顏色 g1.addColorStop(0.2, "#C8EE2B"); //黃 g1.addColorStop(0.8, "#BCC1AC"); // con.fillStyle = g1; con.arc(400, 260, 15, 0, Math.PI * 2, true); con.fill(); con.closePath(); con.restore(); con.save(); con.beginPath(); g1 = con.createRadialGradient(300, 235, 0, 300, 235, 15); //創建漸變顏色 g1.addColorStop(0.2, "#C8EE2B"); //黃 g1.addColorStop(0.8, "#BCC1AC"); // con.fillStyle = g1; con.arc(300, 235, 15, 0, Math.PI * 2, true); con.fill(); con.closePath(); con.fillStyle = "black"; con.font = "30px 楷體"; con.fillText("退幣", 170, 235); con.fillText("投幣", 370, 235);con.fillText("啟動", 270, 210); con.restore(); } /********創建顯示界面的函數**************/ function showSurface(con, x, y, space) { // showFrame(con, x, y, space); //顯示主框架 con.save(); showBeilv(con, y - 80, space); con.restore(); con.save(); showImage(2, 1, x, y, con); showImage(4, 1, x + space, y, con); showImage(8, 0, x + 2 * space, y, con); showImage(8, 1, x + 3 * space, y, con); showImage(1, 1, x + 4 * space, y,con); showImage(1, 0, x + 5 * space, y, con); showImage(3, 1, x + 6 * space, y, con); showImage(4,0,x,y+space,con);showImage(1,1,x,y+2*space,con); showImage(6,0,x,y+4*space,con); showImage(6,1,x,y+5*space,con); showImage(3,1,x,y+6*space,con); showImage(5, 1, x + 6 * space, y + space, con); showImage(5, 0, x + 6 * space, y + 2 * space, con); showImage(1, 1, x + 6 * space, y + 4 * space, con); showImage(2, 0, x + 6 * space, y + 5 * space, con); showImage(2, 1, x + 6 * space, y + 6 * space, con); showImage(3, 0, x + space, y + 6 * space, con); showImage(1, 1, x + 2 * space, y + 6 * space, con); showImage(7, 1, x + 3 * space, y + 6 * space, con); showImage(7, 0, x + 4 * space, y + 6 * space, con); showImage(4, 1, x + 5 * space, y + 6 * space, con); showImage(9, 1, x, y + 3 * space, con); showImage(9, 1, x + 6 * space, y + 3 * space, con); con.restore(); con.save(); showFrame(con, x, y, space); con.restore(); con.save(); showLight(con, 0); con.restore(); con.save(); showGiveQuit(con); con.restore(); init_param(); // gain_score = 200; score = 20; con.save(); showScore(con, gain_score, score); con.restore(); con.save(); showYafen(yafen, con, y, space); con.restore(); con.save(); showBigSmall(con); con.restore(); } /*************************************************/ /***********創建顯示說明和倍率的函數*******************/ function showBeilv(con,y,space) { con.save(); var str; con.fillStyle = "black"; con.lineWidth = 3; con.font = "40px 漢儀丫丫體簡"; str = "*100"; showImage(8, 1, 620, y, con);con.fillText(str, 700, y + 50); str = "*40"; showImage(7, 1, 620, y + space, con);con.fillText(str, 700, y + 50 + space); str = "*30"; showImage(6, 1, 620, y + 2 * space, con); con.fillText(str, 700, y + 50 + 2*space); str = "*20"; showImage(5, 1, 620, y + 3 * space, con); con.fillText(str, 700, y + 50 + 3*space); str = "*20"; showImage(4, 1, 620, y + 4 * space, con); con.fillText(str, 700, y + 50 + 4*space); str = "*15"; showImage(3, 1, 620, y + 5 * space, con); con.fillText(str, 700, y + 50 + 5*space); str = "*10"; showImage(2, 1, 620, y + 6 * space, con); con.fillText(str, 700, y + 50 + 6*space); str = "*5"; showImage(1, 1, 620, y + 7 * space, con); con.fillText(str, 700, y + 50 + 7*space); con.restore(); } /*********************************************/ /******創建顯示各個壓分大小的函數**************/ function showYafen(yafen,con,y,space) { con.save(); con.fillStyle = "#3DD369"; for (var i = 0; i < 8; i++) con.fillRect(780, y + i * space - 60, 60, 40); con.fillStyle = "red"; con.font = "40px 楷體"; for (var j = 0; j < 8; j++) { var str = yafen[7-j].toString(); con.fillText(str, 780, y + j * space - 28); } //其次創建8個按鈕 con.restore(); con.save(); for (var m = 0; m < 8; m++) { con.beginPath(); var g = con.createRadialGradient(860, y+m*space-40, 0, 860, y+m*space-40, 15); //創建漸變顏色 g.addColorStop(0.2, "#C8EE2B"); //黃 g.addColorStop(0.8, "#BCC1AC"); // con.fillStyle = g; con.arc(860, y + m * space - 40, 15, 0, Math.PI * 2, true); con.fill(); con.closePath(); } con.restore(); } /***********************************************/ /***************顯示指示燈的亮滅*************/ function showLight(con, flag) //等 { con.save(); if (flag == 0) //等滅 { var g = con.createRadialGradient(300, 50, 0, 300, 50, 25); //創建漸變顏色 g.addColorStop(0.2, "black"); //黃 g.addColorStop(0.8, "white"); // con.fillStyle = g; con.arc(300, 50, 25, 0, Math.PI * 2, true); con.fill(); } else //等亮 { var g1 = con.createRadialGradient(300, 50, 0, 300, 50, 25); //創建漸變顏色 g1.addColorStop(0.2, "red"); //黃 g1.addColorStop(0.8, "white"); // con.fillStyle = g1; con.arc(300, 50, 25, 0, Math.PI * 2, true); con.fill(); } con.restore(); } /*************************
二:事件處理
在<canvas>標簽中加入了onclick="dealclick(con)"代碼,這是整個事件處理。
其實事件處理包括幾個步驟: 根據坐標找出對應的事件(因為游戲中有押分、啟動、投幣等多個事件),然后再處理對應的事件。
dealclick(con)函數如下:
function dealclick(con) { var posx = event.clientX; var posy = event.clientY; var flag = getPos(posx, posy); //獲得對應的事件序號 //alert(posx.toString()+" "+posy.toString()+" "+flag.toString()); if (flag == 0) //表示不是興趣區域 return; if (flag >= 1 && flag <= 8) //對應的事件是壓分 { deal_yafen_event(flag,con); return; } if (flag >= 9) //對應事件 { switch (flag) // { case 9: deal_quit_event(con); break; //退幣事件 case 10: deal_give_event(con); break; //投幣事件 case 11: begin_event(con); break; //啟動事件 case 12: choseBig(); break; //選大 case 13: choseSmall(); break; ; //選小 case 14: LRevent(1); break; case 15: LRevent(0); break; } } }
其中getPos事件是找出對應事件代號的
/****根據坐標尋找對應位置的函數************/ function getPos(posx, posy) { if (posx < 200 || posx > 1100 || posy < 20 || posy > 670) return 0; //返回零,不在canvas范圍中 if (posx >= 1035 && posx <= 1075) //表示在yafen的橫坐標范圍中 { for (var i = 1; i <= 8; i++) //1-8也分別是序號 { if (posy > Y + (i - 1) * 80 - 35 && posy < Y + (i - 1) * 80 - 5) return 9 - i; //注意1-8分別對應蘋果-大王的位置 } return 0; } if (posx >= 385 && posx <= 615) //在事件啟動范圍中 { if (posx >= 385 && posx <= 415 && posy >= 265 && posy <= 295) return 9; //退幣對應事件9 if (posx >= 585 && posx <= 615 && posy >= 265 && posy <= 295) return 10; //投幣對應事件10 if (posx >= 485 && posx <= 515 && posy >= 240 && posy <= 270) return 11; //啟動對應事件11 if (posx >= 410 && posx <= 250+200 && posy >= 320 && posy <= 360) return 12; //選大 if (posx >= 550 && posx <= 590 && posy >= 320 && posy <= 360) return 13; //選小 if (posx >= 235+200 && posx <= 270+200 && posy >= 410 && posy <= 430) return 14; //左移 if (posx >= 340 + 200 && posx <= 375 + 200 && posy >= 410 && posy <= 430) return 15; //右移 } return 0; }
關于對應的押分,選大、選小事件其實都是比較簡單的, 可以簡單說一下選大選小中關于控制概率的算法, 例如控制莊家贏的概率是70%;可以利用var num=Math.random(); if(num<0.7)就算莊家贏,return true. 這都是比較簡單的。
最復雜的其實是啟動事件。 玩過老虎機的朋友都知道,燈的閃爍、以及閃爍有快慢。 js中只有setInterval() 函數處理定時問題,所以編寫時比較復雜
/********************處理起動事件***************/ function begin_event(con) //啟動事件 { if (isOK == false) return; //表示上一次的啟動還沒有完成 var g=0; for (var e = 0; e < 8; e++) g += yafen[e]; if (g == 0) return; //表示沒有壓分 if (gain_score != 0) //如果右邊有錢先將錢轉到右邊 { score += gain_score; gain_score = 0; showScore(con, gain_score, score); return; } if (repeatYafen == true) //表示重復上次的壓分不變 { showYafen(yafen, con, Y, 80); //顯示壓分 var totalyafen=0; for (var a = 0; a < 8; a++) totalyafen += yafen[a]; if (totalyafen > score) //表示余額不足 return; else score -= totalyafen; //扣分; showScore(con, gain_score, score); } for (n = 0; n < 6; n++) time[n] = 0; n = count = 0; var id = getTheOne(0); //獲取本次中獎的號碼 // var id = 17; //用于實驗 var id2, id3; isOK = false;//表示進入閃爍模式 if (id >= 0 && id <= 15)//沒有中機會 { id2 = getOnlyOne(id); //得到在屏幕中的序號 aim_pos1 = id2; light_flash(id,id2, 0, con); //燈閃爍 } if (id == 16) //中了左機會 { id2 = getTheOne(1); //再次獲得序號 id3 = getOnlyOne(id2); //得到在屏幕中的序號 aim_pos1 = id3; //記錄新的啟示序號 light_flash(id, 0, 1, con); // alert(aim_pos1.toString()); } if (id == 17) //中了右機會 { id2 = getTheOne(1); //在次獲得序號 id3 = getOnlyOne(id2); //得到在屏幕中的位置 aim_pos1 = id3; //alert(id3.toString()); light_flash(id, 12, 2, con); } } /******************************************/
主要介紹一下利用setInterval()介紹一下如何實現遞增的延時,如老虎機燈快停時閃爍的越來越慢。可能我的方法不太好,大家可以參考一下
/*****************閃爍函數1*********************/ function flash1() //閃爍 { var k=0; if (n <count - 5) //這段時間內正常閃爍 { if (n == 0) showImageId(aim_pos, con, 0); else { k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); } showLight(con, n % 2); flashSound(); flashSound(); n++; } else //延時閃爍 { switch(time[0]) //位置 { case 0: time[0]++; k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); flashSound(); showLight(con, n % 2); n++; break; case 1: time[1]++; if(time[1]==2) //時間到 { k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); showLight(con, n % 2); flashSound(); time[0]++; n++; }break; case 2:time[2]++; if(time[2]==3) //時間到 { k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); showLight(con, n % 2); flashSound(); time[0]++; n++; }break; case 3:time[3]++; if(time[3]==4) //時間到 { k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); showLight(con, n % 2); flashSound(); time[0]++; n++; }break; case 4: time[4]++; if(time[4]==5) //時間到 { k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); showLight(con, n % 2); flashSound(); time[0]++; n++; } break; case 5: time[5]++; if (time[5] == 6) //時間到 { k = (aim_pos - 1 + n) % 24; showImageId(k, con, 1); k = (k + 1) % 24; showImageId(k, con, 0); showLight(con, n % 2); flashSound(); clearInterval(jsq); showLight(con, 1); flashSound(); aim_pos = aim_pos1; //更新起始位置 countGainScore(0, con, aim_pos1); repeatYafen = true; //設置默認是重復壓分模式 isOK = true; } } } }
三:背景音樂
游戲中需要游戲背景音樂。 這需要用到html5中的<audio>標簽,然后通過js來控制聲音的播放與暫停
在游戲界面中先載入:
<audio src="sound\HP.wav" id="win"></audio><br /> <audio src="sound\pig.wav" id="lose"></audio><br /> <audio src="sound\CLICK.WAV" id="flash"></audio>
然后利用js來控制, 例如介紹一下選大選小時贏時候的背景音樂
var win = document.getElementById("win"); function winSound() // { win.currentTime = 0; //置于當前 win.play(); }
然后在自己需要控制的地方加入播放函數即可。
四:游戲bug
由于HTML5還不夠成熟,因此瀏覽器對其支持能力不夠好。例如背景音樂,長期使用定時器播放后瀏覽器會失去對<audio>的支持能力。 由于游戲是在瀏覽器中運行的,所以效率相比vc++的程序比較低。 如何腳本過于復雜會直接崩潰。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com