实战项目介绍
在实战篇中,我们将制作一个终端小游戏,在终端中运行一款类似于太空大战的游戏,玩家控制一个小飞机,发射子弹打败敌人。
创建新项目
我们为项目命名为Invaders
(侵略者), 现在让我们使用cargo
命令创建一个新项目:
➜ ~ cargo new invaders
Created binary (application) `invaders` package
在这个游戏中,我们需要一些音频文件,例如:
- 游戏开始的音乐
- 胜利的音乐
- 失败的音乐
- 发射子弹的声音
放置音频文件
现在让我们把这些音频文件(点击下载)也放在项目的目录中:
➜ ~ cp sound/* invaders
添加项目依赖
在Cargo.toml
中添加项目的依赖包:
[package]
name = "invaders"
version = "0.1.0"
edition = "2021"
[dependencies]
crossterm = "0.27.0" // 用于编写终端图形界面
rusty_audio = "1.2" // 用于处理音频
rusty_time = "0.12" // 提供处理时间的功能,如计时器等
编译依赖项
由于依赖项的编译也需要花一些时间,因此我们可以在添加好依赖后,先构建一次项目,这通常需要花一些时间,以便下次构建时更加快速。在这个过程中,我们可以继续进行项目代码的编写。 运行下面的命令构建项目:
cargo build && cargo build --release // 这里运行两个命令的目的是为了之后比较他们的输出,其实只运行前面的就可以了
修改main函数
// main.rs
use std::error::Error;
use rusty_audio::Audio;
fn main() -> Result<(), Box<dyn Error>>{
let mut audio = Audio::new();
audio.add("explode", "./explode.wav");
audio.add("lose", "./lose.wav");
audio.add("move", "./move.wav");
audio.add("pew", "./pew.wav");
audio.add("startup", "./startup.wav");
audio.add("win", "./win.wav");
audio.play("startup");
Ok(())
}
在这个函数中, 返回值的类型是一个Result
枚举型,如果游戏正常运行的话,我们不太关心游戏退出后返回的结果,但我们需要关心游戏异常崩溃时发生的错误, 由于错误的类型不一定,我们使用了智能指针Box
, 这个指针指向一个动态的类型,这个类型需要实现了Error
这个Trait。
接下来需要将音频文件放入音频库中,以便后续使用,因此用Audio::new()
创建了一个音频库,并且用add()
方法把我们所需的音频文件都添加了进去。
然后调用play()
方法播放音频, 程序的末尾返回一个空元组,以满足返回类型的需要。
看起来现在可以播放游戏的开始音乐了,但实际上如果现在就运行这个程序,我们听不见任何的声音, 因为play()
这个方法会起一个子线程并开始播放音乐,我们必须要等待这个子线程结束才能结束主进程,否则子线程还没来得及播放声音,主进程就结束了。
因此上面的代码中还需要添加一行,最终的代码如下:
// main.rs
use std::error::Error;
use rusty_audio::Audio;
fn main() -> Result<(), Box<dyn Error>>{
// Audio
let mut audio = Audio::new();
audio.add("explode", "./explode.wav");
audio.add("lose", "./lose.wav");
audio.add("move", "./move.wav");
audio.add("pew", "./pew.wav");
audio.add("startup", "./startup.wav");
audio.add("win", "./win.wav");
audio.play("startup");
// Cleanup
audio.wait(); // 等待播放结束
Ok(())
}
注:// Cleanup
注释以下的代码表示程序准备退出时执行的代码。
运行程序
现在,我们运行cargo run
命令来运行程序:
(base) ➜ invaders git:(master) ✗ cargo run
Compiling invaders v0.1.0 (/Users/xianyao.chen/invaders)
Finished dev [unoptimized + debuginfo] target(s) in 0.57s
Running `target/debug/invaders`
现在应该就可以听见声音了。
小结
本章中我们启动了一个小游戏的实战项目,并设置了开始音频的播放,下一章开始我们将编写我们的图形界面,并用多线程编程编写游戏逻辑。