<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style type="text/css"> * { margin: 0; padding: 0; } .box { 940px; height: 500px; border: 1px solid #000; margin: 50px auto; position: relative; /* cursor: none; */ } .block { position: absolute; top: 0; left: 0; 94px; height: 36px; background: url(img/block.png); } .ball { position: absolute; 27px; height: 27px; background: url(img/ball.png); } .racket { position: absolute; 179px; height: 37px; background: url(img/racket.png); top: 450px; left: 10px; } </style> </head> <body> <div class="box" id="box"> <div class="ball" id="ball"></div> <div class="racket" id="racket"></div> </div> </body> <script> // 获取dom对象 var box = document.getElementById('box'); var ball = document.getElementById('ball'); var racket = document.getElementById('racket'); // 面向对象的思维挡板,小球,地图,碰撞块,大盒子都可以是一个类 // 创建碰撞块类 function Block(left, top, color) { this.top = top; this.left = left; this.width = 94; this.height = 36; this.color = color; this.alive = true; this.init(); } // 块类有一个初始化方法 Block.prototype.init = function() { this.dom = document.createElement('div'); this.dom.className = 'block'; box.appendChild(this.dom); this.render(); } // 块类有一个渲染方法 Block.prototype.render = function() { this.dom.style.top = this.top + 'px'; this.dom.style.left = this.left + 'px'; this.dom.style.backgroundPosition = -this.color * this.width + 'px 0'; }; // 我们的block也要有碰撞检测,当被小球撞到时消失,并且反弹小球 Block.prototype.check = function() { // 上边界检测 if (b.top >= this.top - b.d && b.top <= this.top && b.left >= this.left - b.d && b.left <= this.left + this.width) { b.deltaY *= -1; this.hide(); return true; // 下边界检测 } else if (b.top <= this.top + this.height && b.top >= this.top && b.left >= this.left - b.d && b.left <= this.left + this.width) { b.deltaY *= -1; this.hide(); return true; // 左边界检测 } else if (b.left >= this.left - b.d && b.left <= this.left && b.top >= this.top && b.top <= this.top + this.height) { b.deltaX *= -1; this.hide(); return true; // 右边界检测 } else if (b.left <= this.left + this.width && b.left >= this.left && b.top >= this.top && b.top <= this.top + this.height) { b.deltaX *= -1; this.hide(); return true; } }; Block.prototype.hide = function() { this.alive = false; container.dom.removeChild(this.dom); }; // 创建地图类 function Map() { // 地图类需要有一个二维数组来表示box内的block数量 this.data = [ [0, 1, 2, 3, 0, 1, 2, 3, 0, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1], ]; this.allBlockArr = []; this.render(); } // Map也有一个render方法 Map.prototype.render = function() { // 遍历二维数组 for (var row = 0; row < this.data.length; row++) { for (var col = 0; col < this.data[row].length; col++) { this.allBlockArr.push(new Block(col * 94, row * 30, this.data[row][col])) } } }; // 检测所有block是否被小球碰撞 Map.prototype.checkAll = function() { for (var i = 0; i < this.allBlockArr.length; i++) { if (this.allBlockArr[i].alive) { var result = this.allBlockArr[i].check() } if (result) { break; } } } // 创建小球类 function Ball() { this.left = 480; this.top = 400; this.d = 27; // 小球运动速度,运动角度 this.speed = 5; this.angle = 50; // 小球的运动方向 // 计算机采用的是弧度制,并不是角度制 // 这里我们将圆球运动看作三角模型那么它斜向运动的speed就是斜线 // 我们可以根据角度计算出sin 也就是对边 / 斜边 的值 // 然后让其 * 斜边speed得到对边也就是Y轴的移动速度 this.deltaY = Math.sin(angleChangeToRadian(this.angle)) * this.speed; // 三角函数中余弦就是邻边比斜边 this.deltaX = Math.cos(angleChangeToRadian(this.angle)) * this.speed; this.dom = ball; this.fly(); } // 小球有一个运动方法 Ball.prototype.fly = function() { var self = this; var timer = setInterval(function() { self.left += self.deltaX; self.top += self.deltaY; self.dom.style.left = self.left + 'px'; self.dom.style.top = self.top + 'px'; // 每十秒让container检测是否被小球碰到 container.check(); map.checkAll(); oRacket.check(); }, 10) } // 创建一个大盒子的类 function Box() { this.dom = box; this.width = 940; this.height = 500; } // 大盒子需要一个碰撞检测,当检测到小球碰撞到盒子时反弹 Box.prototype.check = function() { // 左右边界检测 // 反弹的原理是当我们的小球以X轴5 / s,Y轴 8 / s的速度下降,那么它反弹后 // X轴的速度不变,Y轴向相反方向运动 if (b.left >= this.width - b.d || b.left <= 0) { b.deltaX *= -1; } if (b.top >= this.height - b.d || b.top <= 0) { b.deltaY *= -1; } } // 创建挡板类 function Racket() { this.width = 179; this.height = 37; this.top = 450; this.left = 10; this.dom = racket; this.move() } // 挡板移动 Racket.prototype.move = function() { var self = this; container.dom.onmousemove = function(event) { event = event || window.event; self.left = event.clientX - container.dom.offsetLeft - self.width / 2; self.dom.style.left = self.left + 'px'; } }; // 挡板碰撞检测 Racket.prototype.check = function() { // 上边界检测 if (b.top >= this.top - b.d && b.top <= this.top && b.left >= this.left - b.d && b.left <= this.left + this.width) { b.deltaY *= -1; // 下边界检测 } else if (b.top <= this.top + this.height && b.top >= this.top && b.left >= this.left - b.d && b.left <= this.left + this.width) { b.deltaY *= -1; // 左边界检测 } else if (b.left >= this.left - b.d && b.left <= this.left && b.top >= this.top && b.top <= this.top + this.height) { b.deltaX *= -1; // 右边界检测 } else if (b.left <= this.left + this.width && b.left >= this.left && b.top >= this.top && b.top <= this.top + this.height) { b.deltaX *= -1; } } var b = new Ball(); var map = new Map(); var container = new Box(); var oRacket = new Racket() // 定义角度转弧度的函数 function angleChangeToRadian(angle) { return angle * Math.PI / 180; } </script> </html>