github源代码:

hengsleep/Rust-flappy-game (github.com)https://github.com/hengsleep/Rust-flappy-game

演示示例:

安装完rust后,在cmd引用到对应文件夹目录下,运行:

cargo new

在配置文件cargo.toml中修改如下:

[package]

name = "FirstGame-flappy-Xheng1934"

version = "0.1.0"

edition = "2021"

authors = ["Xheng1934"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

bracket-lib = "~0.8"

最后~0.8为版本号,可自行更改为最新版本。

main.rs文件下的源码:

use std::fmt::format;

use bracket_lib::prelude::*;

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 {

mode: GameMode,

player: Player,

frame_time: f32,

obstacle: Obstacle,

score: i32,

}

impl State {

fn new() -> Self {

State {

player: Player::new(10, 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.frame_time = 0.0;

self.player.gravity_and_move();

}

if let Some(VirtualKeyCode::Space) = ctx.key {

self.player.flap();

}

self.player.render(ctx);

ctx.print(0, 0, "Press space to Flap");

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;

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;

self.score = 0;

self.obstacle = Obstacle::new(SCREEN_WIDTH, 0);

}

fn main_menu(&mut self, ctx: &mut BTerm) {

ctx.cls();

ctx.print_centered(5, "Welcome to Flappy Game! -Xheng1934");

ctx.print_centered(8, "(P) Play Game");

ctx.print_centered(9, "(Q) 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, "You are dead!");

ctx.print_centered(6, &format!("You earned {} points", self.score));

ctx.print_centered(8, "(P) Play Again ");

ctx.print_centered(9, "(Q) Quit Game");

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::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: i32 = self.x - player_x;

let half_size: i32 = 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: i32 = self.size / 2;

let does_x_match: bool = player.x == self.x;

let player_above_gap: bool = player.y < self.gap_y - half_size;

let player_below_gap: bool = player.y > self.gap_y + half_size;

does_x_match && (player_above_gap || player_below_gap)

}

}

fn main() -> BError {

let context = BTermBuilder::simple80x50()

.with_title("Flappy Game")

.build()?;

main_loop(context, State::new())

}

cmd运行:

cargo run

初始界面:

游戏中:

游戏结束:

Codepage 437:IBM 扩展ASCI 字符集

来自 Dos PC上的字符,用于终端输出,除了字母和数字,还提供了一些符号。

Bracket-lib 会把字符翻译成 图形 sprites 并提供一个有限的字符集,字符所展示的是相应的图片。

bracket-terminal是Bracket-Lib 中负责显示的部分。

文章链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: