Rust 命令:摘苹果游戏
游戏介绍
这是一个基于 Rust 语言开发的命令行摘苹果小游戏。游戏中,玩家将控制一个角色在屏幕底部左右移动,接住从上方掉落的苹果得分。随着分数增加,苹果掉落速度会逐渐加快,增加游戏挑战性。游戏结束后会显示最终得分。
游戏特色与难点
难度递增机制:随着玩家得分增加,苹果生成间隔会按一定比例缩短(difficulty_increase_rate),使游戏难度逐渐提高,增加挑战性。
终端交互处理:使用 crossterm 库实现非阻塞式输入处理,确保游戏流畅运行而不会在等待输入时卡顿。
帧率控制:通过计时器控制游戏状态更新频率(update_interval),使游戏速度稳定可控。
跨平台兼容性:借助 crossterm 库的跨平台特性,游戏可以在 Windows、macOS 和 Linux 等不同操作系统上运行。
游戏扩展
总结
这款命令行摘苹果游戏虽然简单,但涵盖了游戏开发的基本要素:游戏循环、输入处理、状态更新、碰撞检测和画面渲染。通过 Rust 语言的特性和相关库的使用,我们能够高效地开发出这样一个交互性强、运行流畅的终端游戏。
Rust 的内存安全特性和高性能保证了游戏的稳定运行,而面向对象的设计使代码结构清晰、易于维护和扩展。这个项目不仅适合作为 Rust 初学者的练习项目,也展示了在命令行环境下开发小游戏的可能性。
通过开发这款游戏,我们可以深入理解游戏开发的基本原理,以及如何在 Rust 中处理终端交互、时间控制和状态管理等关键技术点。希望这个项目能为你的 Rust 学习和游戏开发之路提供一些帮助和启发。
use crossterm::{
event::{self, Event, KeyCode, KeyEvent},
execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use rand::Rng;
use std::{
collections::VecDeque,
io,
time::{Duration, Instant},
};
use tui::{
backend::{Backend, CrosstermBackend},
layout::{Constraint, Direction, Layout},
widgets::{Block, Borders, Paragraph, Text},
Terminal,
};
struct Apple {
x: u16,
y: u16,
}
struct Player {
x: u16,
y: u16,
}
struct Game {
player: Player,
apples: VecDeque<Apple>,
score: u32,
width: u16,
height: u16,
game_over: bool,
last_apple_spawn: Instant,
apple_spawn_interval: Duration,
difficulty_increase_rate: f32,
}
impl Game {
fn new(width: u16, height: u16) -> Self {
Self {
player: Player {
x: width / 2,
y: height - 2,
},
apples: VecDeque::new(),
score: 0,
width,
height,
game_over: false,
last_apple_spawn: Instant::now(),
apple_spawn_interval: Duration::from_secs(1),
difficulty_increase_rate: 0.95,
}
}
fn spawn_apple(&mut self) {
let mut rng = rand::thread_rng();
let x = rng.gen_range(1..self.width - 1);
self.apples.push_back(Apple { x, y: 1 });
}
fn update(&mut self) {
// 检查是否需要生成新苹果
if Instant::now() - self.last_apple_spawn > self.apple_spawn_interval {
self.spawn_apple();
self.last_apple_spawn = Instant::now();
}
// 移动所有苹果
let mut i = 0;
while i < self.apples.len() {
self.apples[i].y += 1;
// 检查苹果是否被玩家接住
if self.apples[i].y == self.player.y && self.apples[i].x == self.player.x {
self.apples.remove(i);
self.score += 1;
// 随着分数增加,加快苹果生成速度
self.apple_spawn_interval = Duration::from_secs_f32(
self.apple_spawn_interval.as_secs_f32() * self.difficulty_increase_rate
);
}
// 检查苹果是否落地(游戏结束)
else if self.apples[i].y >= self.height - 1 {
self.game_over = true;
break;
} else {
i += 1;
}
}
}
fn handle_input(&mut self, key: KeyCode) {
match key {
KeyCode::Left => {
if self.player.x > 1 {
self.player.x -= 1;
}
}
KeyCode::Right => {
if self.player.x < self.width - 2 {
self.player.x += 1;
}
}
KeyCode::Q => {
self.game_over = true;
}
_ => {}
}
}
fn render<B: Backend>(&self, terminal: &mut Terminal<B>) -> io::Result<()> {
let mut game_area = String::new();
// 绘制顶部边框
game_area.push_str(&"─".repeat(self.width as usize));
game_area.push('\n');
// 绘制游戏区域
for y in 1..self.height - 1 {
game_area.push('│');
for x in 1..self.width - 1 {
// 检查是否是苹果
let is_apple = self.apples.iter().any(|a| a.x == x && a.y == y);
// 检查是否是玩家
let is_player = self.player.x == x && self.player.y == y;
if is_apple {
game_area.push('🍎');
} else if is_player {
game_area.push('😀');
} else {
game_area.push(' ');
}
}
game_area.push('│');
game_area.push('\n');
}
// 绘制底部边框
game_area.push_str(&"─".repeat(self.width as usize));
game_area.push('\n');
// 绘制分数和控制说明
game_area.push_str(&format!("得分: {}\n", self.score));
game_area.push_str("使用 ← → 键移动,Q 键退出游戏\n");
if self.game_over {
game_area.push_str(&format!("\n游戏结束!最终得分: {}\n", self.score));
game_area.push_str("按 Q 键退出\n");
}
let para = Paragraph::new(Text::raw(game_area))
.block(Block::default().borders(Borders::ALL).title("摘苹果游戏"));
terminal.draw(|f| {
let size = f.size();
f.render_widget(para, size);
})?;
Ok(())
}
fn run(&mut self) -> io::Result<()> {
// 初始化终端
enable_raw_mode()?;
let mut stdout = io::stdout();
execute!(stdout, EnterAlternateScreen)?;
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
terminal.clear()?;
// 游戏主循环
let mut last_update = Instant::now();
let update_interval = Duration::from_millis(200);
while !self.game_over {
// 处理输入
if event::poll(Duration::from_millis(10))? {
if let Event::Key(event) = event::read()? {
self.handle_input(event.code);
}
}
// 更新游戏状态
if Instant::now() - last_update > update_interval {
self.update();
last_update = Instant::now();
}
// 渲染游戏
self.render(&mut terminal)?;
}
// 清理终端
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
terminal.show_cursor()?;
Ok(())
}
}
fn main() -> io::Result<()> {
let game_width = 40;
let game_height = 20;
let mut game = Game::new(game_width, game_height);
game.run()
}
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)