使用Rust開發(fā)小游戲完成過程
本文是對 使用 Rust 開發(fā)一個(gè)微型游戲【已完結(jié)】
cargo new flappy
在Cargo.toml的[dependencies]下方增加:
bracket-lib = "~0.8.7"
main.rs中:
use bracket_lib::prelude::*;
struct State {}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print(1, 1, "Hello,Bracket Terminal!");
}
}
fn main() -> BError {
let context: BTerm = BTermBuilder::simple80x50()
.with_title("爽哥做游戲--Flappy Dragon")
.build()?;
main_loop(context, State {})
}cargo run后,可以看到

use bracket_lib::prelude::*;
// 游戲3種模式(菜單,游戲中,結(jié)束)
enum GameMode {
Menu,
Playing,
End,
}
struct State {
mode: GameMode,
}
impl State {
fn new() -> Self {
State {
mode: GameMode::Menu,
}
}
fn play(&mut self, ctx: &mut BTerm) {
//TODO
self.mode = GameMode::End;
}
fn restart(&mut self) {
self.mode = GameMode::Playing;
}
fn main_menu(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "歡迎來到游戲~");
ctx.print_centered(8, "Press P key to start Game");
ctx.print_centered(9, "Press Q to quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
{}
}
}
fn dead(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "你掛了..");
ctx.print_centered(8, "按P鍵 再來一局");
ctx.print_centered(9, "按Q鍵 退出游戲");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
{}
}
}
}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
match self.mode {
GameMode::Menu => self.main_menu(ctx),
GameMode::End => self.dead(ctx),
GameMode::Playing => self.play(ctx),
}
// ctx.cls();
// ctx.print(1, 1, "Hello,Bracket Terminal!");
}
}
fn main() -> BError {
let context: BTerm = BTermBuilder::simple80x50()
.with_title("爽哥做游戲--Flappy Dragon")
.build()?;
main_loop(context, State::new())
}
增加玩家
use bracket_lib::prelude::*;
// 游戲3種模式(菜單,游戲中,結(jié)束)
enum GameMode {
Menu,
Playing,
End,
}
const SCREEN_WIDTH: i32 = 80;
const SCREEN_HEIGHT: i32 = 50;
const FRAME_DURATION: f32 = 75.0;
struct Player {
x: i32,
y: i32,
velocity: f32,
}
impl Player {
fn new(x: i32, y: i32) -> Self {
Player {
x: 0,
y: 0,
velocity: 0.0,
}
}
fn render(&mut self, ctx: &mut BTerm) {
ctx.set(0, self.y, YELLOW, BLACK, to_cp437('@'));
}
fn gravity_and_move(&mut self) {
if self.velocity < 2.0 {
self.velocity += 0.2;
}
self.y += self.velocity as i32;
self.x += 1;
if self.y < 0 {
self.y = 0;
}
}
fn flap(&mut self) {
self.velocity = -2.0;
}
}
struct State {
player: Player,
frame_time: f32,
mode: GameMode,
}
impl State {
fn new() -> Self {
State {
player: Player::new(5, 25),
frame_time: 0.0,
mode: GameMode::Menu,
}
}
fn play(&mut self, ctx: &mut BTerm) {
ctx.cls_bg(NAVY);
self.frame_time += ctx.frame_time_ms;
if self.frame_time >= FRAME_DURATION {
self.player.gravity_and_move();
self.frame_time = 0.0;
}
// 按空格
if let Some(VirtualKeyCode::Space) = ctx.key {
self.player.flap();
}
self.player.render(ctx);
ctx.print(0, 0, "按空格起飛~");
if self.player.y > SCREEN_HEIGHT {
self.mode = GameMode::End;
}
}
fn restart(&mut self) {
self.player = Player::new(5, 25);
self.frame_time = 0.0;
self.mode = GameMode::Playing;
}
fn main_menu(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "歡迎來到游戲~");
ctx.print_centered(8, "Press P key to start Game");
ctx.print_centered(9, "Press Q to quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
{}
}
}
fn dead(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "你掛了..");
ctx.print_centered(8, "按P鍵 再來一局");
ctx.print_centered(9, "按Q鍵 退出游戲");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
{}
}
}
}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
match self.mode {
GameMode::Menu => self.main_menu(ctx),
GameMode::End => self.dead(ctx),
GameMode::Playing => self.play(ctx),
}
// ctx.cls();
// ctx.print(1, 1, "Hello,Bracket Terminal!");
}
}
fn main() -> BError {
let context: BTerm = BTermBuilder::simple80x50()
.with_title("爽哥做游戲--Flappy Dragon")
.build()?;
main_loop(context, State::new())
}
增加障礙
use std::fmt::format;
use bracket_lib::prelude::*;
// 游戲3種模式(菜單,游戲中,結(jié)束)
enum GameMode {
Menu,
Playing,
End,
}
const SCREEN_WIDTH: i32 = 80;
const SCREEN_HEIGHT: i32 = 50;
const FRAME_DURATION: f32 = 75.0;
struct Player {
x: i32,
y: i32,
velocity: f32,
}
impl Player {
fn new(x: i32, y: i32) -> Self {
Player {
x: 0,
y: 0,
velocity: 0.0,
}
}
fn render(&mut self, ctx: &mut BTerm) {
ctx.set(0, self.y, YELLOW, BLACK, to_cp437('@'));
}
fn gravity_and_move(&mut self) {
if self.velocity < 2.0 {
self.velocity += 0.2;
}
self.y += self.velocity as i32;
self.x += 1;
if self.y < 0 {
self.y = 0;
}
}
fn flap(&mut self) {
self.velocity = -2.0;
}
}
struct State {
player: Player,
frame_time: f32,
mode: GameMode,
obstacle: Obstacle,
score: i32,
}
impl State {
fn new() -> Self {
State {
player: Player::new(5, 25),
frame_time: 0.0,
mode: GameMode::Menu,
obstacle: Obstacle::new(SCREEN_WIDTH, 0),
score: 0,
}
}
fn play(&mut self, ctx: &mut BTerm) {
ctx.cls_bg(NAVY);
self.frame_time += ctx.frame_time_ms;
if self.frame_time >= FRAME_DURATION {
self.player.gravity_and_move();
self.frame_time = 0.0;
}
// 按空格
if let Some(VirtualKeyCode::Space) = ctx.key {
self.player.flap();
}
self.player.render(ctx);
ctx.print(0, 0, "按空格起飛~");
// 障礙物&積分
// 實(shí)時(shí)打印分?jǐn)?shù)
ctx.print(0, 1, &format!("Score: {}", self.score));
self.obstacle.render(ctx, self.player.x);
if self.player.x > self.obstacle.x {
self.score += 1; // 分?jǐn)?shù)+1
self.obstacle = Obstacle::new(self.player.x + SCREEN_WIDTH, self.score);
}
if self.player.y > SCREEN_HEIGHT || self.obstacle.hit_obstacle(&self.player) {
self.mode = GameMode::End;
}
}
fn restart(&mut self) {
self.player = Player::new(5, 25);
self.frame_time = 0.0;
self.mode = GameMode::Playing;
// 重置分?jǐn)?shù)和障礙物
self.obstacle = Obstacle::new(SCREEN_WIDTH, 0);
self.score = 0;
}
fn main_menu(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "歡迎來到游戲~");
ctx.print_centered(8, "Press P key to start Game");
ctx.print_centered(9, "Press Q to quit Game");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
{}
}
}
fn dead(&mut self, ctx: &mut BTerm) {
ctx.cls();
ctx.print_centered(5, "你掛了..");
// 掛了后顯示一下分?jǐn)?shù)
ctx.print_centered(6, &format!("本局獲得了 {} 分", self.score));
ctx.print_centered(8, "按P鍵 再來一局");
ctx.print_centered(9, "按Q鍵 退出游戲");
if let Some(key) = ctx.key {
match key {
VirtualKeyCode::P => self.restart(),
VirtualKeyCode::Q => ctx.quitting = true,
_ => {}
}
{}
}
}
}
impl GameState for State {
fn tick(&mut self, ctx: &mut BTerm) {
match self.mode {
GameMode::Menu => self.main_menu(ctx),
GameMode::End => self.dead(ctx),
GameMode::Playing => self.play(ctx),
}
}
}
struct Obstacle {
x: i32,
gap_y: i32,
size: i32,
}
impl Obstacle {
fn new(x: i32, score: i32) -> Self {
let mut random: RandomNumberGenerator = RandomNumberGenerator::new();
Obstacle {
x,
gap_y: random.range(10, 40),
size: i32::max(2, 20 - score),
}
}
fn render(&mut self, ctx: &mut BTerm, player_x: i32) {
let screen_x = self.x - player_x;
let half_size = self.size / 2;
for y in 0..self.gap_y - half_size {
ctx.set(screen_x, y, RED, BLACK, to_cp437('|'));
}
for y in self.gap_y + half_size..SCREEN_HEIGHT {
ctx.set(screen_x, y, RED, BLACK, to_cp437('|'));
}
}
fn hit_obstacle(&self, player: &Player) -> bool {
let half_size = self.size / 2;
let does_x_match = player.x == self.x;
let player_above_gap = player.y < self.gap_y - half_size;
let player_below_gap = player.y > self.gap_y + half_size;
does_x_match && (player_above_gap || player_below_gap)
}
}
fn main() -> BError {
let context: BTerm = BTermBuilder::simple80x50()
.with_title("爽哥做游戲--Flappy Dragon")
.build()?;
main_loop(context, State::new())
}

