自從威少砍下45+11+11的大號三雙之後,網上出現了各種各樣的神級段子,有一條是這樣的: 威少:Hey,哥們,最近過得咋樣! 濃眉:對方開啟了好友驗證,請先添加對方為好友 威少:。。。。。。 JRS:2333333 看到了一條比賽當天的數據統計:威少45+11+11,杜少32+8+3,伊巴卡19+ ...
自從威少砍下45+11+11的大號三雙之後,網上出現了各種各樣的神級段子,有一條是這樣的: 威少:Hey,哥們,最近過得咋樣! 濃眉:對方開啟了好友驗證,請先添加對方為好友 威少:。。。。。。 JRS:2333333 看到了一條比賽當天的數據統計:威少45+11+11,杜少32+8+3,伊巴卡19+11+2,雷吉傑克遜17+3+6,哈登16+6+16,雷霆管理層真應該改名雷鋒管理層了,現在對雷霆管理層的每日一輪都是JRS們的常態了。 好了,不扯,接著上一篇博客(H5坦克大戰之畫出坦克http://www.cnblogs.com/zhouhuan/p/H5_tankgame.html),這一篇來看看怎麼響應玩家的操作讓坦克進行相應的移動。 1. 瞭解keydown事件 keydown這一鍵盤事件的觸發條件為按下鍵盤上的任意鍵,如果按住不放,則會重發觸發。 示例:
window.onkeydown = function(){ alert("Merry Christmas!"); };此時載入頁面之後,無論按下哪個鍵,都會彈出“Merry Christmas!”的彈窗。 2. 瞭解鍵碼和字元編碼 ① 鍵碼 在發生keydown和keyup事件時,event對象的keyCode(鍵碼)屬性會包含一個代碼,與鍵盤上一個特定的鍵對應。對於數字字母字元集,keyCode屬性的值與ASCII碼中對應小寫字母或數字的編碼相同。字母中的大小寫不影響。
window.onkeydown = function(eve){ alert(eve.keyCode); };此時按鍵盤上的任意鍵,便可得到所按鍵對應的keyCode ② 字元編碼 發生keypress事件時,event對象的charCode屬性會包含一個值,這個值就是按下的那個鍵所代表字元的ASCII編碼,並且,同一個字母的大小寫對應的字元編碼也是不一樣的。 要註意的是,keypress事件只有在按下字元鍵時才會觸發,並不是所有的按鍵,像Ctrl, Alt之類的就不會觸發該事件。 3. 熱身環節 ① 獲取玩家的指令 我們先看看怎麼獲取到玩家的操控指令,這裡我們寫一段代碼:
window.onkeydown = function(eve){ alert("所按鍵對應的鍵碼是: " + eve.keyCode); };大家運行一下就可以知道鍵盤上每一個按鍵所對應的鍵碼是多少了,然後取自己需要的按鍵繼續編寫程式。這裡需要的是方向鍵的上下左右,當然這個在網上可以查到,也非常方便。 我們運行了之後會發現,上下左右對應的鍵碼分別是38, 40, 37, 39。考慮到有些玩家習慣於使用W A S D來操作,那我們把這幾個鍵也做進去,這幾個鍵對應的鍵碼分別是87, 65, 83, 68。 OK,知道了上面這些東西之後我們就可以寫出下麵這段代碼了:
window.onkeydown = function(eve){ if(eve.keyCode == 38 || eve.keyCode == 87){ alert("上"); }else if(eve.keyCode == 40 || eve.keyCode == 83){ alert("下"); }else if(eve.keyCode == 37 || eve.keyCode == 65){ alert("左"); }else if(eve.keyCode == 39 || eve.keyCode == 68){ alert("右"); } };此時,根據玩家的操作便能彈出相應方向的文字。 鑒於上面if語句的條件分支數量略多,我們最好用switch語句改寫一下上面的代碼,這樣可以提高性能,如下:
window.onkeydown = function(eve){ switch(eve.keyCode){ case 38: case 87: alert("上"); break; case 40: case 83: alert("下"); break; case 37: case 65: alert("左"); break; case 39: case 68: alert("右"); } };
② 封裝畫坦克的函數 前面我們寫的畫坦克的代碼其實是面向過程的,我們將它拿過來改巴改巴做以封裝:
function drawTank(x,y){ var myCanvas = document.getElementById('floor'); var cxt = myCanvas.getContext('2d'); cxt.fillStyle = "#542174"; cxt.fillRect(x,y,20,65); cxt.fillRect(x+70,y,20,65); cxt.fillRect(x+23,y+10,44,50); cxt.fillStyle = "#FCB827"; cxt.beginPath(); cxt.arc(x+45,y+35,16,0,2*Math.PI,false); cxt.closePath(); cxt.fill(); cxt.strokeStyle = "#FCB827"; cxt.lineWidth = "8.0"; cxt.moveTo(x+45,y+35); cxt.lineTo(x+45,y-25); cxt.stroke(); }這個函數調用的時候傳兩個參數(x, y),分別代表坦克左上角的X坐標,Y坐標。 封裝好之後,在任何地方只要一調用,便可以造出一個坦克了:
drawTank(150,200); //以(150,200)的點為坦克的左上角(左邊履帶的左上角)造一個坦克③ 瞭解clearRect()方法 有一個前面遺漏掉的知識點clearRect()方法,這個方法是做游戲的關鍵,用來清空指定矩形內的所有像素,傳四個參數(x, y, width, height),前兩個參數表示要清除的矩形的左上角坐標,後兩個參數表示要清除的矩形的寬高。 比如我們先畫一個矩形:
var myCanvas = document.getElementById('floor'); var cxt = myCanvas.getContext('2d'); cxt.fillStyle = "orange"; cxt.fillRect(50,50,300,80);
得到:
我們再加上下麵這句代碼運行一下:cxt.clearRect(0,0,800,500);此時會發現整個畫布又空空如也了,因為我們把整個畫布的像素都清除掉了。 4. 熱身完畢,正式開始 前面熱身熱了這麼久,相信大家已經可以寫出一個根據玩家的操作移動的坦克了。 我們儘量以面向對象的思想來寫每一個過程,代碼如下:
//封裝一個獲取繪圖環境的函數 function getCxt(){ var myCanvas = document.getElementById('floor'), myContext = myCanvas.getContext('2d'); return myContext; } //封裝一個畫坦克的函數,傳兩個參數x,y,分別代表左上角的橫縱坐標 function drawTank(x,y){ var cxt = getCxt(); cxt.fillStyle = "#542174"; cxt.fillRect(x,y,20,65); cxt.fillRect(x+70,y,20,65); cxt.fillRect(x+23,y+10,44,50); cxt.fillStyle = "#FCB827"; cxt.beginPath(); cxt.arc(x+45,y+35,16,0,2*Math.PI,false); cxt.closePath(); cxt.fill(); cxt.strokeStyle = "#FCB827"; cxt.lineWidth = "8.0"; cxt.moveTo(x+45,y+35); cxt.lineTo(x+45,y-25); cxt.stroke(); } //初始化一個對象myTank,用來存儲一些屬性和方法,避免污染全局空間 var myTank = {}; myTank.x = 350; myTank.y = 400; myTank.step = 3; //設置步長,步長越大那麼坦克運動的速度越快 //先畫一個坦克出來 drawTank(myTank.x,myTank.y); //封裝一個更新戰場的函數 function updateFloor(){ var cxt = getCxt(); cxt.clearRect(0,0,800,500); //更新之前先清除畫布 drawTank(myTank.x,myTank.y); //清除完之後重新造坦克,坦克要移動就必須實時地根據坐標重新來造 } //設置一個間歇調用的函數,每隔100ms更新一下戰場 setInterval(function(){ updateFloor(); },100); //響應玩家的操作指令 window.onkeydown = function(eve){ switch(eve.keyCode){ case 38: case 87: myTank.y -= myTank.step; //Y坐標減小向上移動 break; case 40: case 83: myTank.y += myTank.step; //Y坐標增加向下移動 break; case 37: case 65: myTank.x -= myTank.step; //X坐標減小向左移動 break; case 39: case 68: myTank.x += myTank.step; //X坐標增加向右移動 } };所有必要的說明都已經寫在了註釋中。這樣寫出來之後,我們發現坦克已經可以隨著玩家的按鍵上下左右移動了,但是還存在一點問題,坦克運動起來非常的生硬,不管向哪個方向動它的頭一直都是朝上的,我們必須在這個基礎上做以修改。 不過今天先寫到這裡,接下來的內容筆者寫好之後下次再分享給大家! 明天周一,工作的要上班了,上學的也要上課了,大家伙加油哦,過了下周,大家離夢想便又近了一步(\(^o^)/)也在此祝福所有考研的同學,希望大家都能獲得一個自己滿意、別人羡慕的成績!祝福你們! (註:一個人的力量畢竟有限,如果在閱讀的過程中發現有描述不當或者錯誤的地方,歡迎隨時指正,筆者不勝感激!)