[JavaScript游戏开发] 2D二维地图绘制、人物移动、障碍检测
系列文章目录
第一章 2D二维地图绘制、人物移动、障碍检测
第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示)
文章目录
- 系列文章目录
- 前言
- 一、列计划
- 1.1、目标
- 1.2、步骤
- 二、使用步骤
- 2.1、准备素材(图片):草坪、人物(熊猫)、障碍(石头)
- 2.2、初始化布局(表格),边距设置为0,无边框,设置背景图(草坪)平铺拉满
- 2.3、标记草坪、熊猫、石头的代码
- 2.4、初始化二维地图数据,初始化障碍物围墙,初始化人物位置
- 2.5、计算公共变量二维地图的行、列
- 2.6、合并二维地图数据、人物位置数据,渲染到页面
- 2.7、设置全局键盘事件(在Body上添加),监听wasd按键事件:w(上) s(下) a(左) d(右)、在事件里增加任务移动逻辑/增加边界逻辑、在事件里增加障碍检测逻辑
- 3、部分效果图
- 总结
前言
复习JavaScript 事件有感,心血来潮想做一个2D二维地图绘制、人物移动、障碍检测相关的单页面游戏。
技术栈:JavaScript、Html、CSS
环境:chrome浏览器
编辑器:记事本(Idea)

一、列计划
1.1、目标
做一个2D二维地图绘制、人物移动、障碍检测相关的单页面游戏
1.2、步骤
- 准备素材(图片):草坪、人物(熊猫)、障碍(石头)
- 初始化布局(表格),边距设置为0,无边框,设置背景图(草坪)平铺拉满
- 标记草坪、熊猫、石头的代码
- 初始化二维地图数据,初始化障碍物围墙,初始化人物位置
- 计算公共变量二维地图的行、列
- 合并二维地图数据、人物位置数据,渲染到页面
- 设置全局键盘事件(在Body上添加),监听wasd按键事件:w(上) s(下) a(左) d(右)
- 在事件里增加任务移动逻辑、增加边界逻辑
- 在事件里增加障碍检测逻辑
二、使用步骤
2.1、准备素材(图片):草坪、人物(熊猫)、障碍(石头)


