原生js开发web简易版版消灭星星

昨天看视频之后,整理思路,自己完成了简易版消灭星星
思路:

模块1:初始化

  • 初始化总分数、当前分数、背景图、选择的星星分数
  • 初始化星星(生成二维数组,对二维数组的每一个对象设置样式(长、宽、背景图),生成二维数组个div元素节点插入到游戏面板中)

模块2:预判

  • 判断:
     鼠标移动到某一个方块,判断上下左右是否有连接着的小方块(采用递归方法),然后将其存储到数组choose[],移到其他方块时,choose置为空
  • 闪烁:
     将已选中的小方块设置样式(缩放)
  • 显示选择分数:
     设置初始分数和递增分数,根据选中的块数算出选中的分数

模块3:点击

  • 消失:
     点击已选中的小方块,将连着的所有小方块在二维数组的位置设置为空,清空choose数组
  • 移动:
     下移:设置一个指针,指向最下面的行。每当行+1,若遇到不为空的方块,则pointer++,若遇到该列某行为空,则将pointer的行数设为i
      左移:最底部的一行若有一列为空,将右边的所有方块的列-1
  • 判断:
     每次点击完成之后判断游戏是否结束

代码部分

html

html结构很简单

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./index.js"></script>
    <link rel="stylesheet" href="index.css">
</head>
<body>
    <div id="pop_star">
        <div id="target_score">目标分数:2000</div>
        <div id="now_score">当前分数:0</div>
        <div id="select_score">0块 0分</div>
    </div>
</body>
</html>
CSS

css布局也很简单,相信不用我来说

* {
     margin: 0px;
     padding: 0px;
 }

html, body {
    height: 100%;
    width: 100%;
}

#pop_star {
    width: 500px;
    height: 100%;
    background: url("./pic/background.png");
    margin-left: auto;
    margin-right: auto;
    position: relative;
    background-size: cover;
    font-size: 0px;
}

#target_score {
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    color: white;
    font-size: 20px;
    position: relative;
}

#now_score {
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    color: white;
    font-size: 20px;
    position: relative;
}

#select_score {
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    color: white;
    font-size: 20px;
    position: relative;
    opacity: 0;
}
JS
/*
 创建二维数组
 * 
 * 
 * */
