为什么要使用视野

有时候,我们会需要设计一个很大的房间,譬如设计了一个 4800x720 的房间,这个房间太大了,我们当然不可能直接把整个房间摆在屏幕上给玩家看,而是得根据角色的位置动态控制展示一部分房间给玩家,如下图所示:

Example

这就是本章所讲解的视野(view)所要实现的功能。

视野设置

选择房间左边的“视野”一项,进入视野设置。

首先,必须要勾选“激活视野使用”才能使用视野。你也可以在代码中使用 view_enabled = true; 来开启,或 view_enabled = false; 来关闭。

Enable

可以看到,一个房间一共支持 8 个视野(View 0 ~ View 7)。一般情况下,你需要为其中某一个(通常是 View 0)勾选“当房间开始时可见”,只有勾选了这个选项的视野才能被应用在房间中(可以使用代码 view_visible[0] = true; 来开启,当然也可以 if (view_visible[0] == true) 来判断是否开启)。

有一点需要清楚,房间可以同时开启多个视野(即多个视野勾选“当房间开始时可见”),如下图就是同时使用了两个视野:

Multiple View

双视野在游戏设计中经常出现,比如同机双人游戏,例如 4399 里的双人旋转赛车(童年回忆啊),需要在两个视野内跟随两个不同的 player。

现在来看到视野的设置。

房间视野

房间视野用来决定视野在房间中的位置。四个参数与 GM 内置变量的关系:

  • X -> view_xview[..]
  • Y -> view_yview[..]
  • W -> view_wview[..]
  • H -> view_hview[..]

也就是说,代码 view_xview[1] = 100; 等效于在房间的视野设置中,给 View 1 的“房间视野”部分的 X 设置值为 100。四个参数的作用如下,当运行游戏时,窗口内只显示 view 这个区域的内容。

View Setting

地震效果就可以通过在步事件或计时器事件中写

1
2
view_xview[0] = random(30) - 15;
view_yview[0] = random(30) - 15;

来实现。

屏幕输出

“房间视野”决定了显示房间的哪些部分,而“屏幕输出”则决定了视野如何在窗口中显示。屏幕输出的四个参数与 GM 内置变量的关系:

  • X -> view_xport[..]
  • Y -> view_yport[..]
  • W -> view_wport[..]
  • H -> view_hport[..]

其作用如下图所示(图 1 为视野,图 2 为游戏窗口,为了方便理解,将房间背景色换成了红色):

View Output

Output

如图所示,有色彩的区域就是视野从房间中截取的那部分内容,view_xport[..]view_yport[..]会决定这个视野的左上角显示在窗口的什么位置,而 view_wport[..]view_hport[..]view_wview[..]view_hview[..] 相对应,用来控制视野的缩放。

在使用双视野或者更多的视野的时候,就要通过控制“屏幕输出”来安排各个视野在窗口中的位置及大小。

视野跟随物体

如果要像本章第二张图那样,视野跟随角色的移动而移动的话,那么最好的办法就是将“视野跟随物体”设置为跟随 objPlayer。

在下面还有四个参数,他们与 GM 内置变量的关系:

  • Hbor -> view_hborder[..]
  • Vbor -> view_vborder[..]
  • Hsp -> view_hspeed[..]
  • Vsp -> view_vspeed[..]

view_hborder[..]view_vborder[..] 表示当角色距离窗口边缘多远时开始跟随。如果设置为 0,那么当角色走到窗口的边缘的时候,视野才会开始跟随角色,并保持角色处于窗口边缘的位置,如果超过了视野大小的一半,那么视野一直处于跟随状态,角色将始终保持在窗口正中心(除非碰到了房间边缘)。

view_hspeed[..]view_vspeed[..]限制视野的移动移动速度,设置为 -1 表示不限制。限制视野的移动速度小于角色的运动速度,在角色速度较快时可以避免画面移动过快。

视野的旋转

GM8 有一个内置变量 view_angle[..] 用来控制视野的旋转,使用方法类似于 image_angle,视野旋转总是以视野中心为旋转中心进行旋转的。

视野与绘制事件

如果你使用了多视野,那么每一步的末尾,每一个视野都会调用一次所有实例的绘制事件。举例来说,如果你使用了双视野,每一步每一个实例都会重复调用两次绘制事件。

这也是为什么之前强调不应该在绘制事件中实现绘制以外功能的原因之一,如果你使用了双视野,在绘制事件中令某一个变量自增 1,实际上它每一步都增加了 2,这就和期望相违背了。

常见误区与 view_current

由于 view_系列变量不写数组符号也是可以正常运行的,比如:view_xview = 0; 是不会报错的,所以就有很多 GMer 会陷入一个误区,以为不带数组符号的 view_系列变量代表正在使用的视野,即,认为如果正在使用 View 3,那么 view_xview 等效于 view_xview[3]。但是这是一个天大的误解,之所以不写数组符号也不会出错,原理在我数组中提到过了,GM8 将一切变量与它的 0 号元素视为等效,即 aa[0] 完全等效,因此,即使使用的是 View 3,view_xview 代表的还是 view_xview[0]

view_current 返回当前正在使用的视野,不可改变,且只在绘制事件中有效,在其他事件中值都是 0。因为每一个视野都会调用一次绘制事件,所以可以用 if (view_current == xx) 实现在不同的视野中绘制出不同的图片或图案。