天天看點

網頁版“别踩白塊”實戰筆記

網頁版“别踩白塊”項目 筆記

      • js重點代碼詳解
      • 所有完整代碼如下:
        • index.html
        • index.css
        • index.js
        • 事件對象解釋
        • 參考連結

js重點代碼詳解

//全局變量
var clock = null;
var speed = 6;
var flag = false; //遊戲的狀态:false代表未開始,true代表已經開始
           
  • 1.create_row()函數,首先要通過js來控制

    <div class="row"

    >及它4個子節點

    <div class="cell">

    的生成和删除,友善後面删除掉使用者已經點選過的行,以及從上頂部生成新行。
//建立一個<div class="row">并且包含四個子節點<div class="cell">
function create_row(){
	var content = $('content');//擷取頁面中content這個元素
	var row = create_div('row');//建立div,className=row
	var arr = create_cell();//定義div cell的類名,其中一個為cell black->黑塊
	
	for(var i=0;i < 4;i++){//添加row的4個子節點div
		row.appendChild(create_div(arr[i])); 
	}
	
	if(content.firstChild == null){
		content.appendChild(row); //添加row為content的子節點
	}else {
		content.insertBefore(row,content.firstChild);
	}
}
           
  • 2.初始化函數init():初始建立頁面結構,建立四行四列方塊;

    給main綁定點選事件來擷取使用者的點選,點選後判斷使用者點選的是白塊還是黑塊;

    讓rows自動下落;

function init(){
	flag = true; //标記遊戲已經開始
	//1.建立四行
	for(var i=0;i < 4;i++){
		create_row();
	}
	
	//給整個main内容添加onclick事件,一旦裡面發生點選事件則會觸發判斷judge()
	$('main').onclick = function(ev){
		var ev = ev || event;//擷取事件對象.也就是點選事件
		judge(ev);//标記 點中了哪一行的白塊或者黑塊
	};
	
	//定時器  每30ms調用一次move(),讓rows下落
	clock = window.setInterval('move()',30);
}
           
  • judge(ev):判斷使用者點選的是白塊還是黑塊,然後對應标記那一行pass1=1 or pass=1;此函數标記

    最新的點選狀态

    ,是為了讓每次下落時,都能判斷一下底部一行的黑塊是否被點選。
//判斷是否點選白塊、黑塊,點選了則把該行标記pass(黑塊),pass1(白塊) 屬性==1
function judge(ev){
	//ev.target擷取的是使用者點選的那一個元素
	//檢查點選的這個元素類名是否是黑塊
	if(
	   ev.target.className.indexOf('black') == -1 &&
	   ev.target.className.indexOf('cell') !== -1
	) {
	   	 //這裡表示沒點中黑塊,卻點中了白塊
	   	 //elementNode.parentNode ==> 擷取指定節點的父節點即<div class="row">
	   	 ev.target.parentNode.pass1 = 1; //定義屬性pass1,表示此行row的白塊已被點選
	}
	   
	if(ev.target.className.indexOf('black') !== -1){
		//點選到的是黑塊
		ev.target.className = 'cell';//讓它變成白色
		ev.target.parentNode.pass = 1;//定義屬性pass,表明此行row的黑塊已被點選
		score();//清算分數
	}
}
           
  • 3.IsGameOver():規定了遊戲結束條件,結合judge()函數标記的pass,pass1來判斷是否下落到底部的黑塊沒被點選,是否點選了白塊。

    此處應結合move()函數一起消化

//判斷遊戲是否結束  ==> 每下落一次,都會判斷一次遊戲是否結束
function IsGameOver(){
	var rows = $('content').childNodes;//擷取所有的行
	//下落到最後一行,失敗
	if(rows.length == 5 && rows[rows.length - 1].pass !== 1){
	  //最後一行沒點選黑塊,讓遊戲結束
		//整個遊戲除了遊戲初始時,是4行;
		//除了使用者點選了黑塊,但被點的黑塊完全下落到不見時的瞬間top==0,添加一行後,才是6行,然後又會立馬删掉最後一行,又是5行了;
		//其他時候都是5行:這時候才要判斷底行黑塊是否被點選,沒點則失敗
		fail();
	}
	
	//點選白塊,失敗
	for(let i=0;i < rows.length;i++) {
		if(rows[i].pass1 == 1)  //從上往下,隻要有白塊被點選過,就失敗
		    fail();
	}
}
           
  • 4.move()函數:首先讓其下落speed像素,再判斷此時遊戲是否結束,再判斷是否top==0(隐藏的全部下落到視線),是的話,就建立新行;

    并且判斷底部有沒有已經被使用者點選了的隐藏住的黑塊行,有則删除,沒有則不删除。