2.2、初始化布局(表格),边距设置为0,无边框,设置背景图(草坪)平铺拉满
设置table的ID:map1001
代表是编号1001的地图
<style>table { border-collapse: collapse; padding: 0 ; background: url("../img/item/grass.png"); width:100%;height:100% ; background-position: center; background-size:cover; background-repeat: no-repeat; }td { width: 100px; height: 100px; }tr { display: block; margin: -5px; }</style><body onload="init()" onkeypress="keypress(event)">
<table id="map1001">
</table>
</body>
2.3、标记草坪、熊猫、石头的代码
<script>var empty = 0; //空地或草坪var stone = 1; //石头的标记是1var panda = 9; //熊猫的标记是9
</script>
2.4、初始化二维地图数据,初始化障碍物围墙,初始化人物位置
<script>/*** 加载地图数据* 0 空地/草坪* 1 石头* 9 熊猫* @type {number[]}*/var mapData = [[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1] ,[ 1 , 0 , 1 , 0 , 0 , 0 , 0 , 1] ,[ 1 , 0 , 0 , 1 , 0 , 1 , 0 , 1] ,[ 1 , 0 , 0 , 0 , 0 , 1 , 0 , 1] ,[ 1 , 0 , 1 , 0 , 1 , 1 , 0 , 1] ,[ 1 , 0 , 1 , 0 , 0 , 0 , 0 , 1] ,[ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1]]var initPoint = [1,4]; //初始化熊猫的位置是 1,4
</script>
2.5、计算公共变量二维地图的行、列
<script>var row = mapData.length; //地图的行var column = mapData[0].length; //地图的列
</script>
2.6、合并二维地图数据、人物位置数据,渲染到页面
<script>/*** 合并二维地图数据、人物位置数据,渲染到页面*/function init() {//二维数组里,去初始化熊猫的位置mapData[initPoint[0]][initPoint[1]] = pandaloadData(mapData);}/*** 渲染地图* @param mapData*/function loadData(mapData) {// 获取地图对象var map = document.getElementById("map1001");//渲染一行八列的数据var mapHTML = "";for (var i = 0; i < row; i++) {mapHTML += "<tr>";for (var j = 0; j < column; j++) {if( mapData[i][j] == 0 ){mapHTML += "<td></td>";} else if( mapData[i][j] == 1 ){mapHTML += '<td><img src="../img/item/stone.png" style="height: 90px; height: 90px; border-radius: 50%;" ></td>';} else if( mapData[i][j] == 9 ){mapHTML += '<td><img src="../img/item/panda1.png" style="height: 90px; height: 90px; border-radius: 50%;" ></td>';}}mapHTML += "</tr>";}map.innerHTML = mapHTML;}
</script><body onload="init()" >
2.7、设置全局键盘事件(在Body上添加),监听wasd按键事件:w(上) s(下) a(左) d(右)、在事件里增加任务移动逻辑/增加边界逻辑、在事件里增加障碍检测逻辑
<script>/*** 监听wasd按键事件:w(上) s(下) a(左) d(右)* @param e*/var keypress = function keypress(e){var keynum = window.event ? e.keyCode : e.which;if( 119 == keynum ) {var point = initPoint;if( point[0] < row - 1 ) {var xPoint = initPoint[1];var yPoint = initPoint[0] - 1;if( checkStone(yPoint,xPoint) ){console.log("碰撞到石头了,停止动作")return}console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint )initPoint = [yPoint,xPoint]operatePanda(point);console.log("向上")} else {console.log("超出地图范围了,停止动作")}} else if( 97 == keynum ) {var point = initPoint;if( point[1] > 0 ) {var xPoint = initPoint[1] -1;var yPoint = initPoint[0];if( checkStone(yPoint,xPoint) ){console.log("碰撞到石头了,停止动作")return}console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint )initPoint = [yPoint,xPoint]operatePanda(point);console.log("向左")} else {console.log("超出地图范围了,停止动作")}} else if( 115 == keynum ) {var point = initPoint;if( point[0] < row - 1 ) {var xPoint = initPoint[1];var yPoint = initPoint[0] + 1;if( checkStone(yPoint,xPoint) ){console.log("碰撞到石头了,停止动作")return}console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint )initPoint = [yPoint,xPoint]operatePanda(point);console.log("向下")} else {console.log("超出地图范围了,停止动作")}} else if( 100 == keynum ) {var point = initPoint;if( point[1] < column -1 ) {var xPoint = initPoint[1] + 1;var yPoint = initPoint[0];if( checkStone(yPoint,xPoint) ){console.log("碰撞到石头了,停止动作")return}console.log("移动后的位置:x:" + xPoint + " , y:" + yPoint )initPoint = [yPoint,xPoint]operatePanda(point);console.log("向右")} else {console.log("超出地图范围了,停止动作")}}}/*** 障碍检测(可加多个障碍条件)* @param yPoint* @param xPoint* @returns {boolean}*/function checkStone(yPoint , xPoint ) {return mapData[yPoint][xPoint] == stone;}
</script><body onload="init()" onkeypress="keypress(event)">
3、部分效果图
- 尝试走到右上角的位置,初始化位置:1,4,目标值:1,1

- 尝试走直线,从左走到目标,中途碰到石头障碍就走不动了,此时上下左都有石头障碍,都走不动,只能向右走

- 向右走1格
- 向下走2格
- 向左走2格
- 向上走一格
- 向左走一格
- 向上走一格
- 抵达目标

