1. 作品展示
2. 代码(全)
链接:https://pan.baidu.com/s/1Mxdz8rR18uM_7yuY-eTwbQ
提取码:6666
以下是项目目录及部分代码。
① 项目目录
② HTML
<!-- page\PinballKing.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹球王</title>
<link rel="stylesheet" href="../css/index.css">
</head>
<body>
<div class="game-zone">
<div class="function-area">
<div class="button continue-button keep">继续</div>
<div class="button start-button play">开始游戏</div>
<div class="button puse-button suspend">暂停</div>
</div>
<div class="blocks">
<div class="ball"></div>
<div class="skate"></div>
<div class="message">
<div class="info-txt">第 1 关</div>
<div class="info-time">时间: 00:00</div>
<div class="info-number">砖块: 0</div>
</div>
</div>
</body>
<script src="../js/index.js">
</script>
</html>
③ CSS
/* css\index.css */
/* 游戏区 */
.game-zone {
background-color: pink;
height: 600px;
width: 900px;
margin: 50px 300px;
color: white;
font-size: 25px;
font: bold;
font-family: cursive;
user-select: none;
}
/* 功能区 */
.function-area {
height: 36px;
background-color: #ccc;
display: flex;
}
/* 开始游戏按钮 */
.active {
background-color: black;
}
.start-button {
flex: 1;
/* justify-content 用于设置或检索弹性盒子元素在主轴(横轴)方向上的对齐方式。 */
justify-content: center;
/* align-items 属性定义flex子项在flex容器的当前行的侧轴(纵轴)方向上的对齐方式。 */
align-items: center;
color: #fff;
display: flex;
}
.start-button:hover {
background-color: rgb(115, 115, 168);
}
/* 继续 */
.continue-button {
flex: 1;
justify-content: center;
align-items: center;
color: #fff;
display: flex;
}
.continue-button:hover {
background-color: rgb(187, 187, 247);
}
/* 暂停 */
.puse-button {
flex: 1;
justify-content: center;
align-items: center;
color: #fff;
display: flex;
}
.puse-button:hover {
background-color: rgb(160, 160, 212);
}
/* 堆块区 */
.blocks {
height: calc(600px - 36px);
background-color: rgb(220, 247, 255);
position: relative;
overflow: hidden;
}
.row {
height: 20px;
margin-top: 15px;
/* margin-right: 5px;
margin-left: 5px; */
display: flex;
justify-content: space-between;
}
.brick {
width: 107px;
height: 30px;
}
.brick:nth-child(1) {
background-color: rgb(255, 106, 106);
border-radius: 10px;
}
.brick:nth-child(2) {
background-color: rgb(255, 161, 126);
border-radius: 10px;
}
.brick:nth-child(3) {
background-color: rgb(253, 255, 147);
border-radius: 10px;
}
.brick:nth-child(4) {
background-color: rgb(173, 248, 143);
border-radius: 10px;
}
.brick:nth-child(5) {
background-color: rgb(146, 190, 255);
border-radius: 10px;
}
.brick:nth-child(6) {
background-color: rgb(155, 214, 253);
border-radius: 10px;
}
.brick:nth-child(7) {
background-color: rgb(209, 152, 255);
border-radius: 10px;
}
.brick:nth-child(8) {
background-color: coral;
border-radius: 10px;
}
/* 滑板 */
.skate {
width: 100px;
height: 20px;
background-image: url("../images/skate.png");
border-radius: 20px;
position: absolute;
left: 400px;
bottom: 1px;
}
.ball {
width: 20px;
height: 20px;
position: absolute;
left: 440px;
bottom: 22px;
border-radius: 20px;
background-image: url("../images/ball.png");
}
.message {
font-size: 20px;
position: absolute;
right: 85px;
bottom: 40px;
line-height: 30px;
color: pink;
}
④ JS
/* js\index.js */
// 封装一个添加类名的函数
function addClass(obj) {
// classList 属性返回元素的类名,作为 DOMTokenList 对象
var buttons = document.querySelectorAll(".button");
for (var i = 0; i < buttons.length; i++) {
buttons[i].classList.remove("active");
}
obj.classList.add("active");
};
// 循环创建div
var blocks = document.querySelector(".blocks");
function createBrick(n) {
for (var i = 0; i < n; i++) {
var row = document.createElement("div");
row.classList.add("row");
for (var j = 0; j < 8; j++) {
var brick = document.createElement("div");
brick.classList.add("brick");
row.appendChild(brick);
}
blocks.appendChild(row);
}
var brick = document.querySelectorAll(".brick");
for (var i = 0; i < brick.length; i++) {
brick[i].style.left = brick[i].offsetLeft + "px";
brick[i].style.top = brick[i].offsetTop + "px";
}
for (var j = 0; j < brick.length; j++) {
brick[j].style.position = "absolute";
}
};
createBrick(8);
// 封装定时器
function innerval() {
timer = setInterval(function() {
ball.style.top = ball.offsetTop + spendY + "px";
ball.style.left = ball.offsetLeft + spendX + "px";
// 是否出上边界
if (ball.offsetTop < 0) {
spendY *= -1
}
// 是否出左右边界
if (ball.offsetLeft < 0 || ball.offsetLeft > blocksWidth - ballWidth) {
spendX *= -1
}
// 是否出下边界
if (ball.offsetTop > blocksHeight - ballHeight) {
// 游戏结束,停止定时器
clearInterval(timer)
// 解绑事件
skate.onmousedown = null;
document.onmousemove = null;
alert("游戏结束!");
}
if (collide(ball, skate)) {
spendY *= -1;
}
var rows = document.querySelectorAll(".row");
for (var i = 0; i < rows.length; i++) {
var item = rows[i];
for (var k = 0; k < item.children.length; k++) {
if (collide(ball, item.children[k])) {
spendY *= -1;
item.children[k].style.display = "none";
score++;
var number = document.querySelector(".info-number");
number.innerText = "砖块:" + score;
}
}
}
time++;
var infoTime = document.querySelector(".info-time");
infoTime.innerText = "时间:" + resetTime(time * 20 / 1000)
}, 20);
};
// 封装两个节点相撞的函数
function collide(node1, node2) {
var left1 = node1.offsetLeft;
var right1 = node1.offsetLeft + node1.offsetWidth;
var top1 = node1.offsetTop;
var bottom1 = node1.offsetTop + node1.offsetHeight;
var left2 = node2.offsetLeft;
var right2 = node2.offsetLeft + node2.offsetWidth;
var top2 = node2.offsetTop;
var bottom2 = node2.offsetTop + node2.offsetHeight;
if (left1 > right2 || left2 > right1 || top1 > bottom2 || top2 > bottom1) {
return 0;
} else {
return 1;
}
}
// 重置时间
function resetTime(setTime) {
var f = Math.floor(setTime / 60);
var s = Math.floor(setTime % 60);
return (f < 10 ? "0" + f : f) + ":" + (s < 10 ? "0" + s : s);
}
// querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素
var skate = document.querySelector(".skate");
var gameZone = document.querySelector(".game-zone");
var ball = document.querySelector(".ball");
var blocks = document.querySelector(".blocks");
var skateWidth = skate.offsetWidth;
var skateHeight = skate.offsetHeight;
var gameZoneWidth = gameZone.offsetWidth;
var blocksWidth = blocks.offsetWidth;
var blocksHeight = blocks.offsetHeight;
var ballHeight = ball.offsetHeight;
var ballWidth = ball.offsetWidth;
var spendY;
var spendX;
var timer;
var score = 0;
var time = 1;
// 开始游戏
var play = document.querySelector(".play");
play.onclick = function() {
// play.classList.add("active");
addClass(play);
// 滑板绑定鼠标按下事件
skate.onmousedown = function() {
document.onmousemove = function(e) {
// js在事件处理兼容IE和非IE的写法
var e = e || window.event;
// e.pageX -> 触摸目标在页面中的x坐标。
var moveX = e.pageX - gameZone.offsetLeft - skateWidth / 2;
// 判断是否出了左边界
if (moveX < 0) {
moveX = 0;
}
// 判断是否出了右边界
if (moveX > gameZoneWidth - skateWidth) {
moveX = gameZoneWidth - skateWidth;
}
skate.style.left = moveX + "px";
}
};
document.onmouseup = function() {
// 鼠标弹起解绑鼠标移动事件
document.onmousemove = null;
};
// 小球的垂直速度 -3 ~ -5
spendY = Math.floor(Math.random() * (-3 - (-5) + 1) + -5);
// 小球的水平速度 -5 ~ 5
spendX = Math.floor(Math.random() * (5 - -5 + 1) + -5);
while (spendY == 0) {
// 重新生成一个随机数
spendY = Math.floor(Math.random() * (5 - -5 + 1) + -5);
if (spendX != 0) {
break;
}
}
innerval();
};
// 继续
var keep = document.querySelector(".keep")
keep.onclick = function() {
addClass(keep);
innerval();
};
// 暂停
var suspend = document.querySelector(".suspend")
suspend.onclick = function() {
addClass(suspend);
clearInterval(timer);
};