用Perl设计桌面游戏

桌面游戏比以往任何时候都要受欢迎。事实上,桌面游戏市场在过去一年增长了25%,而视频游戏市场则萎缩了20%。但你是一名Perl黑客,而不是Adobe Illustrator,你该如何设计桌面游戏呢?嗯,这正是我在这篇文章中要展示的内容。

首先,你需要一个想法。你可以将任何东西变成游戏。无论 只是 想要 设计 你自己的 定制 卡片还是 想要 制作 一个 贸易舰队或者 制作 一副 完整的 定制 游戏板 卡牌 游戏选择 无限 可能 。(完全披露:我是The Game Crafter的股东之一,该网站完全是用Perl编写的。)

为了本文的目的,我将制作一个基于流行的Perl网络游戏The Lacuna Expanse的桌面游戏版本。(我也是Lacuna的股东之一。)我选择这个游戏是因为我已经有了一些相关的艺术作品,尽管它们不是桌面游戏的形式。然而,你可以在网络上的各个网站免费获取艺术作品

我的基于Lacuna的桌面游戏将是一款拼图放置游戏,所有玩家将合作防御外星人的入侵。

让我们直接进入Perl吧!

CPAN上有几个优秀的图像处理库,但我个人最喜欢的还是Image::Magick。我首先创建了一个基础图像,可以按任何我想要的方式对其进行操作。(我的选择基于The Game Crafter的组件尺寸和价格列表。)我决定使用迷你卡片,因为如果使用完整的扑克牌大小卡片,桌子会很快被填满;桌上有许多卡片!

 my $card = Image::Magick->new(size=>'600x825');
 say $card->ReadImage('canvas:white');

请注意,我在ReadImage调用前使用了say。如果出现任何错误,Image::Magick将在每个调用时抛出一个文本异常。我可以轻松地用更好的错误处理来包装它,但现在将内容打印到屏幕上已经足够满足我的需求了。当打印内容时(真的是打印,包括所有墨水)你还得考虑一个叫做出血和裁剪线的东西。在卡片上用红色画裁剪线作为可打印图像内容的边界很容易。

 say $card->Draw(stroke=>'red', fill => 'none', strokewidth=>1, primitive=>'rectangle', points=>'38,38 562,787');

带有裁剪线的空白到目前为止一切顺利。下一步是为这张卡片添加背景,使其看起来像一张卡片。为此,我将从Lacuna Expanse的行星表面图像中选择一张,然后将其旋转并拉伸以适应卡片的形状。

 my $surface = Image::Magick->new;
 say $surface->ReadImage('surface-p17.jpg');
 say $surface->Rotate(90);
 say $surface->Resize('600x825!');
 say $card->Composite(compose => 'over', image => $surface, x => 0, y => 0);

注意Resize命令中的感叹号(!)。这告诉Image::Magick扭曲图像的原始宽高比。换句话说,将图像拉伸到指定的大小。

背景你可能注意到这张图片看起来很大。这是因为它是为打印(在纸上!)而不是屏幕准备的。打印的像素密度比屏幕高,所以当你将其显示在屏幕上时,图片看起来更大。

现在这张卡片需要一个标题。向图像添加文本是直截了当的。

 $card->Annotate(text => 'Mayhem Training', font => 'ALIEN5.ttf', y => -275, fill => 'white', pointsize => 70, gravity => 'Center');

标题如你所见,我使用了自定义字体。Image::Magick能够使用几乎所有OpenType或TrueType字体。

有了背景和标题,下一步就是在卡片上叠加来自视频游戏《混乱训练》的Mayhem Training建筑图片。

 my $image = Image::Magick->new;
 say $image->ReadImage('mayhemtraining9.png');
 say $card->Composite(compose => 'over', image => $image, x => 100, y => 165);

添加的图片现在我们终于有点样子了!这真的开始像一张卡片了。使用同样的技术将图标叠加到卡片上。在许多游戏中,这些图标象征着卡片赋予使用者的能力。你可以从网络上到处免费获取图标;我最喜欢的库之一是Glyphish

 my $icon = Image::Magick->new;
 say $icon->ReadImage('target.png');
 say $card->Composite(compose => 'over', image => $icon, x => 100, y => 570);

