绘制事件

绘制事件 管理游戏运行时你在屏幕上看到的内容,它分为多种独立事件来满足你游戏绘图的不同需求。 下图说明了每个事件的执行顺序:物体编辑器绘制图标 普通 绘制 事件有 3 种子事件类型: 绘制开始、标准 绘制绘制结束 事件。通常,你只需要使用基础 绘制事件,需要注意的是,所有房间中的实例,在游戏中每步都会触发这个事件。所以, 只要勾选这个实例 可见 复选框,这个事件就会一直被调用。即使你没有在物体属性中为这个事件定义任何内容(例如:无代码,无动作),只要这个物体被指定了精灵,它就 依然 会触发绘制事件。这是因为 GameMaker Studio 2 在处理绘制事件时有两种绘制方式:

其余的绘制事件将在下面列出的部分中进行说明:

除了主要的 绘制 子事件外,你还有一个 开始绘制绘制结束 子事件。这些动作与标准 绘制 子事件完全相同(即:它们将绘制游戏的每一步和所有视图中的任何内容),但如果没有添加到物体,它们不会 “默认绘制” 任何内容,它们将始终在标准 绘制 子事件之前 / 之后运行。因此,你将拥有所有实例的 开始绘制(Draw Begin) 步骤,然后是所有实例的 绘制(Draw),最后是所有实例的 绘制结束(Draw End)步骤。

通过这种方式,你可以在一个实例的开始绘制步骤中绘制内容或设置绘图属性,并确保具有标准绘制事件或绘制结束事件的所有实例都将使用这些属性或绘制第一个实例绘制的内容。本质上来说它能确保你能在特定时间绘制特定东西,就像步开始(Begin Step)和步结束(End Step)事件一样。

GameMaker Studio 2 中绘制内容时,有几件事需要注意,无论是绘图的精灵还是着色器,还是 3D:

  • 绘制事件是一个非常密集的事件,因为它是占用大部分时间和资源的事件之一......为此,除了绘图之外,在绘制事件中做任何事情都不是一个好主意。因此,在步事件或计时器或任何其他适合的事件保存大型代码或复杂操作,保留绘制事件用于绘图是很清晰的,因为它是最适合的。

  • 如果你的物体将可见(visible)参数设置为否(off,以便不绘制物体的实例),则会跳过所有绘制事件(窗口大小调整 事件除外)。这意味着使实例不可见将 阻止放置在这些事件中的代码运行,因此如果它们不可见,则不要将基本代码放在绘制事件中。

  • 你绘制的内容与你选择的碰撞引擎(传统或物理)无关,因为它是由物体属性和给定物体的精灵(或遮罩)定义的。

绘制 GUI(Draw GUI) 子事件类型属于 绘制事件类别,专门用于绘制不受视图比例或旋转影响的 GUI(图形用户界面)元素。这意味着你可以让实例绘制 HUD 的所有元素,而不必将元素的所有定位基于房间内的实例位置或当前视图的位置。

在这些事件中绘图时,重要的是要了解即使视图处于活动状态时绘制坐标也不会改变,并且 (0,0) 始终 是应用程序表面或所展示的东西(例如一个精灵)的左上角(请参阅本节的底部),应用程序表面的默认宽度和高度是 1:1。深度排序仍然保持在不同层上的不同实例之间(因此较低层上的实例将在较高层之后绘制)并且也在事件本身内,因为 开始绘制 GUI(Draw GUI Begin) 子事件将首先为所有实例绘制,然后标准的 绘制 GUI(Draw GUI) 将为其绘制所有实例,最后触发 绘制 GUI 结束(Draw Gui End) 子事件。

通过这种方式,你可以在一个实例中在 开始绘制 GUI 中绘制内容或设置绘图属性,并确保具有标准 绘制 GUI绘制 GUI 结束 子事件的所有实例都将使用这些属性或绘制第一个实例具有的内容画。基本上它是确保在特定时间绘制某些东西的确定方法,就像 步开始步结束 子事件一样。