參考資料[1]
使用 Rust 開發(fā)一個(gè)微型游戲【已完結(jié)】: https://www.bilibili.com/video/BV1vM411J74S
到此這篇關(guān)于使用Rust開發(fā)小游戲的文章就介紹到這了,更多相關(guān)Rust開發(fā)小游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Rust編程中的共享狀態(tài)并發(fā)執(zhí)行
雖然消息傳遞是一個(gè)很好的處理并發(fā)的方式,但并不是唯一一個(gè),另一種方式是讓多個(gè)線程擁有相同的共享數(shù)據(jù),本文給大家介紹Rust編程中的共享狀態(tài)并發(fā)執(zhí)行,感興趣的朋友一起看看吧2023-11-11
Go調(diào)用Rust方法及外部函數(shù)接口前置
這篇文章主要為大家介紹了Go調(diào)用Rust方法及外部函數(shù)接口前置示例實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
rust標(biāo)準(zhǔn)庫std::env環(huán)境相關(guān)的常量
在本章節(jié)中, 我們探討了Rust處理命令行參數(shù)的常見的兩種方式和處理環(huán)境變量的兩種常見方式, 拋開Rust的語法, 實(shí)際上在命令行參數(shù)的處理方式上, 與其它語言大同小異, 可能影響我們習(xí)慣的也就只剩下語法,本文介紹rust標(biāo)準(zhǔn)庫std::env的相關(guān)知識,感興趣的朋友一起看看吧2024-03-03

