JS/HTML5游戏开发:基于网格的碰撞检测算法详解

作者:木棉时间:2026-10-23 05:07:05浏览:187

本文详解JavaScript游戏中常用的网格碰撞检测算法。通过构建二维数组表示逻辑地图,利用0和1标识通行与障碍,实现高效的人物与NPC或障碍物碰撞判断。文章提供完整代码示例,分析该算法在RPG、SLG等类型游戏中的应用,并探讨其优缺点及精度优化建议。

网格碰撞检测算法概述

本文详细介绍一种在JS/HTML5游戏开发中广泛使用的碰撞检测技术——地图格子算法。内容包含原理分析、代码实现及实际应用案例,供开发者参考学习。

算法适用场景与地图构建

该算法常见于RPG(如早期的《最终幻想》、《勇者斗恶龙》、《仙剑奇侠传》)、SLG(如《炎龙骑士团》、《超级机器人大战》)以及PUZ(如《俄罗斯方块》、《宝石迷阵》)类游戏。在这类游戏中,地图通常由基础地图块拼接而成。开发时,首先对构成地图的基本元素进行编号,随后通过组合这些编号块来构建任意尺寸的地图。

逻辑层设计与碰撞判断原理

早期RPG或SLG游戏的地图明显由小格子构成。这种设计优势在于节省内存,仅需少量基础元素即可组合出大规模地图,具有简单灵活的特点,但视觉美观度可能受限。为了便于处理碰撞逻辑(如人物与NPC交互或避开不可通行障碍),游戏内部通常维护一张不可见的逻辑层地图。该逻辑层与视觉地图大小一致,同样划分为网格。通常使用一个二维数组来描述此层:数组值为1代表不可通行,0代表可通行。例如,当控制人物移动时,只需查询对应网格数组值,即可快速判断是否发生碰撞。

代码实现与测试


var mapArr = [
      1, 0, 0, 1,
      0, 0, 0, 1,
      0, 1, 0, 0,
      1, 0, 0, 1
    ];

具体实现代码如下:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <meta charset="UTF-8">
  <title>地图格子算法</title>
  <style>
    #stage {
      border: 1px solid lightgray;
    }
  </style>
</head>
<body>
<canvas id="stage"></canvas>
</body>
<script>
  window.onload = function () {
    var stage = document.querySelector('#stage'),
      ctx = stage.getContext('2d');
    stage.width = 400;
    stage.height = 400;
    var mapArr = [
      1, 0, 0, 1,
      0, 0, 0, 1,
      0, 1, 0, 0,
      1, 0, 0, 1
    ],rectIdx = 5;
    //栅格线条
    function drawGrid(context, color, stepx, stepy) {
      context.strokeStyle = color;
      context.lineWidth = 0.5;
      for (var i = stepx + 0.5; i < context.canvas.width; i += stepx) {
        context.beginPath();
        context.moveTo(i, 0);
        context.lineTo(i, context.canvas.height);
        context.stroke();
      }
      for (var i = stepy + 0.5; i < context.canvas.height; i += stepy) {
        context.beginPath();
        context.moveTo(0, i);
        context.lineTo(context.canvas.width, i);
        context.stroke();
      }
    }
    function createRect(x, y, r, c) {
      ctx.beginPath();
      ctx.fillStyle = c;
      ctx.rect(x, y, r, r);
      ctx.fill();
    }
    document.onkeydown = function (event) {
      var e = event || window.event || arguments.callee.caller.arguments[0];
      //根据地图数组碰撞将测
      switch (e.keyCode){
        case 37:
          console.log("Left");
          if (rectIdx - 1 >= 0 && (rectIdx - 1) % 4 !== 3 && !mapArr[rectIdx - 1]) {
            rectIdx -= 1;
          }
          break;
        case 38:
          console.log("Top");
          if (rectIdx - 4 >= 0 && !mapArr[rectIdx - 4]) {
            rectIdx -= 4;
          }
          break;
        case 39:
          console.log("Right");
          if ((rectIdx + 1) % 4 !== 0 && !mapArr[rectIdx + 1]) {
            rectIdx += 1;
          }
          break;
        case 40:
          console.log("Bottom");
          if (rectIdx + 4 < mapArr.length && !mapArr[rectIdx + 4]) {
            rectIdx += 4;
          }
          break;
        default:
          return false;
       }
    };
    function update() {
      ctx.clearRect(0, 0, 400, 400);
      drawGrid(ctx, 'lightgray', 100, 100);
      var rect = {
        x: rectIdx % 4 * 100,
        y: rectIdx % 4 === 0 ? rectIdx / 4 * 100 : Math.floor(rectIdx / 4) * 100,
        r: 100,
        c: "blue"
      };
      createRect(rect.x, rect.y, rect.r, rect.c);
      //根据地图数组创建色块
      for (var i = 0, len = mapArr.length; i < len; i++) {
        if (mapArr[i]) {
          createRect(i % 4 * 100, i % 4 === 0 ? i / 4 * 100 : Math.floor(i / 4) * 100, 100, "red");
        }
      }
      requestAnimationFrame(update);
    }
    update();
  };
</script>
</html>

利用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试运行上述代码,可得到如下运行结果:

网格碰撞检测算法概述

完整代码仓库地址:https://github.com/krapnikkk/JS-gameMathematics

算法优缺点与精度优化

这种判断方式逻辑简单且执行效率高,但精度有限。若游戏对象的尺寸远小于网格尺寸,可能出现物体虽未接触但已无法继续移动的情况(即“悬空”碰撞)。因此,采用此类算法时,建议缩小网格尺寸,或确保游戏角色尺寸与网格大小相匹配,以减少视觉与逻辑上的偏差。

如果您对JavaScript算法感兴趣,还可参考本站其他专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》。

希望本文关于JavaScript程序设计的分享能对您的开发工作有所帮助。

作者最新文章