[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 分心模型:没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多细节信息࿰…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
