[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 分心模型:没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多细节信息࿰…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
