绘制

本部分 (以及下一节关于运动和控制的内容) 旨在为您提供 GML 或 GML 可视化的实用示例,使您能够尽快开始制作您的第一个游戏项目。我们不会太深入地解释事情,因为我们希望你尽快开始制作东西,所以我们鼓励你在进行过程中探索任何链接,并使用手册的 " 搜索 " 功能来寻找关于任何你不确定的东西的额外信息。

在本节中,我们将专注于将信息以文本和图像的形式简单地绘制到屏幕上,还将更多地解释不同的绘制事件,特别是主绘制 事件和绘制图形用户界面事件(请注意,在某些示例中,您将需要添加其他事件,但我们将在介绍这些事件时对其进行解释)。

The Draw Events

在继续之前,您可能希望从 开始页 创建一个新项目 (GML 或 GML 可视化),并添加 (或创建) 几个精灵以及一个或两个对象,因为我们将提供一些代码,您可以使用这些代码进行测试。即使是白色正方形现在也可以作为我们的对象的精灵!

现在,正如在对象和实例一节中提到的,如果您不将绘制事件添加到对象,则GameMaker将默认绘制,这意味着如果为对象指定了一个精灵,则将绘制该精灵,并完成已添加的所有变换。我们所说的变形是什么意思?嗯,每个对象都有许多内置的变量,它们将控制对象的实例在默认绘制时如何绘制其精灵,您可以在游戏运行时更改这些变量来更改绘制精灵的方式。

注意:您可以在此处找到可用于转换实例精灵的所有内置变量的列表。GML 可视化用户有一些影响这些变量的专用操作,您可以在此处找到这些操作,您还可以将实际变量本身与获取实例变量设置实例变量操作一起使用。

让我们来看一些例子:

更改 Alpha (透明度)更改 Alpha (透明度)

Alpha 值控制正在绘制的内容的透明度,在 GameMaker 中,您可以使用内置变量 image_alpha 更改指定的精灵的透明度。要了解这是如何工作的,请打开 (或创建) 一个对象,为其指定一个精灵,然后为该对象指定一个 创建事件 。在创建事件中,只需添加以下 GML 可视或 GML:

GML VisualDraw Example For Transparency

var _val = random(1);
image_alpha = _val;

图像 Alpha 的计算范围为 0 到 1 之间的值,其中 0 表示完全透明,1 表示完全不透明 (默认情况下设置为 1)。因此,在本例中,我们要做的就是将图像 Alpha 设置为从 0 到 1 的随机十进制值。将此对象的几个实例放置在房间中,然后单击 IDE 顶部的播放按钮 Play Icon 。

您应该看到该对象的每个实例使用不同的透明度绘制其精灵,例如:

Example Of Sprites Drawn With Different Alpha Values

 

更改颜色混合(调色)更改颜色混合(调色)

当您的对象是默认绘制一个精灵时,这个精灵实际上是用一种颜色来绘制的 混合 ( 或 着色 ),并且该颜色值存储在 image_blend 内置变量中。默认情况下,此颜色为白色,这基本上意味着当精灵显示在屏幕上时,不会添加任何颜色。但是,您可以使用其他颜色来实现特殊效果,例如,使用红色来表示实例受到了一些损害。

在本例中,我们将在按住某个键的同时将不同的颜色与精灵混合,因此您需要打开(或创建)一个对象,为其指定一个精灵,然后为该对象指定一个按下键<空格>事件

Add Key Down Event

在此按下键事件中,添加以下 GML 可视或 GML:

GML VisualExample Using Key Down Event

var _col = choose(c_red, c_green, c_blue, c_yellow, c_fuchsia, c_orange);
image_blend = _col;

将此对象的几个实例放置在房间中,然后单击IDE顶部的播放按钮 Play Icon,并测试按住并松开空格键。您应该会看到,按住按键的同时,每个实例都会快速更改其颜色,并在释放时停止更改:

Example Showing Colour Blending

 

更改比例更改比例

我们可以为精灵更改的另一个属性是 比例 值,允许我们随时根据需要将其绘制得更大或更小。比例是由两个独立的变量沿 X 和 Y 轴独立计算的,即 image_xscale 变量和 image_yscale 变量。默认情况下,这些值设置为 1,它们的作用类似于 倍增 ,因此值 0.5 将是比例的一半,值 2 将是比例的两倍。

重要! 使用这些变量更改指定的精灵比例也会更改边界框的大小以匹配,这意味着精灵的碰撞检测区域也将缩放。

在本例中,我们将使用一些简单的数学运算来使一个实例在循环中上下缩放精灵。首先,打开(或创建)一个对象,为其指定一个精灵,然后为该对象指定一个创建事件。在这种情况下,添加以下内容:

GML VisualSet Variable Example

timer = 0;

