Rust语言项目实战(三) - 创建主循环

回顾

在前面的章节中,我们大致已经完成了如下的工作:

  • 为游戏添加了音频文件
  • 为游戏准备了备用屏幕及设置
  • 为游戏准备了键盘的即时捕获输入的设置
  • 在退出游戏前恢复上述的设置

众所周知,游戏在不手动退出的情况下应该一直运行下去,因此所有的游戏机会都应该有一个主循环来保证游戏不会自动退出。

创建主循环

那么游戏主循环应该从哪里开始呢?当然是在我们准备好所有的配置之后了。 因此,我们将在// Terminal// Cleanup 两部分之间加入我们的游戏主循环:

fn main() -> Result<(), Box<dyn Error>>{
	snip[..]
	// Terminal
	let mut stdout = io::stdout();
	terminal::enable_raw_mode()?;
	stdout.execute(EnterAlternateScreen)?;
	stdout.execute(Hide)?;

    // Game Loop
    'gameloop: loop {
    }

	// Cleanup
    audio.wait();   // 等待播放结束
    stdout.execute(Show)?;
	stdout.execute(LeaveAlternateScreen)?;
	terminal::disable_raw_mode()?;
    Ok(())
}

在前面的章节中,我们提到了可以为循环打标签,上面的代码中,我们给主循环打了一个名为'gameloop的标签, 以便我们可以在游戏进行的任意位置跳出主循环,以结束游戏。

监听事件

在游戏中,我们主要是通过键盘的操作来控制玩家的行为,因此第一步我们需要定期的监控键盘事件,根据键盘事件来决定我们的行为:

snip[..]
    // Game Loop
    'gameloop: loop {
        // Input
        while event::poll(Duration::default())? {  				// 监听所有事件
            if let Event::Key(key_event) = event::read()? {  	// 检测到事件属于一个键盘事件
                match key_event.code {
                    KeyCode::Esc | KeyCode::Char('q') => {   	// 检测到`Esc`或`q`键被按下
                    	audio.play("lose");  					// 播放游戏失败的音乐
                        break 'gameloop;    					// 退出游戏主循环
                    }
                    _ => {}										// 其他键被按下不做操作
                }
            }
        }
    }
snip[..]

上面的代码中, 用到了event::poll, 这是一个事件监听器,他会定期的监听事件,间隔事件在参数中指定, 这个例子中使用Duration::default()作为参数,表示使用默认的间隔时间。

由于我们只监听键盘事件, 因此使用了if let这种模式匹配语法,当监听到键盘事件时,再用match去匹配判断具体是什么键盘事件。

这个例子中, 第一条匹配规则是Escq键被按下,则播放游戏失败的音乐,并退出游戏主循环。注意_ => {}这一行是不可或缺的,因为在前面的基础篇中提到了, match后面的分支必须是穷举的,如果不想一个一个列出来,就要用_代表一个默认分支。

测试退出功能

上面的代码实际上是实现了一个退出游戏的功能,即当游戏开始后, 如果玩家按下了Escq键,则会播放失败音乐并退出,现在让我们来测试一下, 先运行cargo run, 会看到代码的编译构建消息:
请添加图片描述
紧接着程序开始运行,这时会进入备用屏幕,我们会看到一块空白的终端屏幕:请添加图片描述
这时, 程序会一直监听系统重发生的事件, 这时我们按下任意键, 例如k, 这时主循环内监听到了键盘事件并对其进行匹配, 但是这个键并不是Esc或者q, 因此会进入match语句的默认分支,也就是不进行任何操作, 所以我们在界面上也看不到任何的反应。

此时我们再尝试按下q键, 会听到游戏播放失败的音乐“You lose”, 然后退出空白界面,回到正常的命令行终端中,如下:
请添加图片描述

小结

本章在前面的基础上加入了游戏主循环,并且实现了按指定键退出游戏的功能,到此为止,我们的游戏界面还是一片空白,没有任何的显示,下一章中,我们开始进行界面的绘制与渲染,并且将对我们的代码结构进行优化,使得代码结构更加的模块化。目前,我们的main.rs文件的完整内容如下:

// main.rs
use std::{error::Error, io, time::Duration};

use crossterm::{terminal::{self, EnterAlternateScreen, LeaveAlternateScreen}, ExecutableCommand, cursor::{Hide, Show}, event::{KeyCode, self, Event}};
use rusty_audio::Audio;

