本文是对 使用 Rust 开发一个微型游戏【已完结】[1]的学习与记录.

cargo new flappy

在Cargo.toml的[dependencies]下方增加:

bracket-lib = "~0.8.7"

main.rs中:

usebracket_lib::prelude::*;

structState{}

implGameStateforState{
fntick(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print(1,1,"Hello,BracketTerminal!");
}
}

fnmain()->BError{
letcontext:BTerm=BTermBuilder::simple80x50()
.with_title("爽哥做游戏--FlappyDragon")
.build()?;

main_loop(context,State{})
}

cargo run后,可以看到


usebracket_lib::prelude::*;

//游戏3种模式(菜单,游戏中,结束)
enumGameMode{
Menu,
Playing,
End,
}

structState{
mode:GameMode,
}

implState{
fnnew()->Self{
State{
mode:GameMode::Menu,
}
}

fnplay(&mutself,ctx:&mutBTerm){
//TODO
self.mode=GameMode::End;
}

fnrestart(&mutself){
self.mode=GameMode::Playing;
}

fnmain_menu(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print_centered(5,"欢迎来到游戏~");
ctx.print_centered(8,"PressPkeytostartGame");
ctx.print_centered(9,"PressQtoquitGame");

ifletSome(key)=ctx.key{
matchkey{
VirtualKeyCode::P=>self.restart(),
VirtualKeyCode::Q=>ctx.quitting=true,
_=>{}
}
{}
}
}

fndead(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print_centered(5,"你挂了..");
ctx.print_centered(8,"按P键再来一局");
ctx.print_centered(9,"按Q键退出游戏");

ifletSome(key)=ctx.key{
matchkey{
VirtualKeyCode::P=>self.restart(),
VirtualKeyCode::Q=>ctx.quitting=true,
_=>{}
}
{}
}
}
}

implGameStateforState{
fntick(&mutself,ctx:&mutBTerm){
matchself.mode{
GameMode::Menu=>self.main_menu(ctx),
GameMode::End=>self.dead(ctx),
GameMode::Playing=>self.play(ctx),
}

//ctx.cls();
//ctx.print(1,1,"Hello,BracketTerminal!");
}
}

