JS/HTML5游戏开发:追踪算法原理与实现详解

作者:木棉

时间:2026-10-22

浏览:334

本文详解JS/HTML5游戏中常用的追踪算法,包括基础的坐标速度分解算法与更自然的视线追踪算法。通过向量计算实现追踪者始终朝向目标移动的效果,提升游戏可玩性,并提供完整代码示例与在线测试工具。

文章目录

追踪算法概述

本文详细介绍一种在JS/HTML5游戏开发中广泛应用的追踪算法,供开发者参考学习。

追踪算法在动作类游戏中应用极为广泛,从早期的《吃豆人》到现代大型街机机战游戏,追踪效果无处不在。设计优秀的追踪算法能显著提升游戏的可玩性与玩家兴趣。

简单算法实现

简单追踪算法原理

首先介绍一种基础的跟踪算法。如图所示,假设在Canvas坐标系中存在物体A和B,其中物体A负责追踪物体B。物体在二维空间中的运动可分解为X轴和Y轴的分运动,其在X和Y方向的速度分量决定了物体的运行方向与速率。由于速度包含方向与大小,物体A的速度可分解为vx和vy,物体B同理。若物体A要追踪物体B,只需比较两者在X、Y方向的速度即可。设物体A坐标为(x1, y1),速度分量为(vx, vy);物体B坐标为(x2, y2),速度分量为(vx1, vy1)。若A要追踪B,在水平X方向上,若x2大于x1(即B在A右侧),则需将vx设为正值;反之设为负值。垂直Y方向同理处理。

追踪算法概述

基于上述简单算法原理,我们可以尝试构建一个具体的示例。


<!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>
</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;
    balls = [];
    var ball = {
      x: stage.width / 2 - 20,
      y: stage.height / 2 - 20,
      r: 20,
      c: "red"
    };
    balls.push(ball);
    for (var i = 0; i < 30; i++) {
      var trace = {
        x: Math.ceil(Math.random() * (stage.width - 20) + 10),
        y: Math.ceil(Math.random() * (stage.height - 20) + 10),
        r: 10,
        c: "blue"
      };
      balls.push(trace);
    }
    function createBall(x, y, r, c) {
      ctx.beginPath();
      ctx.fillStyle = c;
      ctx.arc(x, y, r, 0, Math.PI * 2);
      ctx.fill();
    }
    stage.addEventListener('click', function (event) {
      var x = event.clientX - stage.getBoundingClientRect().left;
      var y = event.clientY - stage.getBoundingClientRect().top;
      balls[0].x = x;
      balls[0].y = y;
    });
    function update() {
      ctx.clearRect(0, 0, 400, 400);
      ctx.fillStyle = "black";
      ctx.rect(0, 0, 400, 400);
      ctx.fill();
      createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c);
      for (var i = 1, len = balls.length; i < len; i++) {
        //简单算法
        balls[i].x -= ( balls[0].x>balls[i].x)?-1:1;
        balls[i].y -= ( balls[0].y>balls[i].y)?-1:1;
        createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);
      }
      requestAnimationFrame(update);
    }
    update();
  };
</script>
</html>

感兴趣的用户可使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试运行上述代码,以观察实际运行效果。

采用该简单算法的方块运动轨迹较为生硬,变向过程突然,视觉效果不够理想。因此,下文将介绍视线追踪算法。

视线追踪算法实现

视线追踪算法

视线追踪算法的核心在于,追踪者始终沿着与目标对象的连线方向移动。如图所示,这种效果类似于猎豹捕食时死死盯住猎物并直线追击的状态。

要实现此效果,意味着在任意时刻,物体A的速度方向必须保持在A与B连接的直线上。那么,如何获取A在x轴和y轴方向上的速度分量呢?

此处可利用向量知识解决问题。向量仅包含方向与大小,无位置概念。假设任意时刻物体A表示为向量v1(x1, y1),物体B表示为向量v2(x2, y2),则由A指向B的向量v3可表示为(x2−x1, y2−y1)。这三个向量的关系如图6-4所示。设向量v3的长度为VLen = √((x2−x1)² + (y2−y1)²),则向量v3标准化后可表示为v4 = ((x2−x1)/VLen, (y2−y1)/VLen)。最终得到的v4在x轴方向的分量即为物体A在该时刻X轴方向的速度分量,v4在Y轴方向的分量即为物体A在该时刻Y轴方向的速度分量。

追踪算法概述

将上述简单算法按照视线追踪算法的逻辑进行改写:


<!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>
</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;
    balls = [];
    var ball = {
      x: stage.width / 2 - 20,
      y: stage.height / 2 - 20,
      r: 20,
      c: "red"
    };
    balls.push(ball);
    for (var i = 0; i < 30; i++) {
      var trace = {
        x: Math.ceil(Math.random() * (stage.width - 20) + 10),
        y: Math.ceil(Math.random() * (stage.height - 20) + 10),
        r: 10,
        c: "blue"
      };
      balls.push(trace);
    }
    function createBall(x, y, r, c) {
      ctx.beginPath();
      ctx.fillStyle = c;
      ctx.arc(x, y, r, 0, Math.PI * 2);
      ctx.fill();
    }
    stage.addEventListener('click', function (event) {
      var x = event.clientX - stage.getBoundingClientRect().left;
      var y = event.clientY - stage.getBoundingClientRect().top;
      balls[0].x = x;
      balls[0].y = y;
    });
    function update() {
      ctx.clearRect(0, 0, 400, 400);
      ctx.fillStyle = "black";
      ctx.rect(0, 0, 400, 400);
      ctx.fill();
      createBall(balls[0].x, balls[0].y, balls[0].r, balls[0].c);
      for (var i = 1, len = balls.length; i < len; i++) {
        //视线追踪算法
        var vx = balls[i].x - balls[0].x,
          vy = balls[i].y - balls[0].y,
          rlen = Math.sqrt(vx * vx + vy * vy),
          dx = vx / rlen,
          dy = vy / rlen;
        balls[i].x -= dx;
        balls[i].y -= dy;
        createBall(balls[i].x, balls[i].y, balls[i].r, balls[i].c);
      }
      requestAnimationFrame(update);
    }
    update();
  };
</script>
</html>

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

追踪算法概述

相关代码托管于GitHub:https://github.com/krapnikkk/JS-gameMathematics

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《JavaScript数学运算用法总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript数组操作技巧总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》

希望本文所述的算法解析对JavaScript程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章