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 相关文章推荐
jquery 1.4.2发布!主要是性能与API
Feb 25 Javascript
URL地址中的#符号使用说明
Feb 12 Javascript
鼠标选择动态改变网页背景颜色的JS代码
Dec 10 Javascript
js中传递特殊字符(+,&amp;)的方法
Jan 16 Javascript
Javascript基础教程之数据类型 (字符串 String)
Jan 18 Javascript
jQuery表单域属性过滤器用法分析
Feb 10 Javascript
js实现点击链接后窗口缩小并居中的方法
Mar 02 Javascript
JS获取文件大小方法小结
Dec 08 Javascript
jQuery手风琴的简单制作
May 12 jQuery
JavaScript设置名字输入不合法的实现方法
May 23 Javascript
使用prop解决一个checkbox选中后再次选中失效的问题
Jul 05 Javascript
vue二级路由设置方法
Feb 09 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
PHILIPS AE3805收音机的分析打磨
2021/03/02 无线电
输出控制类
2006/10/09 PHP
使用无限生命期Session的方法
2006/10/09 PHP
写一个用户在线显示的程序
2006/10/09 PHP
php5编程中的异常处理详细方法介绍
2008/07/29 PHP
PHP中删除变量时unset()和null的区别分析
2011/01/27 PHP
浅析php插件 Simple HTML DOM 用DOM方式处理HTML
2013/07/01 PHP
PHP中的按位与和按位或操作示例
2014/01/27 PHP
jQuery 技巧大全(新手入门篇)
2009/05/12 Javascript
45个JavaScript编程注意事项、技巧大全
2015/02/11 Javascript
JavaScript使用setTimeout实现延迟弹出警告框的方法
2015/04/07 Javascript
jquery拖拽效果完整实例(附demo源码下载)
2016/01/14 Javascript
jQuery文本框得到与失去焦点动态改变样式效果
2016/09/08 Javascript
JS实现仿百度文库评分功能
2017/01/12 Javascript
jQuery操作之效果详解
2017/05/19 jQuery
前端构建工具之gulp的配置与搭建详解
2017/06/12 Javascript
JavaScript实现三级联动效果
2017/07/15 Javascript
浅谈angular.js跨域post解决方案
2017/08/30 Javascript
VuePress 快速踩坑小结
2019/02/14 Javascript
python连接MySQL、MongoDB、Redis、memcache等数据库的方法
2013/11/15 Python
用python实现面向对像的ASP程序实例
2014/11/10 Python
浅析Python中元祖、列表和字典的区别
2016/08/17 Python
python中文乱码不着急,先看懂字节和字符
2017/12/20 Python
Python无损音乐搜索引擎实现代码
2018/02/02 Python
Pandas之drop_duplicates:去除重复项方法
2018/04/18 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
对python文件读写的缓冲行为详解
2019/02/13 Python
英国时尚泳装品牌:Maru Swimwear
2019/10/06 全球购物
酒后驾驶检讨书
2014/01/27 职场文书
大明湖导游词
2015/02/03 职场文书
大学生毕业个人总结
2015/02/15 职场文书
初一数学教学反思
2016/02/17 职场文书
职场中的你,辞职信写对了吗?
2019/06/26 职场文书
职场领导同事生日简短祝福语
2019/08/06 职场文书
JS中一些高效的魔法运算符总结
2021/05/06 Javascript
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python