上一章节中,我们实现了游戏开始音频的播放,本章我们开始编写游戏界面。我们的游戏是在命令行终端中运行的,因此编写的界面也是终端中展示的界面,上一章中,我们已经把相关的依赖包crossterm
添加到了依赖列表中。本章首先为游戏准备所需的键盘和屏幕配置。
创建一个空白的游戏终端屏幕
// main.rs
use std::{error::Error, io};
use crossterm::{terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, cursor::{Hide, Show}};
use rusty_audio::Audio;
fn main() -> Result<(), Box<dyn Error>>{
// Audio
snip[..]
// Terminal
let mut stdout = io::stdout(); // 首先需要创建一个句柄用于访问终端
terminal::enable_raw_mode()?; // 调用这个方法,可以让系统能在每次键盘操作时都能实时获取到键盘的输入,而不是先放入缓冲区
stdout.execute(EnterAlternateScreen)?; // 进入备用屏幕,例如使用 vim或emacs 命令时,会跳出来一个专用的屏幕,而不是原来的终端命令行,当你退出vim或emacs时,又会回到原来的屏幕上。
stdout.execute(Hide)?; // 隐藏光标
// Cleanup
audio.wait(); // 等待播放结束
stdout.execute(Show)?; // 游戏结束前,我们需要把刚才对屏幕的操作都还原,首先是显示光标
stdout.execute(LeaveAlternateScreen)?; // 然后退出备用屏幕,回到主屏幕
terminal::disable_raw_mode()?; // 然后恢复键盘模式
Ok(())
}
上面的代码中,execute()
函数可以在stdout
变量上调用,让标准输出(也就是终端)立即执行一些操作,例如上面用到的:
- 进入/退出备用屏幕
- 隐藏/显示光标
需要注意的是,我们在游戏过程中对键盘和屏幕都做了一些特殊的操作,为了在游戏退出后能正常使用设备,我们要在游戏退出前还原这些设置。具体的设置已经在上面的代码注释中标注了出来。
上面的代码中,有些语句后面添加了?
符号,它的作用是当这行语句执行返回错误时,立即崩溃并退出程序。
运行空白的终端界面
完成代码修改后, 执行cargo run
开始运行游戏,看看会发生什么? 如果一切正常的话,你会听到游戏开始的声音“bang bang bang bang”, 并且在声音播放的过程中,你的终端会进入备用屏幕,且没有光标,换句话说,就是一个完全空白的终端,像这样:
等到音频播放结束后,游戏准备退出,还原了终端屏幕和键盘的设置,又回到了正常的命令行界面:
小结
本章的内容比较简单,为游戏准备了所需的键盘设置和一个空白的终端屏幕,从下一章开始,我们开始编写游戏的主循环。