var table ;
var suqareWidth = 50 ; //一个星星/方块边长
var boardWidth = 10 ; //横竖方块个数
var squareSet = [];//小方块的集合,二维数组
var choose = [];//有相邻的小方块,将其放到这个数组
var timer = null ;
var baseScore = 5 ;
var stepScore = 10 ;
var totalScore = 0 ;
var targetScore = 1500;
var flag = true ;
var tempSquare = null;//在处理鼠标动作过程中,动作被屏蔽,导致事件处理完成,有不连贯现象
function createSquare(value , row , col){
	//创建小方块节点
	var blocks = document.createElement('div');
	//设置样式
	blocks.style.width = suqareWidth + 'px';
	blocks.style.height = suqareWidth + 'px';
	blocks.style.display = 'inline-block';
	blocks.style.boxSizing = 'border-box';
	blocks.style.position = 'absolute';
	blocks.style.borderRadius = "12px";
	//小方块的行和列,小方块的num.jpg
	blocks.num = value ;
	blocks.row = row ;
	blocks.col = col ;
	return blocks;
}
function refresh(){
	for(var i = 0 ; i < squareSet.length ; i ++){
		for (var j = 0 ; j < squareSet[i].length ; j++) {
			//严谨判断
			if (squareSet[i][j] == null) {
				continue;
			}
			//将二维数组里面的小方块对应面板的行和列显示
			squareSet[i][j].row = i;
            squareSet[i][j].col = j;
            //列*方块长度
            squareSet[i][j].style.transition = "left 0.3s, bottom 0.3s";
			squareSet[i][j].style.left = squareSet[i][j].col * suqareWidth + 'px';
			squareSet[i][j].style.bottom = squareSet[i][j].row * suqareWidth + 'px';
			//背景图
			squareSet[i][j].style.backgroundImage = "url('img/" + squareSet[i][j].num + ".png')";
			squareSet[i][j].style.backgroundSize = 'cover';
			squareSet[i][j].style.transform = 'scale(0.95)';//是图片缩小至原来的0.95倍
		}
	}
}
function checkLinked(square , arr){
	//严谨判断
	if(square == null){
		return;
	}
	//添加小方块到arr
	arr.push(square);
	/*
	 	判断位于该小方块左边的小方格是否能被收录进选择数组
	 	1.小方格不能是最左边的
	 	2.小方格左边必须有小方块
	 	3.小方块左边的要和该小方块颜色相同
	 	4.该小方块左边没有被收录到数组中去
	 	5.递归
	 * 
	 * */
	//向左
	if(square.col > 0 && squareSet[square.row][square.col - 1]
		&& squareSet[square.row][square.col - 1].num == square.num 
		&& arr.indexOf(squareSet[square.row][square.col - 1]) == -1){
			checkLinked(squareSet[square.row][square.col - 1] , arr);
	}
	//向右
	if(square.col < boardWidth - 1 && squareSet[square.row][square.col + 1]
		&& squareSet[square.row][square.col + 1].num == square.num 
		&& arr.indexOf(squareSet[square.row][square.col + 1]) == -1){
			checkLinked(squareSet[square.row][square.col + 1] , arr);
	}
	//向上
	if(square.row < boardWidth - 1 && squareSet[square.row + 1][square.col ]
		&& squareSet[square.row + 1][square.col].num == square.num 
		&& arr.indexOf(squareSet[square.row + 1][square.col ]) == -1){
			checkLinked(squareSet[square.row + 1][square.col] , arr);
	}
	//向上
	if(square.row > 0 && squareSet[square.row - 1][square.col]
		&& squareSet[square.row - 1][square.col].num == square.num 
		&& arr.indexOf(squareSet[square.row - 1][square.col]) == -1){
			checkLinked(squareSet[square.row - 1][square.col] , arr);
	}
}
//让选中的小方块闪烁
function flicker(arr){
	var num = 0 ;
	//设置计时器,让其一之闪烁
	timer = setInterval(function(){
		for (var i = 0 ; i < arr.length ; i++) {
			//设置缩放样式
			arr[i].style.border = "3px solid #BFEFFF";
			arr[i].style.transform = "scale("+(0.9 + 0.05 *Math.pow(-1 , num))+")";
		}
		//小方块闪烁完成之后num++,使其再次缩放
		num++;
	},300);
}
function back(){
	//若计时器还存在,清楚计数器
	if(timer != null){
	 	clearInterval(timer);
	}
	//返回原样式
	for(var i = 0 ; i < squareSet.length ; i++){
		for(var j = 0 ; j < squareSet[i].length ; j++){
			//严谨判断
			if (squareSet[i][j] == null) {
				continue;
			}
			squareSet[i][j].style.border = "0px solid #BFEFFF";
			squareSet[i][j].style.transform = "scale(0.95)";
		}
	}
	
}
//选中分数
function selectScore(){
	var socre = 0 ;
	//遍历choose
	for(var i = 0 ; i < choose.length ; i++){
		socre += baseScore + stepScore * i ;
	}
	//严谨判断
	if (socre <= 0) {
		return ;
	}
	//设置select_score的样式
	var select_score = document.getElementById('select_score');
	select_score.innerHTML = choose.length + "块" + socre + "分";
	select_score.style.transition = null ;
	//设置透明度,让其突然显示
	select_score.style.opacity = 1 ;
	//让其逐渐消失
	setTimeout(function(){
		select_score.style.transition = 'opacity 1s';
		select_score.style.opacity = 0;
	},1000);
	
}
//鼠标移动到该小方块时,闪烁
function mouseOver(obj){
	//当鼠标在移动到该方块突然移动到其他位置时
	if(!flag){
		tempSquare = obj;
		return ;
	}
	//当鼠标移开选中的方块之后,让其回到原来的样式
	back();
	//选择相邻相同的小方格
	//传一个数组
	choose = [];
	checkLinked(obj , choose);//obj是当前鼠标移到的小方块,choose是存储响铃小方块的数组
	if (choose.length <= 1) {
		choose = [] ;
		return;
	}
	//将选中的设置样式,让其闪烁
	flicker(choose);
	//显示所选中的小方块的分数
	selectScore();
}
function move(){
	/*
	 1.设置一个指针,开始的时候指针指向最下面一行
	 2.此时指针和j是否一样,一样都++。
	 3.若改行该列该列有小方块,均++,反之j++,pointer不变,循环判断该条件
	 3.当j移动到该列某行的小方块,该小方块存在,则将j指向的小方块的位置设置为指针指向的那一个小方块的位置
	 * */
    //向下移动
    for (var i = 0 ; i < boardWidth ; i ++) {
        var pointer = 0;//pointer指向小方块,当遇到null的时候停止,等待上面的小方块落到这里来
        for (var j = 0 ; j < boardWidth ; j ++) {
            if (squareSet[j][i] != null) {
                if (j != pointer) {
                    squareSet[pointer][i] = squareSet[j][i];
                    squareSet[j][i].row = pointer;
                    squareSet[j][i] = null;
                }
                pointer ++;
            }
        }
    }
    //横向移动
    for (var i = 0 ; i < squareSet[0].length ; ) {
        if (squareSet[0][i] == null) {
            for (var j  = 0 ; j < boardWidth ; j ++) {
                squareSet[j].splice(i, 1);
            }
            continue;
        }
        i ++;
    }
    refresh();
}
function isFinish(){
	for (var i = 0 ; i < squareSet.length ; i++) {
		for (var j = 0 ; j < squareSet[i].length ; j++) {
			//判断周围是否还有可消除的方块
			var temp = [];
			checkLinked(squareSet[i][j] , temp);
			if(temp.length > 1){
				return false ;
			}
		}
	}
	return true;
}
function init(){
	//获取面板
	table = document.getElementById('pop_star');
	//创建二维数组
	for(var i = 0 ; i < boardWidth ; i++){
		squareSet[i] = new Array();
		for(var j = 0 ; j < boardWidth; j++){
			//创建小方块
			var square = createSquare(Math.floor(Math.random() * 5), i, j);
			//鼠标移动到该方块
			square.onmouseover = function(){
				mouseOver(this);
			}
			//点击小方块时的操作
			square.onclick = function(){
				//小方块在被点击的时候其他操作不能影响他的执行
				if(choose.length == 0 || !flag ){
					return ;
				}
				flag = false;
				tempSquare = null ;
				/*
				 1.增加当前分数
				 2.小方块消失
				 3.向下或想做移动
				 4.判断游戏是否结束
				 */ 
				var socre = 0 ;
				//遍历choose
				for(var i = 0 ; i < choose.length ; i++){
					socre += baseScore + stepScore * i ;
				}
				totalScore += socre ;//总分数
				//改变样式
				document.getElementById('now_score').innerHTML = '当前分数:' + totalScore;
				//小方块消失
				/*
				 1.从二维数组里面移除选择了的小方块
				 2.在面板上移除div,不然div会一直占着格子
				 * */
				for(var i = 0 ; i < choose.length ; i++){
					//立即函数,立即出发该函数,否则的话,不会执行
					(function(i){
						setTimeout(function(){
							//将二维数组的某一值设置为空,后面的会向前移
							squareSet[choose[i].row][choose[i].col] = null ;
							//移除div
							table.removeChild(choose[i]);
						},i * 100);
					})(i);
				}
				//移动
				setTimeout(function(){
					move();
					setTimeout(function(){
						var finished = isFinish();
						if(finished){
							if (totalScore >= targetScore) {
								alert('闯关成功');
							} else{
								alert('闯关失败');
							}
						}else{//还可以继续
							choose = [] ;
							flag = true;
							mouseOver(tempSquare);
						}
					} , 300 + choose.length * 150);
				},choose.length * 100);
			}
			//将小方块放进二维数组
			squareSet[i][j] = square;
			//将创建好的小方块插入到面板中
			table.appendChild(square);
		}
	}
	//显示小星星,刷新整个面板
	
	refresh();
}
//页面加载完成之后,初始化所有操作
window.onload = function(){
	init();
}

其实这里还有优化的就是闯关部分,大致的思路就是,游戏每过一关增加目标分数,当游戏结束时,闯关失败,目标分数恢复初始值。
大家有什么不懂,可以在评论区评论。
jq进阶版的源码详情见我github,网址 https://github.com/ainuo5213/PopStar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值