这些事件也可以与普通的 绘制 子事件一起使用(它将受到视图位置、比例和正常旋转的影响)。如果你没有 绘制事件,但你确实有 绘制 GUI 事件,那么 GameMaker Studio 2 仍会默认为实例绘制精灵(如果它有一个)。

与其他绘制子事件相关,绘制 GUI 事件将始终绘制在正常绘制事件中绘制的任何内容。因此,如果你在较低层上有一个带有 绘制 GUI 事件的实例,它将使用常规绘制事件绘制更高层上的实例。如果两个实例都具有 绘制 GUI 子事件,则将遵循图层顺序。

注意:默认情况下,此事件将使用应用程序表面大小绘制 1:1,通常是房间大小或视口。这意味着当你在 游戏选项 中进行 宽高比校正 时,GUI 不会被绘制在游戏 “宽银幕” 的黑框上。可以使用 display_set_gui_maximise 函数关闭此行为,还可以将 GUI 事件锁定为特定大小,然后使用函数 display_set_gui_size 自动缩放以适应显示或应用程序表面尺寸。

绘制预处理(Pre Draw)绘制后处理(Post Draw) 子事件是 绘制事件 类别的一部分。但是,与其他绘制事件不同,它们直接绘制到屏幕缓冲区,这将是当前可见的所有视图的组合屏幕空间的大小,或者是你当前唯一使用的窗口的大小。 下图说明了这一点:Object Editor Post Draw 因此,如果你正在使用绘制 处理事件,则你将绘制到全屏渲染目标,该目标的大小与所有视图所适合的窗口大小相同。 如果你没有活动的视图,则将其设置为窗口本身的大小。

绘制预处理 子事件在任何其他绘制事件之前触发,在其中你可以设置值,设置绘制属性甚至绘制内容而无需担心 GUI 层的视图或大小(GUI 层的大小可能与屏幕缓冲区相同,但可能不一样,因为你可以在代码中设置 GUI 分辨率)。

值得注意的是,此事件发生在清除屏幕缓冲区之前,这意味着如果你未在房间编辑器中关闭视图清除,则将看到 绘制预处理 事件中绘制的任何内容,然后第一个视图将清除它。如果你希望能够自己查看视图,或者根本没有使用视图,那么你还应该在 房间编辑器 中将背景颜色设置为透明度为 0。

注意: 如果你关闭这些选项,你可能会注意到在测试游戏时屏幕上绘制了不需要的假象(例如来自实例的 “踪迹”)。这是因为你直接绘制了绘制缓冲区的前一帧而不清除它。但是你可以使用 draw_clear_alpha 自己完成此操作。

绘制后处理 子事件在标准绘制事件之后但在绘制 GUI 事件之前触发。与绘制预处理事件一样,它基于屏幕缓冲区大小的大小,并且放置在绘制 GUI 事件之前,使你能够简单轻松地在全屏的基础上执行后处理效果和其他事物,而不会干扰任何事件。你可能在游戏中拥有的 HUD / GUI 元素。

此事件类型属于 绘制事件 类别,虽然它实际上并未绘制任何内容,但它确实对绘制画布中的更改做出了反应 - 具体来说,它是为在游戏窗口 “snapped(突然变化)” 时响应 UWP 画布大小的变化而设计的。

在 UWP 目标平台上,重要的是从游戏窗口的 “snapping” 中捕获游戏画布的大小(例如,当用户将窗口拖动到显示器的侧面时)。 此事件将执行此操作并在每次更改画布时触发,允许你在此处添加自定义代码,以调整视图大小或根据需要重新定位 HUD 元素。提供此函数是一种方便的方法,可以避免使用步事件代码来检查这些事情。

注意: 你无法在这个事件中绘制!它是通过调整画布大小来触发的,仅用于捕捉这个变化......任何应该完成的绘图仍然必须在其他一个绘制事件中。