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