当前位置: 首页 > news >正文

使用Rust开发小游戏

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


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(11"Hello,Bracket Terminal!");
    }
}

fn main() -> BError {
    let context: BTerm = BTermBuilder::simple80x50()
        .with_title("爽哥做游戏--Flappy Dragon")
        .build()?;

    main_loop(context, State {})
}

cargo run后,可以看到

alt



use bracket_lib::prelude::*;

// 游戏3种模式(菜单,游戏中,结束)
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())
}
alt


增加玩家


use bracket_lib::prelude::*;

// 游戏3种模式(菜单,游戏中,结束)
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(0self.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(525),
            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(00"按空格起飞~");

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

    fn restart(&mut self) {
        self.player = Player::new(525);
        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())
}
alt



增加障碍

use std::fmt::format;

use bracket_lib::prelude::*;

// 游戏3种模式(菜单,游戏中,结束)
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(0self.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(525),
            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(00"按空格起飞~");

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

        self.obstacle.render(ctx, self.player.x);
        if self.player.x > self.obstacle.x {
            self.score += 1// 分数+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(525);
        self.frame_time = 0.0;
        self.mode = GameMode::Playing;
        // 重置分数和障碍物
        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"你挂了..");
        // 挂了后显示一下分数
        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(1040),
            size: i32::max(220 - 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())
}
alt
alt

参考资料

[1]

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

本文由 mdnice 多平台发布

http://www.lryc.cn/news/246451.html

相关文章:

  • 笔记二十一、使用路由search进行传递参数
  • python多线程和多进程
  • VMware虚拟机网络配置详解
  • VUE语法--img图片不显示/img的src动态赋值图片显示
  • springboot+vue智能企业设备管理系统05k50
  • C++中的new、operator new与placement new
  • ElasticSearch之cat anomaly detectors API
  • Luminar Neo1.16.0(ai智能图像处理)
  • ElasticSearch之cat aliases API
  • bash编程 数组和for循环的应用
  • Python基础:标准库概览
  • C#,《小白学程序》第三课:类class,类的数组及类数组的排序
  • 建筑结构健康监测系统和传统人工监测的区别
  • 二 使用GPIO的复用功能 利用USART 实现printf()
  • C#中的警告CS0120、CS0176、CS0183、CS0618、CS0649、CS8600、CS8601、CS8602、CS8604、CS8625及处理
  • js中声明变量的关键字(const,let,var)
  • Android13 launcher循环切页
  • Java学习路线第一篇:Java基础(2)
  • 网络工程师精华篇,50种网络故障及解决方法大集合
  • Unity播放网络视频
  • SCI一区级 | Matlab实现GWO-CNN-LSTM-selfAttention多变量多步时间序列预测
  • 线性分类器--图像表示
  • 车载通信架构 —— 传统车内通信网络FlexRay(较高速度高容错、较灵活拓扑结构)
  • 如何在Ubuntu的Linux系统中安装MySQL5.7数据库
  • 基于Hadoop的区块链海量数据存储的设计与实现
  • 运行时错误/缺陷到底是什么缺陷
  • 应用Web3.0的5种方法提升你的点击量
  • 计算机服务器中了mallox勒索病毒如何处理,mallox勒索病毒解密文件恢复
  • 408—电子笔记分享
  • 【每日一题】子数组的最小值之和