//讓黑塊動起來
function move(){
	var content = $('content');
	var top = parseInt(window.getComputedStyle(content,null)['top']);
	
	//speed是全局變量
	if(top + speed > 0) {
		//因為一開始是top=-408,隐藏了格子,現在要一點點下降
		//然後每次消除一行之後,建立的新行也是被隐藏在頂部,top = -102px
		top = 0;
	}else{ //就說明,隐藏在頂部的還沒下落完,則繼續下落
		top += speed;
	}
	
	content.style.top = top + 'px'; //不斷移動top值,使它動起來
	
	IsGameOver(); //判斷遊戲是否結束

	//top==0 也就是之前被隐藏在頂部的rows全部降落到使用者視線中了,
	//如果不繼續建立,就會導緻沒有rows可以下落了
	if(top == 0){
		//也是遊戲完全開始後,每次move,都判斷top==0?
		//==0就代表隐藏在頂部的一行已經完全下落到使用者視線中,然後建立新的一行
		create_row();//建立新的一行在頂部
		content.style.top = '-102px';//先把它這一行隐藏,再慢慢從上掉落
		if(content.childNodes.length == 6){ //隻有使用者成功點選黑塊後,并且等待該行掉落底部不見,才能變成6行
			//若上述代碼添加一行後,有6行了,則删除最後一行(這是删除的已被使用者點選過的黑塊行)
		   del_row();//删除末尾一行
		}
	}
}
           

所有完整代碼如下:

index.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>别踩白塊</title>
		<link rel="stylesheet" href="css/index.css" />
	</head>
	<body>
		<h2>score</h2>
		<h2 id="score">0</h2> <!--記錄總分的,初始為0-->
		<div id="main"> <!--主體塊:包括白塊黑塊内容,友善整個content定位-->
			<!--4 x 4的格子 一行四個元素,一共四行  -->
	        <div id="content"></div>
		</div>
		
		<div class="btn">
	        <button class="start" onclick="start()">
	        	開始遊戲
	        </button>		
	    </div>
	</body>
	<script type="text/javascript" src="js/index.js"></script>
</html>

           

index.css

#main{
	width: 408px; /*400是格子,8是格子之間的border*/
	height: 408px; 
	background: white;
	border: 2px solid gray;
	margin: 0 auto;
	overflow: hidden;
}

h2{
	text-align: center;
}

#content{
	width: 100%; 
	height: 400px;
	position: relative;
	top: -408px; /*使用者點選開始前隐藏所有格子*/
	border-collapse: collapse;/*表格設定合并邊框模型*/
}

/*行*/
.row{
	width: 100%;height: 100px;
}
/*一個塊*/
.cell{
	width: 100px;height: 100px;float: left;
	border: solid 1px rgb(54, 74, 129);
}
.black{
	background: #000;
}
.btn{
	width: 100%;
	text-align: center;
}

.start{
	margin: 20px auto;
	width: 150px;
	height: 50px;
	border-radius: 10px;
	background: yellowgreen;
	line-height: 50px;
	color: #fff;
}

           

index.js

/*
 * 使用者每點選一個黑塊消失其實是删除了一行<div class="row"></div>
 * 然後從上面添加一個新的<div class="row"></div>
 * 
**/
//全局變量
var clock = null;
var speed = 6;
var flag = false; //遊戲的狀态:false代表未開始,true代表已經開始

//根據id來擷取元素
function $(id){
	return document.getElementById(id);
}

//建立div,className是其類名
function create_div(className){
	var div = document.createElement('div');
	div.className = className;
	return div;
}

//建立一個類名的數組,其中一個為cell black,其餘為cell
function create_cell(){
	var temp = ['cell','cell','cell','cell'];
	var i = Math.floor(Math.random()*4);//随機産生黑塊的位置
	temp[i] = 'cell black';
	return temp;
}


//建立一個<div class="row">并且包含四個子節點<div class="cell">
function create_row(){
	var content = $('content');//擷取頁面中content這個元素
	var row = create_div('row');//建立div className=row
	var arr = create_cell();//定義div cell的類名,其中一個為cell black
	
	//content.appendChild(row); //添加row為con的子節點
	
	for(var i=0;i < 4;i++){//添加row的4個子節點
		row.appendChild(create_div(arr[i])); 
	}
	
	if(content.firstChild == null){
		content.appendChild(row);
	}else {
		content.insertBefore(row,content.firstChild);
	}
}

//删除div#content的子節點中最後那個<div class="row">
function del_row(){
	var content = $('content');
	
	content.removeChild(content.lastChild);
}

//點選開始遊戲按鈕,開始遊戲
function start(){
	if(flag == false) {
		init();//進入遊戲初始化
	}else {
		alert('遊戲已經開始,無須再次點選!');
	}
}

/*
 * 遊戲初始化函數  init
 * */
function init(){
	flag = true; //标記遊戲已經開始
	//1.建立四行
	for(var i=0;i < 4;i++){
		create_row();
	}
	
	//給整個main内容添加onclick事件,一旦裡面發生點選事件則會觸發判斷judge()
	$('main').onclick = function(ev){
		var ev = ev || event;//擷取事件對象.也就是點選事件
		judge(ev);//标記 點中了哪一行的白塊或者黑塊
	};
	
	//定時器  每30ms調用一次move(),讓row下落
	clock = window.setInterval('move()',30);
}

