JavaScript实现打砖块游戏

打砖块游戏是一款非常经典的小游戏,它的核心玩法是玩家要逐一击碎各种形状的砖块,来获得游戏分数。在该游戏中,玩家需要使用挡板控制小球反弹,击打并攻破砖块,从而通过每一关的挑战,最终完成游戏。

JavaScript实现打砖块游戏攻略

简介

打砖块游戏是一款非常经典的小游戏,它的核心玩法是玩家要逐一击碎各种形状的砖块,来获得游戏分数。在该游戏中,玩家需要使用挡板控制小球反弹,击打并攻破砖块,从而通过每一关的挑战,最终完成游戏。

下面,我们将介绍如何使用JavaScript来实现打砖块游戏。

HTML和CSS搭建基础页面

在实现打砖块游戏之前,我们首先需要搭建一个基础页面。这个页面应当包括游戏主体,如游戏区域、挡板、小球和砖块,并通过CSS对这些元素进行布局和样式设计。

具体代码实现:

<div class="game_area">
  <div class="start_area">
    <button class="start_btn">Start Game</button>
    <span>Use left/right arrows to move the paddle</span>
  </div>
  <div class="game_board">
    <div class="ball"></div>
    <div class="paddle"></div>
    <div class="brick"></div>
  </div>
  <div class="score_area">
    <span>Score:</span>
    <span class="score">0</span>
  </div>
</div>

<style>
  .game_area {
    width: 400px;
    height: 400px;
    margin: 50px auto;
    border: 1px solid #888;
    position: relative;
  }
  .start_area {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
  }
  .start_btn {
    padding: 6px 12px;
    font-size: 14px;
    border-radius: 6px;
    border: 1px solid #000;
    background-color: #fff;
    cursor: pointer;
  }
  .game_board {
    width: 100%;
    height: 100%;
    position: absolute;
  }
  .ball {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #f00;
    position: absolute;
    top: 200px;
    left: 190px;
  }
  .paddle {
    width: 80px;
    height: 10px;
    background-color: #00f;
    position: absolute;
    bottom: 10px;
    left: 160px;
  }
  .brick {
    width: 30px;
    height: 15px;
    background-color: #0f0;
    position: absolute;
    top: 30px;
    left: 140px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
  }
  .score_area {
    position: absolute;
    bottom: 10px;
    right: 10px;
    font-size: 16px;
    color: #666;
  }
</style>

JavaScript实现游戏逻辑

在我们已经搭建好游戏的基础页面之后,我们需要使用JavaScript完成游戏的逻辑实现。在这一步中,我们需要着重考虑以下几个问题:

  1. 如何控制挡板移动?
  2. 如何控制小球移动并且让它能够反弹?
  3. 如何检测小球与不同形状砖块的碰撞情况,并且如何实现击碎砖块和获得游戏分数的功能?

为了解决上面提到的问题,我们需要写出一些JavaScript代码来实现这些功能。

控制挡板移动

控制挡板移动其实非常简单,我们只需要监听按键事件,根据按键状态和挡板的速度来移动挡板即可。具体的代码实现如下:

document.addEventListener("keydown", paddleMoveHandler, false);
document.addEventListener("keyup", paddleMoveHandler, false);

function paddleMoveHandler(e) {
  if (e.keyCode == 37) {
    paddle.leftSpeed = (e.type == "keydown" ? -5 : 0);
  }
  if (e.keyCode == 39) {
    paddle.rightSpeed = (e.type == "keydown" ? 5 : 0);
  }
}

function movePaddle() {
  var nextLeft = paddle.el.offsetLeft + paddle.leftSpeed;
  var nextRight = paddle.el.offsetLeft + paddle.rightSpeed + paddle.width;
  if (nextLeft >= 0 && nextRight <= boardWidth) {
    paddle.el.style.left = paddle.el.offsetLeft + paddle.leftSpeed + "px";
  }
}

控制小球移动并且让它能够反弹

让小球移动并且反弹的过程中,我们需要控制小球在不同情况下反弹的方向,而这个方向的计算,其实就是根据小球当前碰撞到的物体的位置来决定。具体的代码实现如下:

function moveBall() {
  ball.el.style.top = ball.el.offsetTop + ball.speedY + "px";
  ball.el.style.left = ball.el.offsetLeft + ball.speedX + "px";
  if (ball.el.offsetLeft <= 0 || ball.el.offsetLeft + ball.el.offsetWidth >= boardWidth) {
    ball.speedX = -ball.speedX;
  }
  if (ball.el.offsetTop <= 0) {
    ball.speedY = -ball.speedY;
  }
  if (ball.el.offsetTop + ball.el.offsetHeight >= paddle.el.offsetTop &&
      ball.el.offsetLeft + ball.el.offsetWidth >= paddle.el.offsetLeft &&
      ball.el.offsetLeft <= paddle.el.offsetLeft + paddle.width) {
    ball.speedY = -ball.speedY;
    ball.speedX = 8 * ((ball.el.offsetLeft + ball.el.offsetWidth / 2) - (paddle.el.offsetLeft + paddle.width / 2)) / paddle.width;
  }
}

检测小球与不同形状砖块的碰撞情况

检测小球与不同形状砖块的碰撞情况其实是打砖块游戏中最为核心的一个功能,因为这个功能决定了我们是否能够顺利地通关游戏。为了实现这个功能,我们需要考虑以下两个问题:

  1. 如何检测小球与砖块的碰撞情况?在小球碰撞到砖块之后,应该如何删除砖块以及如何更新游戏分数?
  2. 如何根据不同类型的砖块来更改游戏UI和游戏变量?

对于第一个问题,我们只需要根据小球和砖块的坐标以及大小来计算它们是否有交集,如果有交集,那么说明小球已经与这个砖块碰撞。具体的代码实现,如下所示:

function checkBrickCollision() {
  for (var i = 0; i < brickList.length; i++) {
    var brick = brickList[i];
    if (ball.el.offsetTop <= brick.el.offsetTop + brick.height + ball.el.offsetHeight && 
        ball.el.offsetTop + ball.el.offsetHeight >= brick.el.offsetTop && 
        ball.el.offsetLeft + ball.el.offsetWidth >= brick.el.offsetLeft && 
        ball.el.offsetLeft <= brick.el.offsetLeft + brick.width &&
        !brick.unbreakable) {
      brick.el.style.display = "none";
      score += (brick.hitScore || defaultScore);
      updateScore();
      ball.speedY = -ball.speedY;
    }
  }
}

对于第二个问题,我们需要使用不同的图片来代表不同类型的砖块,并且在代码中定义砖块的变量,用于存储砖块的属性信息。具体的代码实现,如下所示:

var brickList = [
  {el: document.querySelector(".brick"), unbreakable: true},
  {el: document.querySelector(".brick2"), width: 60, hitScore: 2},
  {el: document.querySelector(".brick3"), width: 45, height: 10, hitScore: 1},
  {el: document.querySelector(".brick4"), width: 30, hitScore: 1},
  {el: document.querySelector(".brick5"), unbreakable: true},
];

var defaultScore = 1;

function updateScore() {
  document.querySelector(".score").innerHTML = score;
}

示例说明

下面,我们通过两个示例,来详细讲解JavaScript实现打砖块游戏的具体过程。

示例1:控制小球移动

首先,我们需要在游戏页面中添加一个小球,同时,我们需要在JavaScript中定义一个变量来存储小球的初始速度:

<div class="game_board">
  <div class="ball"></div>
  <div class="paddle"></div>
  <div class="brick"></div>
</div>

<!-- CSS代码 -->
<style>
  .ball {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background-color: #f00;
    position: absolute;
    top: 200px;
    left: 190px;
  }
</style>
var ball = {
  el: document.querySelector(".ball"),
  speedX: 5,
  speedY: 5,
};

然后,我们需要编写一个函数来控制小球的移动,同时,我们还需要在该函数中增加检测小球边界的功能和轮换反弹的功能。具体的代码实现,如下所示:

