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];
}
}
程序很简单的,就是有点头冷(手动滑稽)