使用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 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/190876.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高校大学校园后勤移动报修系统 微信小程序uniapp+vue

本文主要是针对线下校园后勤移动报修传统管理方式中管理不便与效率低的缺点&#xff0c;将电子商务和计算机技术结合起来&#xff0c;开发出管理便捷&#xff0c;效率高的基于app的大学校园后勤移动报修app。该系统、操作简单、界面友好、易于管理和维护&#xff1b;而且对后勤…

微机11111

一、填空题&#xff08;共15分&#xff0c;每空1分&#xff09; 1、十六进制数30A.5转换为二进制是__________&#xff0c;转换为十进制是_________ 001100001010.0101B 778.3125 十六进制转换二进制 将一位十六进制分解成四位二进制 十六进制转换十进制 3X1620X16110X1605X1…

解决Vue编程式导航路由跳转不显示目标路径问题

我们配置一个编程式导航的路由跳转&#xff0c;跳转到 /search 页面&#xff0c;并且携带categoryName和categoryId两个query参数。 this.$router.push({path: "/search",query: {categoryName: dataset.categoryname,categoryId: dataset.categoryid} }) 如果我们…

Qt 网络通信

获取本机网络信息 &#xff08;1&#xff09;在 .pro 文件中加入 QT network&#xff08;2&#xff09; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> #include <QLabel> #include <QLineEdit> #include <QPu…

C语言学习笔记之函数篇

与数学意义上的函数不同&#xff0c;C语言中的函数又称为过程&#xff0c;接口&#xff0c;具有极其重要的作用。教科书上将其定义为&#xff1a;程序中的子程序。 在计算机科学中&#xff0c;子程序&#xff08;英语&#xff1a;Subroutine, procedure, function, routine, me…

【Spring】Spring事务详解

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…

基于springboot+vue的学生宿舍管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

单片机学习6——定时器/计数功能的概念

在8051单片机中有两个定时器/计数器&#xff0c;分别是定时器/计数器0和定时器/计数器1。 T/C0: 定时器/计数器0 T/C1: 定时器/计数器1 T0: 定时器0 T1: 定时器1 C0: 计数器0 C1: 计数器1 如果是对内部振荡源12分频的脉冲信号进行计数&#xff0c;对每个机器周期计数&am…

苹果的未来:分析其成长策略和 2 兆美元以上的野心

Apple正在蕴育新的创新增长。作为世界上最有价值的公司&#xff0c;苹果公司拥有超过2万亿美元的市值和超过1000亿美元的年利润&#xff0c;并成功用十几年实践去打造和培育了一个硬件、软件和服务“三位一体”的商业生态&#xff0c;始终坚持以用户体验为先&#xff0c;创新极…

地铁在线售票vue票务系统uniAPP+vue 微信小程序

功能介绍 管理员 &#xff08;1&#xff09;管理员登录功能 &#xff08;2&#xff09;查看和修改线路信息 &#xff08;3&#xff09;减少线路 &#xff08;4&#xff09;修改价格&#xff08;5站3元 5-10 5元 10-15站6元 往上8元&#xff09; &#xff08;5&#xff09;删除用…

手摸手vue2+Element-ui整合Axios

后端WebAPI准备 跨域问题 为了保证浏览器的安全,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,称为同源策略,同源策略是浏览器安全的基石 同源策略( Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能 所谓同源(即指在同一个域)就是两个页面具…

TDA笔记:夏克林老师,南洋理工大学

TDA比传统的统计方法有优势&#xff1a;benchmark中展现了这种优势 laplacian矩阵 多种单纯复形构造方式&#xff0c;可以构造出不同表征 二部图&#xff1a;Dowker complex Tor algebra可以用到多大数据 目前较新

竞赛选题 题目:基于卷积神经网络的手写字符识别 - 深度学习

文章目录 0 前言1 简介2 LeNet-5 模型的介绍2.1 结构解析2.2 C1层2.3 S2层S2层和C3层连接 2.4 F6与C5层 3 写数字识别算法模型的构建3.1 输入层设计3.2 激活函数的选取3.3 卷积层设计3.4 降采样层3.5 输出层设计 4 网络模型的总体结构5 部分实现代码6 在线手写识别7 最后 0 前言…

@Async注解的坑,小心

背景 前段时间&#xff0c;一个同事小姐姐跟我说她的项目起不来了&#xff0c;让我帮忙看一下&#xff0c;本着助人为乐的精神&#xff0c;这个忙肯定要去帮。 于是&#xff0c;我在她的控制台发现了如下的异常信息&#xff1a; Exception in thread "main" org.s…

传奇,全职业刀刀烈火原理揭秘

相信很多朋友都玩过传奇, 今天我们来揭秘一下,刀刀烈火的实现原理, 其实非常简单. 烈火作为一个技能,使用流程是先释放技能, 获得一个烈火附加的状态,那么下一次攻击就会带烈火效果了. 这里我们拿烈火附加状态,当突破口,进行扫描即可. 绝大部分情况应该是有状态为1(真),没状…

NX二次开发UF_CURVE_ask_wrap_curve_parents 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_wrap_curve_parents Defined in: uf_curve.h int UF_CURVE_ask_wrap_curve_parents(tag_t curve_tag, tag_t * defining_face, tag_t * defining_plane, tag_t * defin…

【KubeSphere】基于AWS在 Linux 上以 All-in-One 模式安装 KubeSphere

文章目录 一、实验配置说明二、实验准备工作1.确认系统版本2. 修改网络DNS3. 关闭SELINUX4. 关闭防火墙 三、实验依赖项安装四、下载 KubeKey五、一键化安装部署六、验证安装结果七、登录KubeSphere管理控制台八、参考链接 一、实验配置说明 本实验基于AWS启动一台新实例&…

电子学会C/C++编程等级考试2021年06月(三级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:数对 给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍。 比如给定1 4 3 2 9 7 18 22,得到的答案是3,因为2是1的两倍,4是2个两倍,18是9的两倍。 时间限制:1000 内存限制…

小程序如何进行版本升级

小程序版本升级是非常重要的&#xff0c;它可以帮助商家及时更新功能、修复bug&#xff0c;提升用户体验&#xff0c;增加小程序的竞争力。那么&#xff0c;商家怎么进行小程序版本升级呢&#xff1f;下面具体介绍。 在小程序管理员后台->版本设置处&#xff0c;会显示是否…

Django之Auth认证模块

文章目录 一、简介二、Auth模块是什么三、Auth模块常用方法create_user() 创建普通用户authenticate() 用户认证auth.login(HttpResponse&#xff0c;user)登录状态保持is_authenticated 登录认证判断auth.loginout(reqeust)退出登录login_required() 登录认证装饰器check_pass…