添加的图标你不能总是用图标;一些文字将向新手解释这些。如果不使用Gabe Schaffer很久以前贡献给ImageMagick论坛的一些非常棒的代码,给卡片添加一些说明将是非常困难的。基本上,没有这段代码,你必须自己设置文本在单词边界处的换行,但有了它,你只需进行一个简单的Annotate调用,就像这样

 $card->Set(font => 'promethean.ttf', pointsize => 35);
 my $text = 'Demolish one of your buildings to use this ability.';
 my $text_wrapped = wrap($text, $card, 400);
 say $card->Annotate(text => $text_wrapped, x => 100, y => 690, font => 'promethean.ttf', fill => 'white', pointsize => 35);

添加的文本如果玩家可以放置任何卡片在任何他们想要的地方,这种类型的游戏就不会很有趣。为了解决这个问题,我想在卡片上添加一些东西来指示其他卡片如何与之连接。这是最具挑战性的部分,因为我想要制作一个半圆形/半矩形连接器。由于这有点复杂,我想用它来在卡片的各个侧面绘制连接点,所以我将其转换为一个子程序。

 sub draw_connection_point {
   my ($card, $color, $rotation, $x, $y) = @_;

   # draw a half circle, it's a half cuz we're drawing outide the image
   my $half_circle  = Image::Magick->new(size=>'70x35');
   say $half_circle->ReadImage('canvas:transparent');
   say $half_circle->Draw(stroke => $color, fill => $color, strokewidth=>1, primitive=>'circle', points=>'35,35, 35,70');

   # create the connection point image
   my $connection = Image::Magick->new(size=>'70x85');
   say $connection->ReadImage('canvas:transparent');

   # add the half circle to the connection point
   say $connection->Composite(compose => 'over', image => $half_circle, x => 0, y => 0);

   # extend the connection point the the edge
   say $connection->Draw(stroke=>$color, fill => $color, strokewidth=>1, primitive=>'rectangle', points=>'0,35 70,85');

   # orient the connection point for its position
   say $connection->Rotate($rotation);

   # apply the connection point to the image
   say $card->Composite(compose => 'over', image => $connection, x => $x, y => $y);
 }

 draw_connection_point($card, 'purple', 0, 265, 740);

添加的连接有时,向玩家提供有关物品的提示,以便他们可以制定更好的策略,这是很不错的。为此,我在标题上方添加了一系列的圆点,以指示牌组中有多少张这张卡片。在这种情况下,这张卡片是独一无二的。

 my $quantity = 1;
 my $pips = '.' x $quantity;
 say $card->Annotate(text => $pips, y => -340, fill => 'white', pointsize => 70, gravity => 'Center');

完成记得在保存文件之前移除裁剪线。

 #say $card->Draw(stroke=>'red', fill => 'none', strokewidth=>1, primitive=>'rectangle', points=>'38,38 562,787');
 say $card->Write('mayhem.png');

cut lines removed

理由

现在我已经向你展示了如何创建卡片,你可能会有一个疑问。为什么你愿意花时间去编码它,而不是直接使用 Photoshop 或 Gimp 呢?有许多原因可以编码它,包括你可能不知道如何使用图像编辑器。然而,真正重要的原因与编写代码做任何事情的原因相同……自动化!一个游戏不仅仅是由一张卡片组成的。同样,游戏也不是一次设计成功的。它需要大量的游戏测试和修改。如果你用代码设计你的桌面游戏,你可以像更改配置文件一样轻松地创建新的修订版。

当然,自动图像生成不仅仅适用于游戏……

下次

我已经向你展示了如何为游戏创建图像。如果你像我一样,接下来你想做的事情就是打印你的游戏。你可以在家做这件事,但会花费你大量的时间和金钱(喷墨墨水比人血还贵)。你也可以把它拿到柯达,但你不会得到一个高质量的产品,因为他们不擅长制作游戏。相反,你可以将你的文件上传到 The Game Crafter,在那里你会得到一个看起来像是从游戏店买来的定制游戏。有一个简单易用的网页界面来做这件事,但你是一个 Perl 程序员。为什么手动做某事,如果你可以自动化它呢?

除此之外,这是一个与完全用 Perl 编写的 Web 服务交互的现实世界例子——在两个方面。谁会不对此感兴趣呢?

对于没有耐心的人

Lacuna Expanse 桌面游戏现在可供购买。此外,我已经通过这个公开的 GitHub 仓库发布了开发它的代码

标签

反馈

这篇文章有什么问题吗?请在 GitHub 上打开一个问题或拉取请求来帮助我们。