朋友让我玩三角洲行动,被地图工具吸引了
我是一个普通的打工人,下班回家后唯一的娱乐就是打开 LOL,选个大乱斗,随缘匹配,乱斗几局,然后顺便吃饭睡觉,日复一日。
某天晚上,一个哥们突然微信我:三角洲行动太好玩了,我都上头了!虽然现在还没固排,赶紧入坑,别老自己一个人大乱斗了。”我随口搪塞了一句:“网速太慢,下载不了……等我搬家换房子再说。”
好哥们也没说什么,等过了俩月我真换房子了,还整了个网线。我想到之前我对那个哥们的承诺,下载了这款游戏。于是联系了他:我下载好了,速来开黑。然后他甩给我一个链接,你先对着地图玩两天。不熟悉地图进去就被踢死了。顺便升升等级,好一起猛攻。我看了一下是一个地图工具,里面是游戏地图,可以查看各类搜索容器、复活点撤离点等信息。好家伙,还真挺有意思的。
后面我也就顺势入了坑,加入三角洲,成为了一名鼠鼠。毕竟上了年纪,打 FPS 这种游戏早就拼不过天才少年的反应了,只能选择避战炫饭。
不过作为一个程序员,我对那套地图工具更感兴趣。我看了一下这个工具,发现 这不是我熟悉的 Leaflet 地图库吗?于是我打算把这个工具涉及到的相关知识分享一波,虽然没什么干货。但看到有意思的东西还是想表达一下。
所以今天咱也不聊游戏,咱就聊聊这个地图工具的相关内容
地址:三角洲行动地图工具
三角洲行动地图工具介绍
三角洲行动地图工具长什么样?
打开网站,你可以看到这样的界面,左侧是交互区域,你可以选择展示哪些信息,比如物资点、撤离点、复活点;
而整个地图铺满视图窗口,所以左侧、右侧交互区是悬浮在地图上方的,通过审查元素 可以看到:
基本的页面结构很简单。不过由于刻板印象,我之前一直以为这些地图库都是用来加载有经纬度的真实地图的。不过转念一想。这种瓦片加载的方式本来就是一张张切好的图片,游戏地图和真实世界地图都是图片而已,没毛病。只不过缺少个坐标系统罢了。但是不妨碍把图片一级一级塞进去呢。于是我打算先向大家介绍一些常见的地图加载方式。
常见的地图加载方式
目前web端常见的地图的加载方式有这么几种:
-
XYZ 瓦片或者TMS瓦片加载
每个瓦片由三元组
{z}/{x}/{y}唯一确定:z:缩放等级(Zoom Level);x:横向瓦片编号(列号);y:纵向瓦片编号(行号);
- 当你拖动/缩放地图时。地图库会做出下列行为:
- 计算当前视图范围;
- 根据当前 zoom 层级、中心点经纬度,反推出视口范围;
- 计算出对应的 tileX, tileY 区间;
- 对每个瓦片请求(例如
z/x/y.png); - 加载完成后拼贴显示在对应位置。
- Zoom 0:整张世界地图只有 1 张图;
- Zoom 1:变成 2×2 = 4 张;
- Zoom 2:4×4 = 16 张,以此类推……
每升一级,瓦片数量呈指数增长。
这是最常见的地图加载方式。你如果想自己搭建一个demo。只需要按照把往名为0-18的文件夹里面塞满名字为三元组的图片。比如857.png。然后通过nginx启动一个服务,然后让地图框架的函数去请求这个地址,就可以顺利的把图片显示到浏览器中去。这里直接请求的是图片资源。网上教程很多,这里不赘述了。
- WMS(Web Map Service)
这个方式在早期特别常见,现在已经渐渐被抛弃了。
- 它的步骤是:你告诉服务器一个地图范围,服务器动态查询数据 + 样式渲染,生成一张图片返回。一般会有下面这些信息
- 地图范围
- 图像大小
- 坐标参考系统
- 图层
- 输出格式
- 缺点很明显,每次拖动、缩放地图都需要重新渲染; 频繁交互 → 请求压力巨大 → 性能不好。
- WMTS(Web Map Tile Service)
WMTS 可以理解为 WMS 的优化升级版:
- 将地图提前切片成瓦片,按缩放层级管理;
- 客户端加载逻辑类似 XYZ;
- 保留了 WMS 的图层语义,又借鉴了瓦片的性能优势。
OGC 标准中最实用的一员。
- 矢量瓦片(Vector Tile)
虽然名字里也叫“瓦片”,但这类是专为矢量数据设计的。并且传输的数据使用高效的编码格式(如 protobuf)压缩: 常用格式为 Mapbox Vector Tile(.mvt 或 .pbf),是 Google protobuf 的二进制压缩形式,体积小、解析快。
-
特点:
- 加载的是数据,不是图像;
- 样式和渲染由客户端控制,交互更灵活;
- 不同缩放层级展示的细节会动态简化,节省性能,视觉效果也更自然。
举个例子:
你在高德 App 上看地铁线路、公交站点,那些线和点都是“矢量要素”。这些数据就适合用矢量瓦片加载。当然如果数据量不大,直接用geojson、WKT、XML也都可以。
- WCS(Web Coverage Service)
最后一个是冷门但很有用的加载方式,专为栅格影像数据服务而设计。
-
与 WMS 类似,但不是图像,而是表达物理量的栅格像元数据;每个像元都有具体的数值,常见的就根据你传入参数给你返回一个GeoTIFF,可以用于分析计算指数等乱七八糟的。遥感学生DNA动了。
-
典型应用:
- DEM(数字高程模型) → 表达海拔;
- 降雨量图、温度图、土地覆盖图等;
-
更适合遥感、气象、水文等专业领域。一般的地图看不到这些内容。
地图工具中用到的leaflet关键函数
其实这个游戏工具的用到的API没几个。而且leaflet非常简单,这类地图库比如openlayer、mapbox、leaflet的用法近乎相同。首先都定义了一个地图对象,leaflet这里叫做L,指定一个你想要挂载的容器
const map = L.map('map')//指定一个挂载点
加载瓦片地图
// 加载瓦片,这里的地址从控制台获取的。
L.tileLayer('https://game.gtimg.cn/images/dfm/cp/a20240729directory/img/map_db/{z}_{x}_{y}.jpg', {
maxZoom: 19, // 最大缩放级别
}).addTo(map);
地图上的物资点呢实际上是一个个marker对象,可以通过图片修改样式。
// 创建 Marker 并添加到地图上,需要指定位置
const marker = L.marker([31.2304, 121.4737]).addTo(map);
完事之后你还可以给他绑定弹窗,这样缩放的时候不用你手动计算弹窗的位置了,地图库帮你处理好了。
marker.bindPopup("<b>Hello World!</b>").openPopup(); //这些地图库做法都是接收一个DOM作为弹窗内容。你完全可以自定义弹窗的样式
剩下的工作量基本就是你需要定义游戏数据了,哪些点位渲染在哪里?如何隐藏打开选中。还有的话就是绘制一些其他的地图要素,比如绘制拉闸点所控制的撤离点的虚线:
const whiteDashedLine = L.polyline(latlngs, {
color: 'white', // 白色线条
weight: 4, // 线条宽度
opacity: 1.0, // 不透明
dashArray: '6, 6' // 虚线:线段长度 6px,间距 6px
}).addTo(map);
最后说几句题外话
不知道为什么,我突然想起了《洛洛历险记》里的一句话,谁说的已经记不清了,但印象一直很深:
“人生就是一场游戏,游戏就是一场人生。
**只不过这场游戏,你想玩也得玩,不想玩也得玩。”
再结合之前挺火的地球online的梗。什么:
- 地球online游戏又肝又氪不推荐新玩家入坑,建议老玩家不要邀请新玩家;
- 主线任务卡到结婚了,需要氪金38.8W才能推进,想弃坑了;
- 能不能让建模师重新修改一下我的建模,完全没有优势啊;
说到底,其实这些梗都有点好笑,但又不只是好笑。
你会发现,它们背后是一种共鸣:大家都觉得地球online这游戏不好打了。俗称又肝又氪
,我也一样。
每天刷短视频,总能看到一些声音说:“现在环境不好,躺平吧,不负债就算成功。”
也会看到另一群人说:“躺平不可取,你也躺不平。”
一来一回,我的判断力也变得模糊了,不知不觉,我也开始麻木了。
最近,女朋友查出了病,治不好的那种,严重的话可能失去生育能力。还要定期检查,增加大量经济压力。所以我个人状态也很差,也挺迷茫的。和新闻里说的那种:“死气沉沉的年轻人”一模一样。
所以后来我也安慰自己,人生会不会真的就是一场游戏吧。毕竟游戏的意义不在于赢,而在于“体验”。因为没有永远的赢家,没有谁会一直赢。
在所有人都觉得淘宝稳坐电商第一的时候,拼多多杀了出来;
大家都认为美团不可动摇时,京东突然喊出“红黄蓝大战开始”。
——你永远不知道游戏进程会怎么改变,也不知道谁是主角,谁会“掉线”。
有时候,换个视角,把它当作一款体验向游戏,反而能撑住你继续往下走。
想到什么做什么吧,想说什么说什么吧。