JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解


Posted in Javascript onDecember 12, 2018

本文实例讲述了JS/HTML5游戏常用算法之碰撞检测 地图格子算法。分享给大家供大家参考,具体如下:

这种算法经常用于RPG(早期的《最终幻想》、《DQ》、《仙剑奇侠传》)、SLG(《炎龙骑士团》、《超级机器人大战》)、PUZ(《俄罗斯方块》、《宝石谜阵》)类型的游戏。这类游戏中,通常情况下整个地图都是由一些地图块元素组成,在制作的时候首先给制作出地图所需要的最基本的元素进行编号,然后把这些编号的地图块组合起来就可以根据需要形成任意大小的地图。

早期的RPG类型或者SLG类型的游戏可以明显地看出游戏中的地图是由一些小的地图块格子而成,采用这种方式组成地图的好处是节约内存的使用,并且不需要太多的地图元素就可以任意组合成足够大的地图,简单灵活,缺陷就是最后制作出的地图不太美观。但实际上为了便于游戏中的碰撞检测,比如人物碰到NPC或者是碰到不可跨越的障碍等情况,在游戏中实际上还是保存了一张看不见的逻辑层。这个层的大小和地图等大,并且也进行了格子划分,主要目的就是为了碰撞检测,通常我们在游戏中对这个碰撞逻辑层使用一个数组描述信息,使用 1 表示不可以通过,0表示可以通过,假设人物和NPC在游戏中行走,这种情况下我们就很容易检测地图中人物是否碰到了NPC或者障碍物。

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.3water.com/code/HtmlJsRun测试运行上述代码,可得到如下运行结果:

JS/HTML5游戏常用算法之碰撞检测 地图格子算法实例详解

github地址:https://github.com/krapnikkk/JS-gameMathematics

采用这种方式判断逻辑极其简单,效率也比较高,但不太精确,如果A物体的大小比格子小很多,则物体行动的时候可能看起来离B物体有些距离就无法行走了,所以做这种类型游戏最好保证格子足够小或者保证人物大小和格子相差不大

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
起点页面传值js,有空研究学习下
Jan 25 Javascript
Jquery iframe内部出滚动条
Feb 11 Javascript
锋利的jQuery jQuery中的DOM操作
Mar 21 Javascript
js静态方法与实例方法分析
Jul 04 Javascript
jQuery实现带滚动线条导航效果的方法
Jan 30 Javascript
javascript获得当前的信息的一些常用命令
Feb 25 Javascript
JavaScript中的this关键字使用详解
Aug 14 Javascript
jquery实现简单文字提示效果
Dec 02 Javascript
JS区分浏览器页面是刷新还是关闭
Apr 17 Javascript
js图片加载效果实例代码(延迟加载+瀑布流加载)
May 12 Javascript
node.js实现为PDF添加水印的示例代码
Dec 05 Javascript
js验证密码强度解析
Mar 18 Javascript
JS/HTML5游戏常用算法之追踪算法实例详解
Dec 12 #Javascript
js使用swiper实现层叠轮播效果实例代码
Dec 12 #Javascript
如何制作一个Node命令行图像识别工具
Dec 12 #Javascript
JS遍历JSON数组及获取JSON数组长度操作示例【测试可用】
Dec 12 #Javascript
ionic使用angularjs表单验证(模板验证)
Dec 12 #Javascript
微信小程序自定义导航教程(兼容各种手机)
Dec 12 #Javascript
express express-session的使用小结
Dec 12 #Javascript
You might like
支持php4、php5的mysql数据库操作类
2008/01/10 PHP
仿AS3实现PHP 事件机制实现代码
2011/01/27 PHP
php简单开启gzip压缩方法(zlib.output_compression)
2013/04/13 PHP
PHP中读取照片exif信息的方法
2014/08/20 PHP
PHP设计模式之工厂模式与单例模式
2016/09/28 PHP
PHP的自定义模板引擎
2017/03/24 PHP
Yii2第三方类库插件Imagine的安装和使用
2017/07/06 PHP
php输出反斜杠的实例方法
2019/09/19 PHP
PHP实现常用排序算法的方法
2020/02/05 PHP
键盘控制事件应用教程大全
2006/11/24 Javascript
javascript中取前n天日期的两种方法分享
2014/01/26 Javascript
jquery解析xml字符串简单示例
2014/04/11 Javascript
有效提高JavaScript执行效率的几点知识
2015/01/31 Javascript
获取IE浏览器Cookie信息的方法
2017/01/23 Javascript
获取本机IP地址的实例(JavaScript / Node.js)
2017/11/24 Javascript
基于Vuex无法观察到值变化的解决方法
2018/03/01 Javascript
javascript深拷贝、浅拷贝和循环引用深入理解
2018/05/27 Javascript
微信小程序之事件交互操作实例分析
2018/12/03 Javascript
Vue使用localStorage存储数据的方法
2019/05/27 Javascript
vue-父子组件和ref实例详解
2019/11/10 Javascript
vue实现拖拽效果
2019/12/23 Javascript
javascript单张多张图无缝滚动实例代码
2020/05/10 Javascript
教你安装python Django(图文)
2013/11/04 Python
pandas.DataFrame删除/选取含有特定数值的行或列实例
2018/11/07 Python
django Layui界面点击弹出对话框并请求逻辑生成分页的动态表格实例
2020/05/12 Python
Python结合百度语音识别实现实时翻译软件的实现
2021/01/18 Python
css3动画效果抖动解决方法
2018/09/03 HTML / CSS
用CSS3的box-reflect设置文字倒影效果的方法讲解
2016/03/07 HTML / CSS
CSS3实现各种图形的示例代码
2016/10/19 HTML / CSS
HTML5是否真的可以取代Flash
2010/02/10 HTML / CSS
代理商会议邀请函
2014/01/27 职场文书
校本教研活动总结
2014/07/01 职场文书
销售人才自我评价范文
2014/09/27 职场文书
建国大业电影观后感
2015/06/01 职场文书
Apache Pulsar集群搭建部署详细过程
2022/02/12 Servers
十大动画制作软件,Adobe产品上榜两款,第一是行业标准软件
2022/03/18 杂记