[上篇:序][下篇:地表的数据组织及滚屏]
斜视角图象的处理, 在程序设计上的一大难点在于它的世界中坐标反映在2D屏幕上
需要做一些变换.
Isometric Tile 游戏中的 X 轴一般是从左上指向右下,
沿 35 度角左右的方向(如果是 45 度视角的话), 每个 Tile 的底面在屏幕上看起来就象
菱形,整个 Tile 是一个六面体 (见右图). x 轴和 y 轴成 90 度.
这是个不错的角度, 但在设计 Isometric Tile 的时候, 更好的角度是 26 度 (arc tan 0.5),
对应的视角是 30 度. 看起来更扁一些, 32:15 的 Tile 设计随处可见(如左图),
因为 32 对计算机处理来说可是个很方便的数值.(所谓视角,
这里指视线和水平面的夹角, 特别的, 游戏中大多采用的都是俯视的视角,
如果你需要将坐标轴同水平线的角度转换为视角,可以将其取 tg,再来次 arc sin)
在 Isometric Tile Engine 的设计中, 使用什么角度的视角并不重要,
程序代码基本相同,只对于美工是不同的. 但是经过这几天的思考,
我发现斜视角(非 Tile) 的引擎设计中如果能采用比较合适的角度,
引擎的速度将有很大的提高, 这个最合适的角度就是 37 度 (arc tan 0.75)
视角大约 48 度. 在这个角度下, 游戏中的 X, Y 轴, 和屏幕上 X,Y 轴的转换关系正好为
勾三股四弦五的关系, 这在我们需要的大量坐标转换的工作中提供了加速运算的可能 ;-)
游戏中的 X 轴上一个单位,相当于屏幕 X 的 0.8 个单位, Y 的 0.6 个单位的变化.
游戏中的 Y 轴上一个单位,相当于屏幕 X 的 -0.8 个单位, Y 的 0.6 个单位的变化.
就是说我们的 Sprite 在游戏中移动 aX+bY, 在屏幕上就移动了 0.8(a-b)X+0.6(a+b)Y
现在让我们来看看屏幕, 假如我们选择 640x480 的分辨率. Aha, 640:480=4:3
就有这么好的事 ;) 那么在游戏坐标系中的一条水平线正好是屏幕的对角线,
这使得判断游戏世界中的一个坐标点是否在屏幕区域内变的很简单 ;-) 请看左图,
外菱形框是游戏世界中的一矩形部分,中间的矩形框表示屏幕区域. 我们的屏幕坐标
从左上角的 (0,0) 到右下角的 (639,479) 为了好说明问题, 将游戏世界的坐标原点
也定在屏幕的左上角, ok, 现在来算一下屏幕四个角对应的游戏世界的坐标.
由于屏幕对角线长 800, 那么右上角的坐标是 (400,-400); 左下角是 (400,400);
右下角是 (800,0). 决定一个点是否在屏幕内的根据是 0≤X+Y≤800,
就这么简单.
最后谈谈引擎设计时的优化, 我们在坐标变换时, 使用最多的运算是除5.
而除法指令是最慢的, 有没有办法优化呢? 针对我们的作用数值并不是很大的情况
这个运算可以达到最快的速度. 即用 *205/1024 代替 /5
而 205=(1+5*8)*5 , 386 以上的 CPU 计算 *5 *8 等都可以利用 LEA 指令,
非常的快. 右移 10 位就可以代替 /1024, 这个不用我多说了吧 ;-)
当然现在的 C 语言编译器将优化选项开到最大时, 会自动帮你做优化,
不用你写内嵌汇编的. 如果实在是想自己写,大概是这么几行:
mov edx,eax ; eax 里是被除数 a lea eax,[edx+4*edx] ; eax = 5*a lea eax,[edx+8*eax] ; eax = a+8*eax = 41*a lea eax,[eax+4*eax] ; eax = 5*eax = 205*a sar eax,10 ; eax = 205*a/1024注意:如果用 C 语言写, 最好写将 /1024 直接写成 >>10, 虽然 /1024 会被优化成右移操作, 但除法是有四舍五入的, 所以编译器在优化时,将多考虑些东西,而多几条指令.
担心计算的精度吗? 大可不必, 205/1024=0.200195 就是说, 一个点有 0.000195 的误差, 这样,即使积累到 800 个点 (屏幕的对角线,就是最长的线啦) 也才 0.17 点的误差, 而屏幕上的坐标是整数的,所以没有影响. 你可以很容易的验证, 就算使用 1280x1024 的分辨率也是没有问题.