现在向对象添加一个步事件,如下所示:

GML VisualActions To Change Sprite Scale

timer = timer + 1;
var _val = dsin(timer);
image_xscale = 1 + _val;
image_yscale = 1 + _val;

在这里,我们使用数学函数 dsin() 通过定时器变量生成一个介于 -1 和 1 之间的值,然后将其应用于刻度变量。在将一些实例放置到房间中并按下 播放 按钮 Play Icon 后,您应该会看到这些实例是如何从 0 的比例缩放到 2 的比例,然后再缩放回来的。

最后一件事 ..。将 "image_yscale" 部分更改为 "1-_val",看看会发生什么!

 

 

上面的例子只是说明了当 GameMaker 是默认绘制时,您可以操作对象精灵的许多方法中的一部分,但是如果您想要为一个对象绘制多个东西怎么办?在这些情况下,您需要使用 绘制事件 来显式地告诉 GameMaker 要绘制什么,这就是我们将在以下示例中执行的操作。

将两个(或更多)精灵绘制在一起将两个(或更多)精灵绘制在一起

在本例中,您需要两个精灵和一个对象。调用精灵 "spr_One" 和 "spr_Two",然后将 "spr_One" 原点居中,对于 "spr_Two",将其原点设置为左中:

Show Origins For Sprites将第一个精灵 ("spr_one",中心原点) 分配给您创建的对象,然后添加一个 创建事件 。在创建事件中添加以下 GML 可视化或 GML:

Set Draw Angle Variable In DnD

draw_angle = 0;

我们将使用该变量随时间旋转 "spr_Two",并将其绘制在分配给对象的精灵上 ("spr_One")。为此,我们需要向对象添加一个 绘制事件 。通过这样做,我们告诉 GameMaker 我们希望接管实例绘制的内容,这意味着我们的代码将包括对 draw_self() 函数或 绘制自身 操作的调用。此操作只是复制对象在不存在绘制事件时所做的操作,并且它是默认绘制指定的精灵。然后,我们将绘制第二个精灵,我们希望将其用作旋转的叠加精灵。GML 可视和 GML 如下所示:

Draw Two Sprites With DnD

draw_self();
draw_angle = draw_angle + 0.5;
draw_sprite_ext(spr_Two, 0, x, y, 1, 1, draw_angle, c_red, 1);

将该对象的多个实例添加到房间编辑器中,然后按下 IDE 顶部的 播放 按钮 Play Icon。如果一切正常,您现在应该看到如下所示:

Animation Drawing Two Sprites Together

在我们离开这个例子之前,让我们稍微调整一下,让它指向鼠标位置,而不是简单地旋转 "spr_Two"。为此,我们需要将绘制事件 GML 可视化或 GML 更改为如下所示:

Edited Draw Code For Drawing Two Sprites With DnD

draw_self();
draw_angle = point_direction(x, y, mouse_x, mouse_y);
draw_sprite_ext(spr_Two, 0, x, y, 1, 1, draw_angle, c_red, 1);

再次运行该项目,这一次您将看到非常不同的东西!

Animation Drawing Two Sprites Pointing At Mouse精灵现在指向鼠标,无论你将它移动到哪里!正如你所看到的,分层精灵是一种很好的方法来给对象添加细节,或者让一些东西独立于指定给对象的基础精灵移动,这是一个强大的工具,你可能会在你自己的项目中大量使用。

 

绘制精灵以外的东西绘制精灵以外的东西

您也可以在绘制事件中绘制精灵以外的对象,如文本或形状。在本例中,我们将使用 GML 可视化或 GML draw_self() 函数来绘制对象精灵,但我们还将绘制一些其他内容,从一些 文本 开始。在本例中,您将需要一个精灵和一个对象 (为其指定了精灵)。在对象中,首先使用此 GML 可视化或 GML 添加一个 创建事件

Setting Variables Using DnD

name = choose("Fred", "Jonas", "Sharon", "Kate", "Frank", "John", "Monica", "Amanda");
number = irandom(100);

所做的只是告诉 GameMaker 从列出的名称中选择一个并将其赋给一个变量,并为该对象的每个实例生成一个从 0 到 100 的随机数。我们希望将这些值绘制到屏幕上,因此您现在需要添加一个 绘制事件 ,并在其中添加以下 GML 可视或 GML:

Drawing Text Using DnD

draw_self();
draw_set_halign(fa_center);
draw_text(x, y + 32, "My name is " + name);
draw_text(x, y + 48, "My number is " + string(number));