fn main() -> Result<(), Box<dyn Error>>{
    let mut audio = Audio::new();
    audio.add("explode", "./explode.wav");
    audio.add("lose", "./lose.wav");
    audio.add("move", "./move.wav");
    audio.add("pew", "./pew.wav");
    audio.add("startup", "./startup.wav");
    audio.add("win", "./win.wav");
    audio.play("startup");

	// Terminal
	let mut stdout = io::stdout();
	terminal::enable_raw_mode()?;
	stdout.execute(EnterAlternateScreen)?;
	stdout.execute(Hide)?;

    // Game Loop
    'gameloop: loop {
        // Input
        while event::poll(Duration::default())? {
            if let Event::Key(key_event) = event::read()? {
                match key_event.code {
                    KeyCode::Esc | KeyCode::Char('q') => {
                        break 'gameloop;
                    }
                    _ => {}
                }
            }
        }
    }

	// Cleanup
    audio.wait();   // 等待播放结束
    stdout.execute(Show)?;
	stdout.execute(LeaveAlternateScreen)?;
	terminal::disable_raw_mode()?;
    Ok(())
}

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

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

相关文章

编程好处、系统介绍、app演示

编程视频教学地址&#xff1a; 1、编程好处 1.1、自主开发 类似微信、qq等软件应用&#xff0c;解决人们日常生活问题 例如&#xff1a; 1&#xff09;你可以&#xff0c;自己开发一个网站&#xff0c;管理自己的日常生活照片&#xff0c;防止哪一天手机掉了或丢了&#xff0…

UVA11729 Commando War

UVA11729 Commando War 题面翻译 突击战 你有n个部下&#xff0c;每个部下需要完成一项任务。第i个部下需要你花Bj分钟交代任务&#xff0c;然后他就会立刻独立地、无间断地执行Ji分钟后完成任务。你需要选择交代任务的顺序&#xff0c;使得所有任务尽早执行完毕&#xff08…

高斯混合模型:GMM和期望最大化算法的理论和代码实现

高斯混合模型(gmm)是将数据表示为高斯(正态)分布的混合的统计模型。这些模型可用于识别数据集中的组&#xff0c;并捕获数据分布的复杂、多模态结构。 gmm可用于各种机器学习应用&#xff0c;包括聚类、密度估计和模式识别。 在本文中&#xff0c;将首先探讨混合模型&#xf…

【Java Web学习笔记】 1 - HTML入门

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/html 零、网页的组成 HTML是网页内容的载体。内容就是网页制作者放在页面上想要让用户浏览的信息&#xff0c;可以包含文字、图片视频等。 CSS样式是表现。就像网页的外衣。比如&#xff0c;标题字体、…

electerm下载和安装

electerm下载和安装 一、概述 electerm 是一款免费开源、基于electron/ssh2/node-pty/xterm/antd/ subx等libs的终端/ssh/sftp客户端(linux, mac, win)。 而且个人觉得electerm界面更好看一些&#xff0c;操作都是类似的。 二、下载安装 下载地址&#xff1a;https://elec…

正则表达式从放弃到入门(1):“正则表达式”是什么?

正则表达式从放弃到入门&#xff08;1&#xff09;&#xff1a;“正则表达式”是什么&#xff1f; 本博文转载自 这是一篇”正则表达式”扫盲贴&#xff0c;如果你还不理解什么是正则表达式&#xff0c;看这篇文章就对了。 如果你已经掌握了”正则表达式”&#xff0c;就不用再…

pip包管理工具

pip 是 Python 包管理工具&#xff0c;该工具提供了对Python包的查找、下载、安装、卸载的功能。 Python 2.7.9 或 Python 3.4 以上版本的python都自带 pip 工具 1. 配置pip国内镜像 pip安装的包都存在于外国的服务器上&#xff0c;速度会非常慢&#xff0c;可以给pip配置国内…

全栈冲刺 之 一天速成MySQL

一、为什么使用数据库 数据储存在哪里&#xff1f; 硬盘、网盘、U盘、光盘、内存&#xff08;临时存储&#xff09; 数据持久化 使用文件来进行存储&#xff0c;数据库也是一种文件&#xff0c;像excel &#xff0c;xml 这些都可以进行数据的存储&#xff0c;但大量数据操作…

