网页版“别踩白块”实战笔记

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)事件对象.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值