您会注意到,在上面的代码中,我们使用 string() 函数或 数值转字符串 对要绘制的 "number" 变量进行字符串操作。这是因为所有文本都必须由 字符 组成,而不是值,因此我们需要使用此函数 / 操作将数值转换为我们想要绘制的字符。在本例中,我们将获取我们生成的随机数,并将其转换为可以绘制的 " 字符串"。另请注意,我们设置了文本 对齐方式 。这只是告诉 GameMaker 相对于给定位置从哪里开始绘制文本,在本例中,我们希望文本沿 x 轴居中。

将该对象的多个实例添加到工作室编辑器中,然后按下 IDE 顶部的播放按钮 Play Icon 。您应该会看到类似这样的内容:

Sprites Being Drawn Along With Text

在到目前为止的所有示例中,我们都绘制了分配给实例的精灵,但情况并不总是如此。您可以在绘制事件中绘制任何您想要的内容,而不管指定的精灵是什么。为了说明这一点,我们将更改当前拥有的代码,方法是删除 draw_self() 调用,并替换为绘制彩色椭圆的函数,如下所示:

Drawing Shapes Along With Text Using DnD

draw_ellipse_colour(x - 50, y - 32, x + 50, y + 32, c_fuchsia, c_lime, false);
draw_set_halign(fa_center);
draw_text(x, y + 32, "My name is " + name);
draw_text(x, y + 48, "My number is " + string(number));

再次运行该项目,您应该会看到以下内容:

Example Of Drawing Shapes And Text Together

需要注意的一点是,即使我们没有绘制指定的精灵,它仍将用于碰撞检测。因此,虽然您可能正在绘制一件东西,但碰撞仍将基于指定的精灵计算,就像它与实例一起放置在房间中一样,即使它不可见。这实际上很方便,因为这意味着你可以绘制不同的精灵,但基于指定的精灵维护一个单一的碰撞遮罩。还请注意,您仍然可以应用不同的变换,如X/Y比例,碰撞将基于更改的大小,即使没有绘制任何内容来显示这一点。

 

 

GUI 层

我们在页面顶部提到,我们将讨论 绘制 GUI 事件 以及绘制事件,现在让我们来看看这一点。绘制图形用户界面事件作用于名为 图形用户界面 的东西,它是在房间中的实例上绘制的具有固定宽度和高度的特殊绘制层。GUI 层的好处是它不会随着房间摄像头移动,所以它是添加静态图形用户界面项目的理想位置,比如分数、健康条和其他你的游戏需要与用户交流的信息。您可以从手册的 绘制事件  部分找到有关图形用户界面层的更多信息。

注意:房间可以比屏幕大,所以你可以有很大的关卡供玩家走动。这意味着在房间编辑器中(或在代码中),您需要定义一个跟随游戏动作的相机。这基本上是一种根据玩家在房间中的位置来设置屏幕的固定区域来显示较大房间的不同部分的方式,并在许多游戏中使用。想想看,在马里奥或塞尔达这样的经典游戏中,人们的视角总是跟随着主角。这是用相机完成的。有关更多信息,请参阅手册的房间编辑器部分中的房间属性一节。

下面的示例都将使用绘制图形用户界面事件,因此您需要创建一个对象并将该事件添加到其中。注意,对象不需要指定精灵,因为我们不想默认绘制任何东西,也不需要它来检测碰撞。像这样只为绘制东西或控制游戏某些方面而设计的对象通常被称为控制器对象。还要注意,我们将对所有示例使用相同的对象,因此我们建议您逐一查看它们(尽管这并不是绝对必要的)。

Draw GUI Event In An Object 绘制文本绘制文本

当绘制到图形用户界面层时,左上角是原点位置,右上角是 +X,下是 +Y。这使得定位文本和图形非常容易,如您将在本例中看到的。我们在这里要做的就是提取一个表示球员得分的值,因此在我们的对象中,我们需要添加一个 创建事件 来初始化一个变量来保存该值,如下所示:

Defining A Variable Using DnD

player_score = 0;

我们还希望向对象添加一个键盘按下<空格键>事件,因为每次按空格键时,我们都会使用该事件来增加分数。

Adding A Space Key Pressed Event

在这种情况下,添加以下内容:

GML VisualActions In The Space Key Event

var _val = irandom(100);
player_score = player_score + _val;

最后,让我们在绘制 GUI 事件中绘制分数值,如下所示:

在这种情况下,添加以下内容:

Drawing Text To The GUI Layer Using DnD

draw_set_halign(fa_left);
draw_set_colour(c_yellow);
draw_text(32, 32, "SCORE:");
draw_set_colour(c_white);
var _str = string(player_score);
draw_text_transformed(32, 48, _str, 2, 2, 0);

您将注意到我们如何使用硬编码(或固定的)值来表示要绘制的文本的 X/Y 位置,因为在绘制到图形用户界面层时,我们不需要它相对于任何实例。我们还使用了"设置颜色"功能来更改文本的颜色,以及使用"转换"功能来使实际的得分值更大,这说明了如何在自己的游戏中自定义文本元素。