arcgis投影栅格不可用

1、使用【投影栅格】工具进行栅格数据投影转换时报错。 解决方法&#xff1a;如果使用的是arcgis10.5及以下的版本&#xff0c;则需要更换更高的版本&#xff0c;因为这个是软件问题&#xff0c;需要更换到arcgis10.6及以上版本&#xff0c;更高级别的版本已经修复了这个问题。…

【题目】链表相关算法题

文章目录 一. 合并两个有序链表题目解析算法原理代码编写 二. 相交链表问题题目解析算法原理代码编写 三. 环形链表问题1. 判断是否有环2. 计算环的长度3. 找到环的入口点 四. 反转链表方法一&#xff1a;边迭代、边逆置方法二&#xff1a;头插 五. 判断链表是否回文题目解析算…

LinkedList详解

LinkedList详解 LinkedList是List接口的一个主要的实现类之一&#xff0c;基于链表的实现。以java8为例来了解一下LinkedList的源码实现 继承关系 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>,…

进制转化总结

来源&#xff0c;做个笔记&#xff0c;讲的还蛮清楚通信原理-2.5 数据封装与传输05_哔哩哔哩_bilibili ip地址范围

6 新建工程——寄存器

文章目录 6.1 本地新建工程文件夹6.2 新建工程6.2.1 选择CPU型号6.2.2 在线添加库文件6.2.3 添加文件6.2.4 复制存储器分配文件6.2.5 配置选项卡6.2.5.1 Linker6.2.5.2 Target6.2.5.3 Output 选项卡6.2.5.4 Listing 选项卡6.2.6 下载器配置 版本说明&#xff1a;MDK5.24 6.1 本…

许战海战略文库|重回大众视野的健力宝如何重生

摘要&#xff1a;销售额连续7年没有增长;产业主品牌定位不清晰;产品不协同缺少产品战略;子品牌无法形成合力新产品共性不足;过度差异化缺少渠道战略;被渠道能力更强的品牌挤压。火遍世界的“东方魔水”从第一品牌到被人遗忘&#xff0c;健力宝该如何重生? 健力宝诞生于1984年&…

css 三栏布局的实现

三栏布局在前端页面设计中是一个常见的布局方式&#xff0c;通常包含左侧、中间和右侧三个部分。这种布局方式在多种场景中都很受欢迎&#xff0c;例如博客、新闻网站和企业官网。本文将详细介绍三栏布局的实现方法&#xff0c;包括用法、代码、深入理解&#xff0c;以及配合高…

Python编程基础:输入/输出函数、注释与缩进

Python是一种简单易学的编程语言&#xff0c;广泛应用于Web开发、数据分析、人工智能等领域。无论您是初学者还是有一定编程经验的人士&#xff0c;都可以从Python的基础知识开始建立自己的编程技能。 目录 理论Python语言的发展程序设计语言的分类静态语言与脚本语言的区别 代…

解决element ui tree组件不产生横向滚动条

结果是这样的 需要在tree的外层&#xff0c;包一个父组件 <div class"tree"><el-tree :data"treeData" show-checkbox default-expand-all></el-tree></div> 在css里面这样写,样式穿透按自己使用的css编译器以及框架要求就好 &l…

笔记:Pika Labs 3D 动画生成工具

Pika Labs 一款3D 动画生成工具 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134657306 目 录 1. 简介2. 准备2.1 安装 discord2.2 加入 Discord 频道 3. Pika 使用指南2.1 快速开始2.2 从图像到视频2.3 Pika Bot按钮2.4 提示&#xff08;Prompt&a…

WPF Live Charts2 自学笔记

文章目录 前言实现效果微软平台的历史问题 WPF 项目搭建Nuget添加额外框架添加项目初始化livecharts配置其它LiveCharts2 案例简单案例Demo示例ViewViewModel GPU渲染 Github地址仓库 前言 LiveChart 是C# 上面很受欢迎的统计图 UI控件。最近在学WPFhalcon开发&#xff0c;想想…

肖sir__mysql之单表练习题2__(2)

mysql之单表练习题 一.建表语句 create table grade(class int(4),chinese int(8),english int(4),math int(8),name varchar(20),age int(8),sid int(4)primary key auto_increment) DEFAULT charsetutf8; insert into grade(class,chinese,english,math,name,age)values(1833…