function moveBall() {
  ball.el.style.top = ball.el.offsetTop + ball.speedY + "px";
  ball.el.style.left = ball.el.offsetLeft + ball.speedX + "px";
  if (ball.el.offsetTop <= 0 || ball.el.offsetTop + ball.el.offsetHeight >= boardHeight) {
    ball.speedY = -ball.speedY;
  }
  if (ball.el.offsetLeft <= 0 || ball.el.offsetLeft + ball.el.offsetWidth >= boardWidth) {
    ball.speedX = -ball.speedX;
  }
}

最后,我们需要在游戏循环中调用该函数,让小球能够随着时间的推移不断移动。具体的代码实现,如下所示:

function gameLoop() {
  movePaddle();
  moveBall();
  checkBrickCollision();
  setTimeout(gameLoop, 20);
}

gameLoop();

示例2:更改砖块的分数和样式

在打砖块游戏中,不同类型的砖块往往还会有不同的分数和样式。因此,我们需要在代码中为不同类型的砖块定义不同的分数和样式,并且在检测碰撞的函数中根据砖块的类型来更新分数和样式。具体的代码实现,如下所示:

<div class="game_board">
  <div class="ball"></div>
  <div class="paddle"></div>
  <div class="brick"></div>
  <div class="brick2"></div>
  <div class="brick3"></div>
  <div class="brick4"></div>
  <div class="brick5"></div>
</div>

<!-- CSS代码 -->
<style>
  .brick {
    width: 30px;
    height: 15px;
    background-color: #0f0;
    position: absolute;
    top: 30px;
    left: 140px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
  }
  .brick2 {
    width: 60px;
    height: 15px;
    background-image: url("brick2.png");
    position: absolute;
    top: 60px;
    left: 120px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
  }
  .brick3 {
    width: 45px;
    height: 10px;
    background-image: url("brick3.png");
    position: absolute;
    top: 100px;
    left: 140px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
  }
  .brick4 {
    width: 30px;
    height: 15px;
    background-image: url("brick4.png");
    position: absolute;
    top: 130px;
    left: 165px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
  }
  .brick5 {
    width: 30px;
    height: 15px;
    background-color: #00f;
    position: absolute;
    top: 160px;
    left: 180px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
  }
</style>
var brickList = [
  {el: document.querySelector(".brick"), unbreakable: true},
  {el: document.querySelector(".brick2"), width: 60, hitScore: 2},
  {el: document.querySelector(".brick3"), width: 45, height: 10, hitScore: 1},
  {el: document.querySelector(".brick4"), width: 30, hitScore: 1},
  {el: document.querySelector(".brick5"), unbreakable: true},
];

var defaultScore = 1;

function checkBrickCollision() {
  for (var i = 0; i < brickList.length; i++) {
    var brick = brickList[i];
    if (ball.el.offsetTop <= brick.el.offsetTop + brick.height + ball.el.offsetHeight && 
        ball.el.offsetTop + ball.el.offsetHeight >= brick.el.offsetTop && 
        ball.el.offsetLeft + ball.el.offsetWidth >= brick.el.offsetLeft && 
        ball.el.offsetLeft <= brick.el.offsetLeft + brick.width &&
        !brick.unbreakable) {
      brick.el.style.display = "none";
      score += (brick.hitScore || defaultScore);
      updateScore();
      ball.speedY = -ball.speedY;
      ball.speedX = 8 * ((ball.el.offsetLeft + ball.el.offsetWidth / 2) - (paddle.el.offsetLeft + paddle.width / 2)) / paddle.width;
    }
  }
}

总结

通过上面的示例和解释,我们可以发现,JavaScript实现打砖块游戏虽然需要涉及到很多基础知识,但如果我们能够将这些知识合理地组织起来,那么最终实现游戏也并不会很难。因此,如果我们能够系统地学习、掌握一些前端基础,并且能够善于利用相关的资源和工具,那么我们就能够更加自如地实现各种有趣和有价值的项目。

本文标题为:JavaScript实现打砖块游戏

基础教程推荐