有些奇淫技巧玩好的話,就能提高本身的逼格,這不,一行js
代碼實現一個貪吃蛇小遊戲就成了裝逼到了最高境界嘛!代碼以下:html
(function(){var s = [41,40],d = 1,f = 43,x,c = document.createElement('canvas');c.width=400;c.height=400;c.style.background="#535353";c.textContent="當前瀏覽器不支持canvas標籤";b=c.getContext('2d');function w(s,c){b.fillStyle = c;b.fillRect(s % 20 * 20, ~~(s / 20) * 20 , 18 , 18);};document.onkeydown=function(e){d = s[1] - s[0] == (x = [-1,-20,1,20][(e || event).keyCode - 37] || d ) ? d : x;};!(function(){s.unshift(x = s[0] + d);if(s.indexOf(x,1) > 0 || x < 0 || x > 399 || d == 1 && x % 20 == 0 || d == -1 && x % 20 == 19)return alert('遊戲結束!');w(x,'#2396ef');x === f ? (()=>{while (s.indexOf(f = ~~(Math.random() * 399)) > 0);w(f,'#35e3dc');})() : w(s.pop(),'#535353');setTimeout(arguments.callee,300);})();document.body.appendChild(c);})();
ps
:我不是來裝逼的。!canvas
好了,讓咱們來運行一下這行代碼,看一下效果:segmentfault
看動圖看着不過癮?,好,你本身去線上看看demo
能夠撒,具體示例。數組
裝逼完成,
。瀏覽器
好了,言歸正傳,我怎麼多是來裝逼的,我要來分析一下,這個是怎麼玩的,這纔是個人目的。app
讓咱們拆分代碼來看:dom
首先,最外層包裹了一個自調用函數,以下:函數
(function(){ //具體內容 })(); //自調用函數固然不止這樣的寫法
而後第二步,要畫一個場景,那很明顯,要用HTML5
的canvas
標籤,咱們能夠採用document.createElement()
這個方法來建立一個元素,繼續:學習
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); })();
蛇運動的場景確定是固定大小的,也就是說,咱們要給canvas
設置寬和高,在這裏,我就是設置的400X400
,而後給場景加一個背景。就這樣:spa
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; })();
建立了canvas
元素,咱們要添加到DOM
網頁中去,因此用appendChild()
來添加。以下:
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; document.body.appendChild(c); })();
哦,有些瀏覽器可能不支持canvas
標籤,因此咱們不能忘了給一個優雅的提示:
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; c.textContent="當前瀏覽器不支持canvas標籤"; document.body.appendChild(c); })();
場景畫好了,接下來,咱們要在場景上畫蛇,因此canvas.getContext('2d')
這個方法是必不可少的。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); document.body.appendChild(c); })();
接下來分析蛇的構成,實際上這裏的場景,咱們能夠當作是400
個20*20
的塊組成,那麼蛇也就能夠當作一個塊一個塊的組成,用技術術語來講就是一個隊列,也就是一個數組,[20]
。在這裏初始化蛇爲2
個塊,也就是[20,20]
,那麼蛇初始化位置仍是稍微調整一下嘛,因此也就改爲[40,40]
,其實在這裏第一次出現的時候,是隱藏了一個食物的,默認就在蛇初始化位置的下一格,而後蛇會當即吃掉,而後就隨機出現下一個食物的位置了,所以默認食物的位置是40
。爲了一個方便細小的微差,就稍微調大一點,爲43
。好了,如今咱們要知道蛇運行的方向,蛇能夠上下左右活動,那麼,咱們定義爲s[1] - s[0]
,這是根據位置來計算的。我們先定義蛇再說:
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的 d = 1,//定義蛇活動方向,默認向右 f = 42;//默認食物的位置 document.body.appendChild(c); })();
接下來,開始繪製蛇,蛇活動的軌跡與食物。定義一個函數,利用canvas.fillStyle()
填充背景,在這裏蛇與食物還有蛇活動的軌跡都是一個小方塊矩形,這樣咱們就使用canvas.fillRect()
來繪製一個矩形,這個方法有四個參數,以下圖所示:
蛇活動的軌跡座標,也就是定義的蛇數組的座標,所以第一個參數就是s % 20 * 20
,第二個參數就是~~(s / 20 * 20)
。關於~~
這個操做符,若是不理解的話,能夠看個人文章淺談JavaScript位操做符。這裏感受有些抽象,實際上,須要靠本身的想象力來想象理解。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42;//默認食物的位置 //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } document.body.appendChild(c); })();
蛇每吃掉一個食物,也就是往數組中添加一個20*20
的小塊,固然爲了區分方向,這裏的小塊寬高應該與繪製的矩形寬高有關。所以,咱們還要定義一個變量來表明蛇吃掉食物後,隨機出現的下一個食物出現的位置。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42,//默認食物的位置 x; //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } document.body.appendChild(c); })();
接下來就是用戶按鍵盤的方向鍵,固然也能夠是wsad
字母鍵來控制蛇活動的方向。不過咱們須要知道鍵盤鍵的keyCode
,方向鍵的keyCode
分別是:向左:37,向上:38,,向右:39,向下:40
。鍵盤事件爲onkeydown
。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42,//默認食物的位置 x; //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } //按方向鍵控制蛇運動方向,這裏根據食物的位置來控制方向,防止用戶隨便更改方向,而後遊戲崩潰 document.onkeydown = function(e){ d = s[1] - s[0] === (x = [-1,-20,1,20][e || event].keyCode - 37 ] || d) ? d : x; } document.body.appendChild(c); })();
而後蛇吃掉一個食物就應該添加下一個食物,在這裏用unshift()
方法來添加數組。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42,//默認食物的位置 x; //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } //按方向鍵控制蛇運動方向,這裏根據食物的位置來控制方向,防止用戶隨便更改方向,而後遊戲崩潰 document.onkeydown = function(e){ //方向由蛇頭來肯定,初始化蛇只有2個小方塊組成,所以蛇的方向就是s[1] - s[0] d = s[1] - s[0] === (x = [-1,-20,1,20][e || event].keyCode - 37 ] || d) ? d : x; } !(function(){ s.unshift(x = s[0] + d); })();//這也是一種自調用函數寫法 document.body.appendChild(c); })();
接下來判斷蛇若是撞牆或者撞到了自身,則遊戲結束。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42,//默認食物的位置 x; //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } //按方向鍵控制蛇運動方向,這裏根據食物的位置來控制方向,防止用戶隨便更改方向,而後遊戲崩潰 document.onkeydown = function(e){ //方向由蛇頭來肯定,初始化蛇只有2個小方塊組成,所以蛇的方向就是s[1] - s[0] d = s[1] - s[0] === (x = [-1,-20,1,20][e || event].keyCode - 37 ] || d) ? d : x; } !(function(){ s.unshift(x = s[0] + d); //判斷蛇若是撞牆或者撞到了自身,則遊戲結束 if(s.indexOf(x,1) > 0 || x < 0 || x > 399 || d == 1 && x % 20 == 0 || d == -1 && x % 20 == 19)return alert('遊戲結束'); })();//這也是一種自調用函數寫法 document.body.appendChild(c); })();
而後開始畫食物,以及判斷食物是否被蛇吃掉,若是吃掉了,則隨機生成下一個食物。
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42,//默認食物的位置 x; //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } //按方向鍵控制蛇運動方向,這裏根據食物的位置來控制方向,防止用戶隨便更改方向,而後遊戲崩潰 document.onkeydown = function(e){ //方向由蛇頭來肯定,初始化蛇只有2個小方塊組成,所以蛇的方向就是s[1] - s[0] d = s[1] - s[0] === (x = [-1,-20,1,20][e || event].keyCode - 37 ] || d) ? d : x; } !(function(){ s.unshift(x = s[0] + d); //判斷蛇若是撞牆或者撞到了自身,則遊戲結束 if(s.indexOf(x,1) > 0 || x < 0 || x > 399 || d == 1 && x % 20 == 0 || d == -1 && x % 20 == 19)return alert('遊戲結束'); //而後開始畫蛇節點的顏色 w(x,'#e641d3'); //判斷蛇是否是吃到食物,若是吃到則從新隨機生成一個節點也就是新食物的座標,Math.random()方法表示取隨機數,由於方向有多是負的,因此用到了~~符號表示取絕對值到正數.~就是先取反再減一的意思. if(x == f){ while (s.indexOf(f = ~~(Math.random() * 399)) > 0); //從新畫食物顏色 w(f,'#35e3dc'); }else{ //蛇吃到食物,蛇身會變長,因此不會改變蛇的運動軌跡 w(s.pop(),'#535353'); } })();//這也是一種自調用函數寫法 document.body.appendChild(c); })();
最後,讓蛇按必定的時間運行,以下:
(function(){ //建立canvas標籤 var c = document.createElement('canvas'); c.width = 400; c.height = 400; c.style.background = '#535353'; var b = c.getContext('2d'); var s = [41,40],//這裏41也是有講究的,表明默認向右方向 d = 1,//定義蛇活動方向,默認向右,蛇運動方向爲s[1] - s[0] f = 42,//默認食物的位置 x; //這個函數既是繪製蛇方塊,也是繪製食物與蛇活動軌跡的定義 function w(s,c){ b.fillStyle = c; b.fillRect(s % 20 * 20,~~(s / 20 * 20),18,18); } //按方向鍵控制蛇運動方向,這裏根據食物的位置來控制方向,防止用戶隨便更改方向,而後遊戲崩潰 document.onkeydown = function(e){ //方向由蛇頭來肯定,初始化蛇只有2個小方塊組成,所以蛇的方向就是s[1] - s[0] d = s[1] - s[0] === (x = [-1,-20,1,20][e || event].keyCode - 37 ] || d) ? d : x; } !(function(){ s.unshift(x = s[0] + d); //判斷蛇若是撞牆或者撞到了自身,則遊戲結束 if(s.indexOf(x,1) > 0 || x < 0 || x > 399 || d == 1 && x % 20 == 0 || d == -1 && x % 20 == 19)return alert('遊戲結束'); //而後開始畫蛇節點的顏色 w(x,'#e641d3'); //判斷蛇是否是吃到食物,若是吃到則從新隨機生成一個節點也就是新食物的座標,Math.random()方法表示取隨機數,由於方向有多是負的,因此用到了~~符號表示取絕對值到正數.~就是先取反再減一的意思. if(x == f){ while (s.indexOf(f = ~~(Math.random() * 399)) > 0); //從新畫食物顏色 w(f,'#35e3dc'); }else{ //蛇吃到食物,蛇身會變長,因此不會改變蛇的運動軌跡 w(s.pop(),'#535353'); } //這是一種遞歸的寫法 setTimeout(arguments.callee,300); })();//這也是一種自調用函數寫法 document.body.appendChild(c); })();
到此爲止,就拆分完了,其實這裏的邏輯不算難,難的是計算蛇與蛇運動軌跡還有食物的座標。可以理解透,就看我的的數學知識了,哈哈。最後,將這麼多代碼整合成一行代碼,就能夠好好的裝逼了!
ps
:本文代碼借鑑國外某大神20多行js代碼實現貪吃蛇,在源代碼基礎上進行分析並加以修改封裝而成,不喜勿噴。
鄙人建立了一個QQ羣,供你們學習交流,但願和你們合做愉快,互相幫助,交流學習,如下爲羣二維碼: