JavaScript 之DOM案例(打方块)

本文详细介绍了一个使用JavaScript实现的打方块游戏案例,包括页面布局、样式设置及关键的碰撞检测算法。游戏通过DOM操作控制小球与方块的交互,实现了开始、暂停、计分等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript 之DOM案例——打方块


废话不多说直接上代码

结构部分(实际上页面结构对后面的行为设计师有很大影响的,布局没布局好会很坑爹。。。。。)

<body>
	<div id="btn">  //按钮区
		<span id="start">Start</span>	//开始按钮
		<span>分数:<i id="grade">0</i></span>	//分数区
	</div>
	<div id="box">		//游戏区
		<div id="item"></div>		//方块存放区
		<div id="ball"></div>		//小球
		<div id="move"></div>	//接球的方块
	</div>
</body>

页面布局很重要。。。。。很重要

样式部分

	   *{
			margin: 0;
			padding: 0;
		}
		html,body{
			height: 100%;
			width: 100%;
			overflow: hidden;
			background: linear-gradient(90deg,pink,skyblue);
		}
		#box{
			width: 1200px;
			height: 800px;
			margin: 20px auto;
			position: relative;
			border: 5px solid #004085;
		}
		#move{
			width: 150px;
			height: 15px;
			background: #000000;
			position: absolute;
			bottom: 0;
			left: 0;
		}
		#ball{
			width: 30px;
			height: 30px;
			border-radius: 50%;
			background: red;
			position: absolute;
			bottom: 16px;
			box-sizing: border-box;
			border: 5px solid #008000;
		}
		#btn{
			width: 300px;
			margin: 15px auto;
			display: flex;
		}
		#btn>span{
			width: 150px;
			padding: 5px;
			text-align: center;
			font-size: 20px;
			color: red;
			border: 2px solid #101010;
			cursor: pointer;
			-webkit-user-select: none;
			margin-left: 10px;
		}
		#start{
			background: ;
		}
		#item{
			width: 100%;
			position: relative;
		}
		#item>div{
			position: absolute;
			box-sizing: border-box;
			border: 1px solid wheat;
		}
	</style>

样式部分要考虑盒子模型,因为这个案例是通过offset属性的,边框和距离就会变得很敏感

接下来到了正主Js代码

	function Brick(){
		this.Box = document.querySelector('#box');
		this.Item = document.querySelector('#item');
		this.MoveBlock = document.querySelector('#move');
		this.StartBtn = document.querySelector('#start');
		this.Grade = document.querySelector('#grade');
		this.Ball = document.querySelector('#ball');
		this.height = parseInt(this.Box.offsetHeight*0.5/20);
		this.width = parseInt(this.Box.offsetWidth/20);
		this.maxHight = this.Box.offsetHeight-this.Ball.offsetHeight;
		this.maxWidth = this.Box.offsetWidth-this.Ball.offsetWidth;
		this.Grade.innerText=0;
		this.back=false;
		this.speedT=-10;
		this.speedL=10;
		this.T;
		this.BlockPos = [];
		this.init();
	}
	
	Brick.prototype.init=function(){//初始化函数,实际上就是意思意思(^$^)
		this.releaseBall();
	}
	
	Brick.prototype.releaseBall=function(){//释放小球
		var that = this;
		this.StartBtn.onclick=function(){
			if(this.innerText=="Start"){//开始游戏
				this.innerText="Suspend";
				that.Item.innerHTML=null;//清空	
				that.Grade.innerText=0;
				that.createBlock();
				that.keyCtrl();
				that.Detection();
			}else{//停止游戏
				this.innerText="Start";
				clearInterval(that.T);//终止小球运动
			}
		}
	}
	
	Brick.prototype.Detection=function(){//检测碰撞
		var over=false;
		this.T= setInterval(()=>{
			for(var i=0;i<this.Item.children.length;i++){
				this.testP(this.Ball,this.Item.children[i],function(){
					this.Grade.innerText=parseInt(this.Grade.innerText)+10;
					this.Item.removeChild(this.Item.children[arguments[0]]);
					this.speedT = -this.speedT;
					this.back=true;
				}.bind(this,i));//其实这里用bind我个人赶脚不是很好
				if(this.back){//检测到碰撞了,就结束整个循环,节省资源消耗
					this.back=false;
					break;
				}
			}
			//下面是小球的运动轨迹,只要不是接触到底部边界就随便跑
			if(this.Ball.offsetTop<0){
				this.Ball.style.top = "0";
				this.speedT = -this.speedT;
			}else if(this.maxHight-this.Ball.offsetTop<this.speedT){
				over=true;
			}else{
				this.Ball.style.top = this.Ball.offsetTop + this.speedT+"px";
			}
			
			if(this.Ball.offsetLeft<0){
				this.Ball.style.left = "0";
				this.speedL = -this.speedL;
			}else if(Math.abs(this.speedT) >= 1){
				this.Ball.style.left = this.Ball.offsetLeft + this.speedL/2+"px";
			}
			
			if(this.maxWidth - this.Ball.offsetLeft<this.speedL){
				this.Ball.style.left =this.maxWidth+"px";
				this.speedL = -this.speedL;
			}else if(Math.abs(this.speedT) >= 1){
				this.Ball.style.left = this.Ball.offsetLeft + this.speedL/2+"px";
			}
			
			if(over){//检测是后碰到了游戏区的最底部
				alert("you die!");
				this.Grade.innerText=0;
				this.StartBtn.innerText="Start";
				this.Ball.style.bottom="16px";
				this.Ball.style.top=null;
				this.Ball.style.left=0;
				this.MoveBlock.style.left=0;
				clearInterval(this.T);//停止小球运动
			}
			this.testP(this.Ball,this.MoveBlock,()=>{//碰到底部的方块后执行的回调
				this.speedT = -this.speedT;//小球原路反向返回
			});
		},30);
	}
	
	Brick.prototype.testP=function(Ele1,Ele2,callback){//这里才是真正的碰撞检测的封装
		var t1=Ele1.offsetLeft;
		var t2=Ele1.offsetTop;
		var b1=t1+Ele1.offsetWidth;
		var b2=t2+Ele1.offsetHeight;
		var tt1=Ele2.offsetLeft;
		var tt2=Ele2.offsetTop;
		var bb1=Ele2.offsetLeft+parseInt(getStyle(Ele2,"width"));
		var bb2=Ele2.offsetTop+parseInt(getStyle(Ele2,"height"));
		if(tt1>b1 || tt2>b2 || bb1<t1 || bb2<t2){
			
		}else{
			callback();//确认发生碰撞以后的回调
		}
	}
	
	Brick.prototype.createBlock=function(){//初始化生成你们要打的方块(我感觉方块老可怜了,生出来就是被你们打的。)
		this.BlockPos=[];
		for(var j=0;j<15;j++){
			for(var i=0;i<20;i++){
				var NewBlock = document.createElement('div');
				NewBlock.style.height = this.height+"px";
				NewBlock.style.width = this.width+"px";
				NewBlock.style.left = this.width*i+"px";
				NewBlock.style.top = this.height*j+"px";
				NewBlock.style.background = randomColor();
				this.Item.appendChild(NewBlock);
			}
		}
	}
	
	Brick.prototype.keyCtrl=function(){//键盘事件,左右移动
		var that = this;
		document.onkeydown=function(eve){
			var e = eve || window.event;
			var MaxNowP = that.Box.offsetWidth-that.MoveBlock.offsetWidth-(that.Box.clientLeft*2);
			var NowP = that.MoveBlock.offsetLeft <= 0 ? 50 : that.MoveBlock.offsetLeft;//移动距离+-50px
			NowP = that.MoveBlock.offsetLeft >= MaxNowP ? MaxNowP-50 : NowP;
			switch(e.keyCode){
				case 37: that.MoveBlock.style.left=NowP-50+"px";break;
				case 39: that.MoveBlock.style.left=NowP+50+"px";break;
			}
		}
	}
	
	function randomColor(){//随机的RGB值
		return "rgb("+random(0,255)+","+random(0,255)+","+random(0,255)+")";
	}
	
	function random(min,max){
		return Math.round(Math.random()*(max-min)+min);
	}
	
	function getStyle(ele,attr){//获取元素样式的兼容
	    if(ele.currentStyle){
	        return ele.currentStyle[attr];
	    }else{
	        return getComputedStyle(ele,false)[attr];
	    }
	}

程序很简单的,就是有点头冷(手动滑稽)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值