立即将此对象的单个实例添加到您的房间,然后按播放按钮Play Icon。当游戏运行时,按下并松开<空格键>,您应该会看到分数值增加。

Animation Showing Text Being Drawn To The GUI Layer

 

绘制精灵绘制精灵

在本例中,我们将使用图形用户界面层来绘制一些精灵。最明显的用处是画出玩家的生活,所以让我们继续这样做吧!在本例中,您需要一个精灵 -- 它应该大约是 64x64 像素 -- 但是它不应该被分配给对象,因为我们将自己绘制它。

首先,我们需要向创建事件中的对象添加一些新变量(如果您已经完成了前面的示例,请在下面添加已有的内容):

Defining Variables Using DnD

player_lives = 3;
gui_w = display_get_gui_width();

在这段代码中,我们为 player_lives 初始化了一个变量,但我们还创建了一个变量来保持 GUI 层的宽度,这样我们就可以相对于屏幕的右侧正确地定位东西。我们可以只将一个值硬编码到代码中并使用它,但这意味着如果我们对房间的大小进行任何更改,或者如果我们添加摄像头等……。稍后,我们需要遍历代码并在任何地方更改值。相反,使用 display_get_gui_width() 函数意味着我们不需要担心任何类似的未来更改,因为代码将自动适应图形用户界面层最终的大小。

接下来,我们要向对象添加一个按下键盘回车的事件,因为我们将使用该事件来更改每次按下回车键时的生命数:

Adding An Enter Key Pressed Event

在这种情况下,添加以下内容:

GML VisualIn The Enter Key Down Event

player_lives = player_lives - 1;

if (player_lives < 0)
{
player_lives = 3;
}

最后,我们需要将精灵画到显示器上。为此,我们将使用 "for" 循环 (使用 GML 在这里 和 GML 可视化 在这里 的信息),以及将所有内容放置在屏幕右上角的图形用户界面宽度变量。因此,将其添加到绘制 GUI 事件中 (在前面的示例中可能具有的任何其他操作之后):

GML VisualActions To Draw Sprites To The GUI Layer

for (var i = 0; i < player_lives; i += 1)
{
var _xx = gui_w - 48 - (i * 70);
draw_sprite(spr_Heart, 0, _xx, 48);
}

如果您尚未将此对象的实例添加到房间,请立即添加它(只有一个!),然后按播放按钮Play Icon。游戏运行后,按下<回车>键不同的次数即可看到生活的变化。

Animation Drawing Sprites To The GUI Layer

在您离开这个例子之前,您应该试验一下生命的数量,看看会发生什么。目前它设置为 3,但更改创建事件和按键事件以将值设置为 5 或 10...。如果你做的每件事都是正确的,那么代码应该会调整并正确地绘制它们!

 

绘制健康条绘制健康条

最后一个示例介绍如何将健康条绘制到 GUI 层。有很多方法可以做到这一点,但 GameMaker 有一个专门用于制作健康条的内置功能,所以这就是我们在这里使用的,尽管你也可以使用精灵或形状来创建自己的功能。首先,与前面一样,我们需要初始化一个变量来保存健康值,因此将以下 GML 可视或 GML 添加到对象的 创建事件 中 (在可能已经存在的任何其他代码之后):

Defining A Variable Using DnD

player_health = 100;

我们希望使用箭头键根据按下的箭头键来向上或向下更改健康值,我们可以通过添加两个按下键盘的 箭头 事件来实现这一点,但是使用 步事件 和一些代码来检查按键可能更容易,所以现在使用以下 GML 可视化或 GML 继续添加一个 步事件

Step Event GML VisualActions

if (keyboard_check(vk_up))
{
    if (player_health < 100)
    {
        player_health = player_health + 1;
    }
}

if (keyboard_check(vk_down))
{
    if (player_health > 0)
    {
        player_health = player_health - 1;
    }
}

完成这些工作后,我们实际上可以开始绘制健康条,这是在绘制 GUI 事件中完成的,添加以下内容 (在已有的任何内容之后):

GML VisualFor The Draw GUI Event To Draw A Healthbar

var _xx = display_get_gui_width() / 2;

draw_healthbar(_xx - 50, 24, _xx + 50, 40, player_health, c_black, c_red, c_lime, 0, true, true);

如果您尚未将此对象的实例添加到房间中(但只有一个!),然后按下播放按钮Play Icon。游戏运行后,按<向上箭头><向下箭头>键可查看健康状况的变化。

Animation Of Drawing A Healthbar

 

我们希望在做完这些例子之后,你在使用 GameMaker 时会有更多的信心,对它的工作原理有更多的了解。下一节将探讨如何让这些你一直在画的东西在房间里移动,以及接受和响应用户的输入。