fnmain()->BError{
letcontext:BTerm=BTermBuilder::simple80x50()
.with_title("爽哥做游戏--FlappyDragon")
.build()" />


增加玩家

usebracket_lib::prelude::*;

//游戏3种模式(菜单,游戏中,结束)
enumGameMode{
Menu,
Playing,
End,
}

constSCREEN_WIDTH:i32=80;
constSCREEN_HEIGHT:i32=50;
constFRAME_DURATION:f32=75.0;

structPlayer{
x:i32,
y:i32,
velocity:f32,
}

implPlayer{
fnnew(x:i32,y:i32)->Self{
Player{
x:0,
y:0,
velocity:0.0,
}
}

fnrender(&mutself,ctx:&mutBTerm){
ctx.set(0,self.y,YELLOW,BLACK,to_cp437('@'));
}

fngravity_and_move(&mutself){
ifself.velocity<2.0{
self.velocity+=0.2;
}
self.y+=self.velocityasi32;
self.x+=1;
ifself.y<0{
self.y=0;
}
}

fnflap(&mutself){
self.velocity=-2.0;
}
}

structState{
player:Player,
frame_time:f32,
mode:GameMode,
}

implState{
fnnew()->Self{
State{
player:Player::new(5,25),
frame_time:0.0,
mode:GameMode::Menu,
}
}

fnplay(&mutself,ctx:&mutBTerm){
ctx.cls_bg(NAVY);
self.frame_time+=ctx.frame_time_ms;

ifself.frame_time>=FRAME_DURATION{
self.player.gravity_and_move();
self.frame_time=0.0;
}

//按空格
ifletSome(VirtualKeyCode::Space)=ctx.key{
self.player.flap();
}

self.player.render(ctx);
ctx.print(0,0,"按空格起飞~");

ifself.player.y>SCREEN_HEIGHT{
self.mode=GameMode::End;
}
}

fnrestart(&mutself){
self.player=Player::new(5,25);
self.frame_time=0.0;
self.mode=GameMode::Playing;
}

fnmain_menu(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print_centered(5,"欢迎来到游戏~");
ctx.print_centered(8,"PressPkeytostartGame");
ctx.print_centered(9,"PressQtoquitGame");

ifletSome(key)=ctx.key{
matchkey{
VirtualKeyCode::P=>self.restart(),
VirtualKeyCode::Q=>ctx.quitting=true,
_=>{}
}
{}
}
}

fndead(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print_centered(5,"你挂了..");
ctx.print_centered(8,"按P键再来一局");
ctx.print_centered(9,"按Q键退出游戏");

ifletSome(key)=ctx.key{
matchkey{
VirtualKeyCode::P=>self.restart(),
VirtualKeyCode::Q=>ctx.quitting=true,
_=>{}
}
{}
}
}
}

implGameStateforState{
fntick(&mutself,ctx:&mutBTerm){
matchself.mode{
GameMode::Menu=>self.main_menu(ctx),
GameMode::End=>self.dead(ctx),
GameMode::Playing=>self.play(ctx),
}

//ctx.cls();
//ctx.print(1,1,"Hello,BracketTerminal!");
}
}

fnmain()->BError{
letcontext:BTerm=BTermBuilder::simple80x50()
.with_title("爽哥做游戏--FlappyDragon")
.build()" />


增加障碍

usestd::fmt::format;

usebracket_lib::prelude::*;

//游戏3种模式(菜单,游戏中,结束)
enumGameMode{
Menu,
Playing,
End,
}

constSCREEN_WIDTH:i32=80;
constSCREEN_HEIGHT:i32=50;
constFRAME_DURATION:f32=75.0;

structPlayer{
x:i32,
y:i32,
velocity:f32,
}

implPlayer{
fnnew(x:i32,y:i32)->Self{
Player{
x:0,
y:0,
velocity:0.0,
}
}

fnrender(&mutself,ctx:&mutBTerm){
ctx.set(0,self.y,YELLOW,BLACK,to_cp437('@'));
}

fngravity_and_move(&mutself){
ifself.velocity<2.0{
self.velocity+=0.2;
}
self.y+=self.velocityasi32;
self.x+=1;
ifself.y<0{
self.y=0;
}
}

fnflap(&mutself){
self.velocity=-2.0;
}
}

structState{
player:Player,
frame_time:f32,
mode:GameMode,
obstacle:Obstacle,
score:i32,
}

implState{
fnnew()->Self{
State{
player:Player::new(5,25),
frame_time:0.0,
mode:GameMode::Menu,
obstacle:Obstacle::new(SCREEN_WIDTH,0),
score:0,
}
}

fnplay(&mutself,ctx:&mutBTerm){
ctx.cls_bg(NAVY);
self.frame_time+=ctx.frame_time_ms;

ifself.frame_time>=FRAME_DURATION{
self.player.gravity_and_move();
self.frame_time=0.0;
}

//按空格
ifletSome(VirtualKeyCode::Space)=ctx.key{
self.player.flap();
}

self.player.render(ctx);
ctx.print(0,0,"按空格起飞~");

//障碍物&积分
//实时打印分数
ctx.print(0,1,&format!("Score:{}",self.score));

self.obstacle.render(ctx,self.player.x);
ifself.player.x>self.obstacle.x{
self.score+=1;//分数+1
self.obstacle=Obstacle::new(self.player.x+SCREEN_WIDTH,self.score);
}

ifself.player.y>SCREEN_HEIGHT||self.obstacle.hit_obstacle(&self.player){
self.mode=GameMode::End;
}
}

fnrestart(&mutself){
self.player=Player::new(5,25);
self.frame_time=0.0;
self.mode=GameMode::Playing;
//重置分数和障碍物
self.obstacle=Obstacle::new(SCREEN_WIDTH,0);
self.score=0;
}

fnmain_menu(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print_centered(5,"欢迎来到游戏~");
ctx.print_centered(8,"PressPkeytostartGame");
ctx.print_centered(9,"PressQtoquitGame");

ifletSome(key)=ctx.key{
matchkey{
VirtualKeyCode::P=>self.restart(),
VirtualKeyCode::Q=>ctx.quitting=true,
_=>{}
}
{}
}
}

fndead(&mutself,ctx:&mutBTerm){
ctx.cls();
ctx.print_centered(5,"你挂了..");
//挂了后显示一下分数
ctx.print_centered(6,&format!("本局获得了{}分",self.score));
ctx.print_centered(8,"按P键再来一局");
ctx.print_centered(9,"按Q键退出游戏");

ifletSome(key)=ctx.key{
matchkey{
VirtualKeyCode::P=>self.restart(),
VirtualKeyCode::Q=>ctx.quitting=true,
_=>{}
}
{}
}
}
}

implGameStateforState{
fntick(&mutself,ctx:&mutBTerm){
matchself.mode{
GameMode::Menu=>self.main_menu(ctx),
GameMode::End=>self.dead(ctx),
GameMode::Playing=>self.play(ctx),
}
}
}

structObstacle{
x:i32,
gap_y:i32,
size:i32,
}

implObstacle{
fnnew(x:i32,score:i32)->Self{
letmutrandom:RandomNumberGenerator=RandomNumberGenerator::new();
Obstacle{
x,
gap_y:random.range(10,40),
size:i32::max(2,20-score),
}
}

fnrender(&mutself,ctx:&mutBTerm,player_x:i32){
letscreen_x=self.x-player_x;
lethalf_size=self.size/2;

foryin0..self.gap_y-half_size{
ctx.set(screen_x,y,RED,BLACK,to_cp437('|'));
}

foryinself.gap_y+half_size..SCREEN_HEIGHT{
ctx.set(screen_x,y,RED,BLACK,to_cp437('|'));
}
}

fnhit_obstacle(&self,player:&Player)->bool{
lethalf_size=self.size/2;
letdoes_x_match=player.x==self.x;
letplayer_above_gap=player.y<self.gap_y-half_size;
letplayer_below_gap=player.y>self.gap_y+half_size;
does_x_match&&(player_above_gap||player_below_gap)
}
}

fnmain()->BError{
letcontext:BTerm=BTermBuilder::simple80x50()
.with_title("爽哥做游戏--FlappyDragon")
.build()" />

参考资料

[1]

使用 Rust 开发一个微型游戏【已完结】: https://www.bilibili.com/video/BV1vM411J74S

本文由 mdnice 多平台发布