总结
以上就是今天要讲的内容,本文仅仅简单介绍了2D二维地图绘制、人物移动、障碍检测,可以根据此开发出自动寻径避障、多障碍物绘制、NPC自动出现并移动、人物动画动作、多地图切换、装备仓库、装备效果等。例如:推箱子、走迷宫、副本游戏、熊猫吃竹子等。
相关文章:
[JavaScript游戏开发] 2D二维地图绘制、人物移动、障碍检测
系列文章目录 第一章 2D二维地图绘制、人物移动、障碍检测 第二章 跟随人物二维动态地图绘制、自动寻径、小地图显示(人物红点显示) 文章目录 系列文章目录前言一、列计划1.1、目标1.2、步骤 二、使用步骤2.1、准备素材(图片):草坪、人物(熊猫)、障碍(石头)2.2、初…...
区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型
区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型 目录 区间预测 | MATLAB实现基于QRF随机森林分位数回归时间序列区间预测模型效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRF随机森林分位数回归时间序列区间预测模型࿱…...
.NET网络编程——TCP通信
一、网络编程的基本概念 : 1. 网络 就是将不同区域的电脑连接到一起,组成局域网、城域网或广域网。把分部在不同地理区域的计算机于专门的外部设备用通信线路 互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,…...
【Python机器学习】实验01 Numpy以及可视化回顾
文章目录 一、Numpy的基础知识实验1 生成由随机数组成的三通道图片,分别显示每个维度图片,并将三个通道的像素四周进行填充,分别从上下左右各填充若干数据。 二、Numpy的线性代数运算实验2 请准备一张图片,按照上面的过程进行矩阵…...
vue3-组件中的变化
1. 路由 1. 安装指令:npm i vue-routernext 2. 创建路由:createRouter2. 异步组件(defineAsyncComponent) defineAsyncComponent 是用于定义异步组件的函数。defineAsyncComponent 接受一个工厂函数作为参数,这个工厂…...
认识主被动无人机遥感数据、预处理无人机遥感数据、定量估算农林植被关键性状、期刊论文插图精细制作与Appdesigner应用开发
目录 第一章、认识主被动无人机遥感数据 第二章、预处理无人机遥感数据 第三章、定量估算农林植被关键性状 第四章、期刊论文插图精细制作与Appdesigner应用开发 更多推荐 遥感技术作为一种空间大数据手段,能够从多时、多维、多地等角度,获取大量的…...
数学建模的六个步骤
一、模型准备 了解问题的实际背景,明确其实际意义,掌握对象的各种信息,以数学思路来解释问题的精髓,数学思路贯彻问题的全过程,进而用数学语言来描述问题。要求符合数学理论,符合数学习惯,清晰…...
【计算机组成原理】24王道考研笔记——第二章 数据的表示和运算
第二章 数据的表示和运算 一、数值与编码 1.1 进制转换 任意进制->十进制: 二进制<->八进制、十六进制: 各种进制的常见书写方式: 十进制->任意进制:(用拼凑法最快) 真值:符合人…...
JQ-6 Bootstrap入门到实战;Bootstrap的(优缺点、安装、响应式容器原理、网格系统、响应式工具类、Bootstrap组件);小项目实践
目录 1_认识Bootstrap1.1_概念1.2_起源和历史1.3_Bootstrap优缺点 2_Bootstrap4的安装2.1_方式一 CDN2.2_方式二 : 下载源码引入2.3_方式三 : npm安装 3_Bootstrap初体验4_响应式容器原理4.1_屏幕尺寸的分割点(Breakpoints)4.2_响应式容器Containers 5_网…...
如何用3D格式转换工具HOOPS Exchange读取颜色和材料信息?
作为应用程序开发人员,非常希望导入部件的图形表示与它们在创作软件中的外观尽可能接近。外观可以在每个B-Rep面的基础上指定,而且,通过装配层次结构的特定路径可以在视觉外观上赋予父/子覆盖。HOOPS ExchangeHOOPS Exchange可捕获有关来自各…...
[Ubuntu 22.04] 安装docker,并设置镜像加速
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; doneapt install -y curl vim wget gnupg dpkg apt-transport-https lsb-release ca-certificates# 添加Docker的GPG公钥和apt源 #curl -sSL https://download.d…...
如何使用GPT作为SQL查询引擎的自然语言
生成的AI输出并不总是可靠的,但是下面我会讲述如何改进你的代码和查询的方法,以及防止发送敏感数据的方法。与大多数生成式AI一样,OpenAI的API的结果仍然不完美,这意味着我们不能完全信任它们。幸运的是,现在我们可以…...
Servlet3.0上传文件
页面: <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>文件上传</title> </head> <body> <form action"fileup" enctype"multipart/form-data" method"…...
【ARM Cache 系列文章 6 番外篇 – MMU, MPU, SMMU, PMU 差异与关系】
文章目录 MMU 与 MPU 之间的关系MMU 与 SMMU 之间的关系MMU 与 PMU 之间的关系 上篇文章:ARM Cache 系列文章 5 – 内存屏障ISB/DSB/DMB MMU 与 MPU 之间的关系 MMU(Memory Management Unit)和MPU(Memory Protection Unit&#…...
NetSuite ERP顾问的进阶之路
目录 1.修养篇 1.1“道”是什么?“器”是什么? 1.2 读书这件事儿 1.3 十年计划的力量 1.3.1 一日三省 1.3.2 顾问损益表 1.3.3 阶段课题 2.行为篇 2.1协作 2.2交流 2.3文档管理 2.4时间管理 3.成长篇 3.1概念能力 3.1.1顾问的知识结构 …...
js 新浏览器打开页面
博主gzh:“程序员野区”,回复“加群”,可进博主web前端微信群 效果如下 setTimeout(()>{var url "https://blog.csdn.net/xuelang532777032?typeblog"; //要打开的网页地址var features "height500, width800, top100, left100, …...
jmeter软件测试实验(附源码以及配置)
jmeter介绍 JMeter是一个开源的性能测试工具,由Apache软件基金会开发和维护。它主要用于对Web应用程序、Web服务、数据库和其他类型的服务进行性能测试。JMeter最初是为测试Web应用程序而设计的,但现在已经扩展到支持更广泛的应用场景。 JMeter 可对服务…...
ZooKeeper原理剖析
1.ZooKeeper简介 ZooKeeper是一个分布式、高可用性的协调服务。在大数据产品中主要提供两个功能: 帮助系统避免单点故障,建立可靠的应用程序。提供分布式协作服务和维护配置信息。 2.ZooKeeper结构 ZooKeeper集群中的节点分为三种角色:Le…...
【算组合数】CF1833 F
少见地秒了这道1700,要是以后都这样就好了.... Problem - F - Codeforces 题意: 给定一个数列,让你在这个数列里找一个大小为M的子集,使得极差不超过M 思路: 子集,不是子序列,说明和顺序无…...
Attention详解(自用)
encoder-decoder 分心模型:没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多细节信息࿰…...
如何用PPI网络community分析发现潜在药物靶点?微生信可视化保姆教程
从PPI网络到药物靶点:基于Community分析的生物标记物发现全流程 在生物医学研究的浩瀚海洋中,蛋白质-蛋白质相互作用(PPI)网络犹如一张精密的城市交通图,而community分析则帮助我们识别出其中的"功能街区"。想象一下,当…...
TI DSP BootLoader实战:从Flash分区到安全跳转的工程化指南
1. 为什么需要BootLoader? 想象一下你家的空调遥控器突然需要升级功能,但厂家要求必须拆开外壳用专用设备烧录——这显然不现实。BootLoader就是嵌入式设备的"遥控器升级按钮",让设备在出厂后仍能通过常规接口(如串口、…...
Offline-First数据同步策略:解决网络中断的智能方案
Offline-First数据同步策略:解决网络中断的智能方案 【免费下载链接】offline-first :electric_plug: Everything you need to know to create offline-first web apps. 项目地址: https://gitcode.com/gh_mirrors/of/offline-first 在当今移动优先的时代&am…...
3步告别微信单向好友:WechatRealFriends帮你轻松识别谁删了你
3步告别微信单向好友:WechatRealFriends帮你轻松识别谁删了你 【免费下载链接】WechatRealFriends 微信好友关系一键检测,基于微信ipad协议,看看有没有朋友偷偷删掉或者拉黑你 项目地址: https://gitcode.com/gh_mirrors/we/WechatRealFrie…...
银河麒麟V4.0.2-sp4服务器到手后,这三步网络配置(IP/DNS/源)一个都不能少
银河麒麟V4.0.2-sp4服务器网络配置实战指南:从零搭建稳定运行环境 刚拿到一台预装银河麒麟V4.0.2-sp4操作系统的服务器时,许多运维工程师常会陷入"有设备却用不起来"的困境——无法远程连接、软件包安装失败、系统更新卡壳,这些问题…...
别再混淆了!FFmpeg提取AAC/H264流时常见的3个容器格式误区
别再混淆了!FFmpeg提取AAC/H264流时常见的3个容器格式误区 第一次用FFmpeg提取音频时,我把.m4a文件直接重命名为.aac,结果播放器报错——这个看似简单的操作背后,隐藏着容器格式与编码格式的深层差异。本文将用真实踩坑案例&#…...
避坑指南:Dify知识库数据清洗的5个常见错误与正则表达式优化技巧
避坑指南:Dify知识库数据清洗的5个常见错误与正则表达式优化技巧 在企业级知识库构建过程中,数据清洗环节往往成为影响LLM问答质量的关键瓶颈。许多团队投入大量资源进行知识库建设后,仍面临"清洗了数据但召回率低"的困境。本文将揭…...
一文搞懂训练大模型的数据怎么准备!
谈到大模型,很多人第一反应都是模型参数大、算力强,但其实数据才是大模型真正的底座。没有足够大、足够干净的数据,再先进的模型也发挥不出威力。今天就从数据层面,把大模型训练的几个关键环节梳理清楚。 数据采集与清洗 大模型训…...
从零到一:基于LLaMA-Factory的微调实战与核心参数精讲
1. 环境准备与LLaMA-Factory初探 第一次接触LLaMA-Factory时,我对着官方文档发呆了半小时——这个工具链实在太强大了,但新手很容易被各种依赖项劝退。这里分享我的踩坑经验:不要一上来就追求最新版本。去年12月我在RTX 3090上折腾v0.4.0时&a…...
ArXiv:为何大模型无法拥有意识|Erik Hoel
导语当AI能流畅谈论“自我感受”,当Anthropic赋予Claude“对话退出权”,我们是否可以说它有意识?2026年初,神经科学家Erik Hoel在ArXiv发布论文《大语言模型意识证伪:持续学习对意识存在的必要性》(A Dispr…...
