2D 等轴测视角:完整理论
05/2584 浏览开发心得
2D 等轴测视角:完整理论
一、视角的本质
什么是等轴测
人站在高处斜着往下看地面,地面上的方格子不再是正方形,而变成了菱形。这就是等轴测的视觉本质。
俯视(正上方看下去): 等轴测(斜上方看下去):
┌──┬──┬──┐ ◇
├──┼──┼──┤ ◇ ◇
├──┼──┼──┤ ◇ ◇ ◇
└──┴──┴──┘ ◇ ◇
◇
正方形网格经过旋转 + 压缩,变成了菱形网格。
为什么是 2:1
业界最通用的等轴测比例是菱形宽:高 = 2:1。
╱╲ 宽 = 2 单位
╱ ╲ 高 = 1 单位
╱ ╲
╱ ╲
╲ ╱
╲ ╱
╲ ╱
╲╱
为什么选 2:1:
比例 视觉效果 问题
1:1 正菱形,像扑克牌方块♦ 太陡,像从很低的角度看
2:1 最经典,视野开阔 无
3:1 非常扁,接近俯视 建筑太矮,缺乏立体感
2:1 对应的理论观察角度约为 30°(从水平线往上抬 30° 的仰角去看),但在像素游戏中不需要精确角度,只需要记住"宽是高的两倍"这一条规则。
投影公式
这是整个系统的数学基石。假设每个格子宽 W、高 H(W = 2H):
网格坐标 (col, row) → 屏幕坐标 (sx, sy)
sx = (col - row) × W/2
sy = (col + row) × H/2
逆变换(屏幕坐标反推网格坐标):
col = (sx / (W/2) + sy / (H/2)) × 0.5
row = (sy / (H/2) - sx / (W/2)) × 0.5
直觉理解:
col 增大 → 屏幕往右下走
row 增大 → 屏幕往左下走
col 和 row 同时增大 → 纯粹往屏幕下方走
col 增大 row 减小 → 纯粹往屏幕右方走
二、地图的制作原理
层级结构
等轴测地图不是一张大图片,而是由多层数据叠加而成:
┌─────────────────────────────┐
│ 第四层:UI / HUD │ ← 固定在屏幕上,不随地图滚动
├─────────────────────────────┤
│ 第三层:角色 / NPC │ ← 按 Y 坐标排序(遮挡关系)
├─────────────────────────────┤
│ 第二层:建筑 / 障碍物 │ ← 有高度的物体
├─────────────────────────────┤
│ 第一层:地面瓦片 │ ← 最底层,铺满整个地图
└─────────────────────────────┘
地面层:瓦片铺设
地面是一个二维数组,每个格子存一个类型编号:
tileType[row][col] = GRASS / ROAD / WATER / PLAZA / ...
渲染时遍历可见范围内的格子,根据类型选择对应的菱形贴图:
对于每个可见格子 (col, row):
1. 用投影公式算出屏幕坐标 (sx, sy)
2. 查表得到瓦片类型 → 选择贴图
3. 在 (sx, sy) 处绘制菱形贴图
关键优化:只绘制屏幕可见区域。一张 281×242 的地图有 6.8 万格子,全部遍历太慢。通过相机位置和缩放级别,反算出可见的 col/row 范围,只遍历这个子集。
道路系统:参数化定义
道路不是逐格手工填充,而是用参数化线段定义:
一条道路 = {
方向: 水平 或 垂直,
中心线: 第几行/列,
起止: 从第几格到第几格,
宽度: 占几格,
}
示例:一条宽 5 格的水平主干道
中心线 coord = 50
──────────────────────────
│ row 48 │░░░░░░░░░░│ ← coord - 2
│ row 49 │░░░░░░░░░░│
│ row 50 │░░░░░░░░░░│ ← 中心
│ row 51 │░░░░░░░░░░│
│ row 52 │░░░░░░░░░░│ ← coord + 2
──────────────────────────
from → to
判断某格是否是道路:
for 每条道路 do
half = floor(宽度 / 2)
if 水平道路 then
if row 在 [coord-half, coord+half] 且 col 在 [from, to] then
→ 是道路
else -- 垂直道路
if col 在 [coord-half, coord+half] 且 row 在 [from, to] then
→ 是道路
这种方式用十几条数据就能定义整个城市的路网,比逐格填充高效几个数量级。
区域系统:矩形标记
建筑、广场、水域等用矩形区域定义:
一个区域 = {
左上角: (col1, row1),
右下角: (col2, row2),
类型: 建筑 / 广场 / 水域,
名称: "xxx",
}
查询某格属于什么区域:
function getTileInfo(col, row)
-- 优先判断道路(道路覆盖在区域之上)
for 每条道路 do
if 在道路范围内 then return "道路", 可走
end
-- 再判断区域
for 每个区域 do
if col 在 [x1, x2] 且 row 在 [y1, y2] then
return 区域类型, 是否可走
end
end
-- 默认是草地
return "草地", 可走
end
通行性
每种瓦片类型有固定的通行规则:
类型 可通行 说明
草地 是 默认地面
道路 是 主要行走路线
广场 是 开阔区域
建筑 否 角色绕行
水域 否 不可踏入
城门 是 出入口
三、建筑的制作原理
等轴测建筑的核心思想:在菱形底面上向上"挤出"墙壁,再盖上屋顶。虽然整个画面是纯平面绘制,但通过几何技巧模拟出立体感。
步骤一:确定地面菱形
建筑占据一个矩形区域 (col1,row1) 到 (col2,row2),投影到屏幕后是一个菱形:
顶点 (col1,row1)
◇
╱ ╲
左点 ╱ ╲ 右点
(col1,row2+1) (col2+1,row1)
╲ ╱
╲ ╱
◇
底点 (col2+1,row2+1)
4 个角的屏幕坐标用投影公式算出。
步骤二:向上挤出墙壁
将地面菱形的 4 个顶点各向屏幕 Y 方向上移 wallHeight 像素,得到顶面 4 点:
顶面 (上移 wallH)
◇ ─ ─ ─ ─ ─ ◇
╱ │ ╱ │
╱ │ ╱ │
◇ │ ◇ │ ← 只画可见的两个面
╲ │ ╲ │ (左墙面 + 右墙面)
╲ │ ╲ │
◇ ─ ─ ─ ─ ─ ◇
地面菱形
等轴测视角下,只能看到建筑的两个侧面:
左墙面(西南面):顶点连线为 左点→底点→底点上方→左点上方
右墙面(东南面):顶点连线为 底点→右点→右点上方→底点上方
北面和西面被自身遮挡,不需要画。
步骤三:光影区分
两个可见面用不同明度区分,制造光照感:
光源假设在右上方:
左墙面(背光):基色 - 35 明度 较暗
右墙面(受光):基色 + 8 明度 较亮
假设墙壁基色 RGB = (190, 170, 140)
左墙: (155, 135, 105) ← 减 35,阴影面
右墙: (198, 178, 148) ← 加 8,受光面
仅这一步就能让平面绘制产生很强的立体感。
步骤四:添加屋顶
两种常见屋顶形态:
尖顶(四棱锥):
尖顶点
△
╱ │ ╲
╱ │ ╲
╱ │ ╲
左上 ╱─────│─────╲ 右上
╲ │ ╱
╲ │ ╱
╲ │ ╱
底上
尖顶点 = 顶面中心再上移 peakHeight
4 个三角面,分别用不同深浅的屋顶色
平顶:
顶面直接画一个填充菱形
◇
╱ ╲
◇ ◇
╲ ╱
◇
步骤五:装饰细节
在墙面上叠加细节增加真实感:
砖缝线:
沿墙面水平方向画几条等距细线
颜色比墙面暗 20-30,半透明
模拟石砖或木板纹理
门:
右墙面底部中央画一个深色矩形
宽度约占墙面 16%,高度约占墙高 45%
窗户(可选):
墙面上方画小矩形,浅色描边
步骤六:阴影
在地面菱形偏移 (3, 3) 像素处画一个半透明黑色菱形,模拟地面投影:
真实菱形位置
◇
╱ ╲ ◇ ← 阴影 (偏移3px, 黑色半透明)
◇ ◇ ╱ ╲
╲ ╱ ◇ ◇
◇ ╲ ╱
◇
先画阴影,再画建筑本体,阴影就自然出现在建筑边缘。
建筑配色体系
不同功能的建筑用不同色系区分:
建筑类型 墙面色调 屋顶色调 屋顶形态
城堡/官方 灰蓝石 深蓝 平顶
商店 暖砂岩 红瓦 尖顶
民居 木色 红棕 尖顶
宗教 白石 铜绿 尖顶
竞技/军事 砂石 灰褐 平顶
公共服务 浅石 棕瓦 尖顶
这样玩家不看文字标注,光凭颜色就能大致分辨建筑功能。
四、绘制顺序(遮挡关系)
等轴测最关键的问题:谁画在谁前面?
规则很简单:先画远的,后画近的。"远近"的判断标准是 col + row 的值(即屏幕 Y 方向):
绘制顺序(从远到近):
row=0, col=0 ← 最先画(最远,屏幕最上方)
row=0, col=1
row=1, col=0
row=1, col=1
...
row=N, col=M ← 最后画(最近,屏幕最下方)
画面叠加效果:
远处建筑 (先画)
┊
近处角色 (后画,覆盖在建筑下半部分之上)
┊
最近的树 (最后画,覆盖角色)
对于建筑和角色混合的场景,统一按 col + row(或直接用屏幕 Y 坐标)排序后依次绘制,自然就形成了正确的前后遮挡。
五、完整渲染流水线
每一帧:
1. 清屏(填充背景色)
│
2. 计算可见网格范围(根据相机位置和缩放)
│
3. 绘制地面层
│ 遍历可见格子,逐行逐列
│ 根据类型铺菱形贴图(草地/道路/广场/水面)
│
4. 收集所有需要绘制的立体物体
│ 建筑、角色、NPC、树木……
│ 按 (col + row) 或屏幕 Y 排序
│
5. 按排序顺序依次绘制
│ 先画阴影 → 墙壁(暗面+亮面)→ 屋顶 → 装饰
│
6. 绘制 UI 层(固定在屏幕上,不随地图移动)
总结
概念 核心原理
视角 正交网格旋转 45° + Y 轴压缩 50%,菱形宽高比 2:1
投影 sx = (col-row)×W/2,sy = (col+row)×H/2,及其逆变换
地图 多层叠加:地面瓦片 + 道路参数化线段 + 区域矩形标记
建筑 地面菱形 → 向上挤出墙壁 → 光影分


面 → 加屋顶 → 加装饰
遮挡 按 col + row 从小到大绘制,后画覆盖先画
交互 屏幕坐标逆投影回网格坐标,判断通行性后移动角色
这套体系从 90 年代的《暗黑破坏神》《仙境传说》到现在的独立游戏一直在用,原理完全相同,区别只在于美术精度和优化手段。