//判斷是否點選白塊、黑塊,點選了則把該行标記pass屬性==1
function judge(ev){
	//ev.target擷取的是使用者點選的那一塊元素
	//對比點選的這個元素類名是否是黑塊
	if(
	   ev.target.className.indexOf('black') == -1 &&
	   ev.target.className.indexOf('cell') !== -1
	) {
	   	 //這裡表示沒點中黑塊,卻點中了白塊
	   	 //elementNode.parentNode ==> 擷取指定節點的父節點即<div class="row">
	   	 ev.target.parentNode.pass1 = 1; //定義屬性pass1,表示此行row的白塊已被點選
	}
	   
	if(ev.target.className.indexOf('black') !== -1){
		//點選到的是黑塊
		ev.target.className = 'cell';//讓它變成白色
		ev.target.parentNode.pass = 1;//定義屬性pass,表明此行row的黑塊已被點選
		score();//清算分數
	}
}

//判斷遊戲是否結束  ==> 每下落一次,都會判斷一次遊戲是否結束
function IsGameOver(){
	var rows = $('content').childNodes;//擷取所有的行
	//下落到最後一行,失敗
	if(rows.length == 5 && rows[rows.length - 1].pass !== 1){
		//rows.length==5 && 最後一行的pass !==1
		//最後一行沒點選黑塊,讓遊戲結束
		fail();
	}
	
	//點選白塊,失敗
	for(let i=0;i < rows.length;i++) {
		if(rows[i].pass1 == 1)  //從上往下,隻要有白塊被點選過,就失敗
		    fail();
	}
}

//遊戲結束
function fail(){
	clearInterval(clock);//關閉定時器
	flag = false;
	speed = 6;
	confirm('你的最終得分為' + parseInt($('score').innerHTML));
	var content = $('content');
	content.innerHTML = ''; //清除所有的白塊黑塊
	$('score').innerHTML = 0;//分數歸零
	content.style.top = '-408px'; //又重新隐藏在頂部
}


//讓黑塊動起來
function move(){
	var content = $('content');
	var top = parseInt(window.getComputedStyle(content,null)['top']);
	
	//speed是全局變量
	if(top + speed > 0) {
		//因為一開始是top=-408,隐藏了格子,現在要一點點下降
		//然後每次消除一行之後,建立的新行也是被隐藏在頂部,top = -102px
		top = 0;
	}else{ //就說明,隐藏在頂部的還沒下落完,則繼續下落
		top += speed;
	}
	
	content.style.top = top + 'px'; //不斷移動top值,使它動起來
	
	IsGameOver(); //判斷遊戲是否結束

	//top==0 也就是之前被隐藏在頂部的rows全部降落到使用者視線中了,
	//如果不繼續建立,就會導緻沒有rows可以下落了
	if(top == 0){
		//也是遊戲完全開始後,每次move,都判斷top==0?
		//==0就代表隐藏在頂部的一行已經完全下落到使用者視線中,然後建立新的一行
		create_row();//建立新的一行在頂部
		content.style.top = '-102px';//先把它這一行隐藏,再慢慢從上掉落
		if(content.childNodes.length == 6){ //隻有使用者成功點選黑塊後,并且等待該行掉落底部不見,才能變成6行
			//若上述代碼添加一行後,有6行了,則删除最後一行(這是删除的已被使用者點選過的黑塊行)
		   del_row();//删除末尾一行
		}
	}
}

//加速函數
function speed_up(){
	speed += 2;
	if(speed == 20) {
		alert("你超神了");
	}
}


function score(){
	var newscore = parseInt($('score').innerHTML) + 1;//分數+1
	$('score').innerHTML = newscore;//修改分數
	if(newscore % 10 == 0) {
		//當分數是10的倍數時,使用加速函數,越來越快
		speed_up();
	}
}


           

事件對象解釋

事件對象

• 什麼是事件對象?

• 就是當你觸發了一個事件以後,對該事件的一些描述資訊

• 例如:

  • 你觸發一個點選事件的時候,你點在哪個位置了,坐标是多少
  • 你觸發一個鍵盤事件的時候,你按的是哪個按鈕

• 每一個事件都會有一個對應的對象來描述這些資訊,我們就把這個對象叫做 事件對象

• 我們就得用一種方式來擷取 事件對象,在每一個事件處理函數的行參位置,預設第一個就是 事件對象(ev)

function init(){
	flag = true; //标記遊戲已經開始
	//1.建立四行
	for(var i=0;i < 4;i++){
		create_row();
	}
	
	//添加onclick事件
	$('main').onclick = function(ev){
		var ev = ev || event;//擷取事件對象
		judge(ev);
	};
	
	//定時器  每30ms調用一次move()
	clock = window.setInterval('move()',30);
}
           

3.關于event對象

  • 在觸發的事件的函數裡面我們會接收到一個event對象,通過該對象我們需要的一些參數,比如說我們需要知道此事件作用到誰身上了,就可以通過event的屬性

    target

    來擷取到(IE暫且不談),或者想阻止浏覽器的預設行為可以通過方法

    preventDefault()

    來進行阻止.以下是event對象的一些屬性和方法
網頁版“别踩白塊”實戰筆記
網頁版“别踩白塊”實戰筆記
網頁版“别踩白塊”實戰筆記

參考連結

1.【js】event(事件對象)詳解.

2. js中(event)事件對象.