REX Paint 主菜单


关于本教程

本教程是免费且开源的,所有代码均使用 MIT 许可证 - 因此您可以随意使用。我希望您会喜欢本教程,并制作出色的游戏!

如果您喜欢本教程并希望我继续写作,请考虑支持我的 Patreon

Hands-On Rust


我们的主菜单非常无聊,不利于吸引玩家!本章将为它增添趣味。

REX Paint

Grid Sage Games(Reddit 上令人惊叹的 u/Kyzrati)提供了一个很棒的工具,用于 Codepage 437 图像编辑,名为 REX Paint。RLTK 内置了对使用此编辑器输出的支持。正如他们在 BBC 的老牌儿童节目 Blue Peter 中常说的那样 - 这是我之前做好的一个。

截图

我稍微作弊了一下;我找到了一张 CC0 图像,在 GIMP 中将其大小调整为 80x50,并使用我多年前编写的工具 将 PNG 转换为 REX Paint 文件。不过,我喜欢这个结果。您可以在 resources 文件夹中找到 REX Paint 文件。

加载 REX 资源

我们将引入一个新文件 rex_assets.rs 来存储我们的 REX 精灵图。该文件看起来像这样:

#![allow(unused)]
fn main() {
use rltk::{rex::XpFile};

rltk::embedded_resource!(SMALL_DUNGEON, "../../resources/SmallDungeon_80x50.xp");

pub struct RexAssets {
    pub menu : XpFile
}

impl RexAssets {
    #[allow(clippy::new_without_default)]
    pub fn new() -> RexAssets {
        rltk::link_resource!(SMALL_DUNGEON, "../../resources/SmallDungeon_80x50.xp");

        RexAssets{
            menu : XpFile::from_resource("../../resources/SmallDungeon_80x50.xp").unwrap()
        }
    }
}
}

非常简单 - 它定义了一个结构体,并在调用 new 时将地下城图形加载到其中。我们还将它作为资源插入到 Specs 中,以便我们可以在任何地方访问我们的精灵图。这里有一些新概念:

  1. 我们正在使用 rltk::embedded_resource! 将文件包含在我们的二进制文件中。这避免了必须将二进制文件与您的可执行文件一起发布(并使 wasm 环境中的生活更轻松)。
  2. #[allow(clippy::new_without_default)] 告诉 linter 不要再告诉我编写默认实现,当我们不需要它时!
  3. rltk::link_resource! 是嵌入式资源的后半部分;前半部分将其存储在内存中,后半部分告诉 RLTK 在哪里找到它。
  4. menu : XpFile::from_resource("../../resources/SmallDungeon_80x50.xp").unwrap() 从内存中加载 Rex paint 文件。

main.rs 中:

#![allow(unused)]
fn main() {
gs.ecs.insert(rex_assets::RexAssets::new());
}

现在我们打开 gui.rs 并找到 main_menu 函数。在开始打印菜单内容之前,我们将添加两行代码:

#![allow(unused)]
fn main() {
let assets = gs.ecs.fetch::<RexAssets>();
ctx.render_xp_sprite(&assets.menu, 0, 0);
}

结果(cargo run 查看)是一个不错的菜单的开始!

截图

改善菜单外观 - 添加边框和文本框

为了使其看起来更漂亮,我们将处理间距 - 并为菜单和文本添加一个框。将当前标题渲染代码替换为:

#![allow(unused)]
fn main() {
ctx.draw_box_double(24, 18, 31, 10, RGB::named(rltk::WHEAT), RGB::named(rltk::BLACK));
ctx.print_color_centered(20, RGB::named(rltk::YELLOW), RGB::named(rltk::BLACK), "Rust Roguelike Tutorial");
ctx.print_color_centered(21, RGB::named(rltk::CYAN), RGB::named(rltk::BLACK), "by Herbert Wolverson");
ctx.print_color_centered(22, RGB::named(rltk::GRAY), RGB::named(rltk::BLACK), "Use Up/Down Arrows and Enter");
}

如果您现在 cargo run,您的菜单看起来像这样:

截图

这好多了!

修复间距

您会注意到,如果您没有要加载的已保存游戏,菜单项之间会有一个恼人的间隙。这是一个简单的修复方法,通过在渲染菜单时跟踪我们使用的 y 位置。这是新的菜单渲染代码:

#![allow(unused)]
fn main() {
let mut y = 24;
    if let RunState::MainMenu{ menu_selection : selection } = *runstate {
        if selection == MainMenuSelection::NewGame {
            ctx.print_color_centered(y, RGB::named(rltk::MAGENTA), RGB::named(rltk::BLACK), "Begin New Game");
        } else {
            ctx.print_color_centered(y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Begin New Game");
        }
        y += 1;

        if save_exists {
            if selection == MainMenuSelection::LoadGame {
                ctx.print_color_centered(y, RGB::named(rltk::MAGENTA), RGB::named(rltk::BLACK), "Load Game");
            } else {
                ctx.print_color_centered(y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Load Game");
            }
            y += 1;
        }

        if selection == MainMenuSelection::Quit {
            ctx.print_color_centered(y, RGB::named(rltk::MAGENTA), RGB::named(rltk::BLACK), "Quit");
        } else {
            ctx.print_color_centered(y, RGB::named(rltk::WHITE), RGB::named(rltk::BLACK), "Quit");
        }
    ...
}

如果您现在 cargo run,它看起来更好了:

截图

本章的源代码可以在这里找到

使用 web assembly 在您的浏览器中运行本章的示例(需要 WebGL2)

版权所有 (C) 2019, Herbert Wolverson。