虚拟键代码

 

虚拟键代码

虚拟键码 (Winuser.h) - Win32 apps | Microsoft Learn

在Windows操作系统中,虚拟键代码(Virtual-Key Codes)是一组用来表示键盘上按键的数值。这些代码通常用于Windows API函数,以便程序能够识别和处理键盘输入。
虚拟键代码是按键的物理位置定义的,而不是按字符本身定义的。这意味着,无论用户的键盘布局如何,同一物理按键的虚拟键代码都是相同的。例如,无论用户使用的是美式键盘、德式键盘还是日式键盘,字母 'A' 键的虚拟键代码都是 `VK_A`。
虚拟键代码通常以 `VK_` 开头,后面跟着一个或多个大写字母,表示特定的按键。例如:
- `VK_A` 表示 'A' 键。
- `VK_B` 表示 'B' 键。
- `VK_SPACE` 表示空格键。
- `VK_RETURN` 表示回车键。
- `VK_ESCAPE` 表示 ESC 键。
- `VK_UP` 表示向上箭头键。
- `VK_DOWN` 表示向下箭头键。
- `VK_LEFT` 表示向左箭头键。
- `VK_RIGHT` 表示向右箭头键。
- `VK_F1` 到 `VK_F12` 表示功能键 F1 到 F12。
在程序中,可以通过 `GetAsyncKeyState`、`GetKeyState` 或 `TranslateMessage` 等Windows API函数来检测虚拟键代码,从而判断用户是否按下了某个键。
 

if (KEY_PRESS(VK_UP) && ps->_SNAKE_DIR != DOWN)
{ps->_SNAKE_DIR = UP;
}

这里的 `KEY_PRESS(VK_UP)` 是一个宏或函数,用来检查用户是否按下了向上箭头键(`VK_UP`)。如果按下了,并且蛇当前的方向不是向下(`DOWN`),则将蛇的方向设置为向上(`UP`)。
这些虚拟键代码使得开发者能够以一种与键盘布局无关的方式处理键盘输入,从而编写出更加通用和易于移植的软件。
简单的说虚拟键代码的目的就是,进行识别是否按键

封装一个宏

我们封装一个宏,进行虚拟键代码的判断

#define KEY_PRESS(vk) (GetAsyncKeyState(vk)&1?1:0)

宏 `KEY_PRESS(vk)` 是一个用于检测指定虚拟键 `vk` 是否被按下的辅助宏。它使用了 `GetAsyncKeyState` 函数,这是Windows API中的一个函数,用于检查异步键盘输入的状态。


下面是宏 `KEY_PRESS(vk)` 的详细解释:
- `GetAsyncKeyState(vk)`:这个函数接受一个虚拟键代码 `vk` 作为参数,并返回该键的异步键状态。返回值是一个16位的整数,其中第15位(从最低位开始的最高位)表示该键是否被按下。如果该位为1,则键被按下;如果为0,则键没有按下。


- `&1`:这是一个位运算符,用于对 `GetAsyncKeyState(vk)` 的返回值进行按位与操作。这里 `1` 表示二进制的最低位为1,其他位为0。因此,`&1` 操作实际上是在检查

`GetAsyncKeyState(vk)` 返回值的第15位是否为1。


- `? :`:这是C语言中的三元条件运算符。如果 `GetAsyncKeyState(vk)&1` 的结果为真(非零),则表达式的值为 `1`,表示键被按下;如果为假(零),则表达式的值为 `0`,表示键没有被按下。


综上所述,`KEY_PRESS(vk)` 宏的目的是简化对 `GetAsyncKeyState` 函数的调用,并返回一个布尔值(0或1),指示指定的虚拟键 `vk` 是否被按下。在您的代码中,这个宏被用于检测用户的键盘输入,并根据这些输入来更新蛇的方向或游戏状态。
 

按键信息(贪吃蛇为例进行举例)

//蛇的运行逻辑
void Snake_RunGame(pSnake_State ps)
{do{//打印分数Snake_Cursor_Position(90, 20);wprintf(L"当前的得分是:%d", ps->_SNAKE_SCORE);Snake_Cursor_Position(90, 24);wprintf(L"一个食物的分数是:%d", ps->_SNAKE_ONE_FOOD);if (KEY_PRESS(VK_UP) && ps->_SNAKE_DIR != DOWN){ps->_SNAKE_DIR = UP;}else if (KEY_PRESS(VK_DOWN) && ps->_SNAKE_DIR != UP){ps->_SNAKE_DIR = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->_SNAKE_DIR != RIGHT){ps->_SNAKE_DIR = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->_SNAKE_DIR != LEFT){ps->_SNAKE_DIR = RIGHT;}if (KEY_PRESS(VK_ESCAPE))//退出{ps->_SNAKE_STATE = KILL_ESE;}if (KEY_PRESS(VK_F4))//减速{if (ps->_SNAKE_ONE_FOOD > 10){ps->_SNAKE_SLEEP_TIME += 30;ps->_SNAKE_ONE_FOOD = ps->_SNAKE_ONE_FOOD - 5;}}if (KEY_PRESS(VK_F3))//加速{if (ps->_SNAKE_ONE_FOOD < 45){ps->_SNAKE_SLEEP_TIME -= 30;ps->_SNAKE_ONE_FOOD = ps->_SNAKE_ONE_FOOD + 5;}}if (KEY_PRESS(VK_SPACE))//暂停{SNAKEVK_SPACE();}//蛇的移动Snake_move(ps);//蛇的每次移动的休眠时间Sleep(ps->_SNAKE_SLEEP_TIME);} while (ps->_SNAKE_STATE == OK);
}

这段代码定义了一个函数 `Snake_RunGame`,它实现了蛇形游戏的主要运行逻辑。这个函数包含了蛇的移动、用户输入的检测、得分的更新以及游戏速度的控制。
下面是代码的解释:


1. `Snake_RunGame` 函数接受一个指向 `Snake_State` 结构的指针 `ps`,这个结构包含了蛇的状态信息,如头节点、状态、休息时间、得分等。


2. 函数使用一个 `do-while` 循环来持续运行游戏,直到蛇的状态不再是 `OK`(例如,蛇撞墙或吃到自己时)。


3. 在循环内部,首先使用 `Snake_Cursor_Position` 和 `wprintf` 函数打印当前得分和一个食物的分数。


4. 接下来,使用 `KEY_PRESS` 宏(或函数)来检测用户的键盘输入。根据用户按下的键(上、下、左、右箭头键),更新蛇的方向。如果蛇当前不是朝相反方向移动,蛇的方向会被更新。


5. 如果用户按下 `ESC` 键,游戏状态被设置为 `KILL_ESE`,表示游戏结束。


6. 如果用户按下 `F4` 键,游戏速度会减慢,蛇的休息时间增加,同时每个食物的分数减少。


7. 如果用户按下 `F3` 键,游戏速度会加快,蛇的休息时间减少,同时每个食物的分数增加。


8. 如果用户按下空格键,游戏会暂停。这可能是通过调用一个名为 `SNAKEVK_SPACE` 的函数实现的,但这个函数在提供的代码片段中没有定义。


9. `Snake_move` 函数被调用来处理蛇的移动逻辑。这个函数可能会更新蛇的位置,检查是否有食物被吃掉,以及蛇是否撞墙或吃到自己。


10. `Sleep` 函数用于控制游戏的更新速度,根据 `ps->_SNAKE_SLEEP_TIME` 的值来暂停一段时间。


11. `do-while` 循环的条件是蛇的状态为 `OK`,如果蛇的状态变为其他值(如 `KILL_ESE`),循环结束,游戏结束。


这个函数是蛇形游戏的核心部分,它负责处理游戏的主要逻辑和用户交互。在实际的游戏中,`Snake_move` 函数的实现细节对于游戏的行为至关重要。
 

这里代码有些函数是写完直接进行调用的,下面我会一一进行解释

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言刷题系列】移除元素

目录 一、问题描述 二、解题思路 三、源代码 个人主页&#xff1a; 倔强的石头的博客 系列专栏 &#xff1a;C语言指南 C语言刷题系列 一、问题描述 二、解题思路 在C语言中&#xff0c;原地移除数组中所有等于特定值的元素并返回新长度的问题可以通过双指针法…

SpringCloud——consul

SpringCloud——consul 一、consul安装与运行二、consul 实现服务注册与发现1.引入2.服务注册3.服务发现 三、consul 分布式配置1.基础配置2.动态刷新3.配置持久化 四、参考 Eureka已经停止更新了&#xff0c;consul是独立且和微服务功能解耦的注册中心&#xff0c;而不是单独作…

计算机组成结构—高速缓冲存储器(Cache)

目录 一、Cache的基本工作原理 1.Cache工作原理 2.命中率 3.Cache的基本结构 4.Cache的改进 二、Cache和主存之间的映射方式 1.直接映射 2.全相联映射 3.组相联映射 三、Cache中主存块的替换算法 四、Cache的写策略 概为了解决 CPU 和主存之间速度不匹配的问题&#x…

复写零(双指针)

下面的解法需要手动画图&#xff0c;举例去体会&#xff0c;只有自己手动去做了&#xff0c;才会有所收获。 class Solution {public void duplicateZeros(int[] arr) {int n arr.length;//先找到最后一个元素的位置;//至于为什么要直接先设dest 为-1&#xff0c;这是经过研究…

Celery(分布式任务队列)入门学习笔记

Celery 的简单介绍 用 Celery 官方的介绍&#xff1a;它是一个分布式任务队列; 简单&#xff0c;灵活&#xff0c;可靠的处理大量消息的分布式系统; 它专注于实时处理&#xff0c;并支持任务调度。 Celery 如果使用 RabbitMQ 作为消息系统的话&#xff0c;整个应用体系就是下…

代码本地化

目的 代码本地化&#xff08;Localization&#xff09;是指将软件应用程序中的文本、图形、声音和其他内容翻译成特定语言的过程&#xff0c;同时确保这些内容在目标文化中适当地呈现。本地化不仅仅是对文本进行翻译&#xff0c;还包括对日期、时间、数字、货币、排序顺序、文本…

​《MATLAB科研绘图与学术图表绘制从入门到精通》示例:绘制德国每日风能和太阳能产量3D线图

在MATLAB中&#xff0c;要绘制3D线图&#xff0c;可以使用 plot3 函数。 在《MATLAB科研绘图与学术图表绘制从入门到精通》书中通过绘制德国每日风能和太阳能产量3D线图解释了如何在MATLAB中绘制3D线图。 购书地址&#xff1a;https://item.jd.com/14102657.html

自动驾驶融合定位系列教程四:惯性导航解算

自动驾驶融合定位系列教程四&#xff1a;惯性导航解算 一、概述 惯性导航的解算是一个实现起来非常简单&#xff0c;但是理解起来要费一番功夫的东西&#xff0c;所谓“实现”就是把公式变成代码&#xff0c;所谓“理解”&#xff0c;就是要弄明白几个公式是怎么推导出来的。…

滑动窗口 | 1652. 拆炸弹 |LeetCode

文章目录 题目介绍暴力(可以过力扣竟然。不愧是简单题)&#xff1a;滑动窗口 祝你天天开心 题目介绍 你有一个炸弹需要拆除&#xff0c;时间紧迫&#xff01;你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。 为了获得正确的密码&#xff0c;你需要替换掉每…

【数据结构】C++语言实现栈(详细解读)

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

multipass和multipassd命令的区别

multipassd通常是multipass服务的后台守护进程&#xff0c;它负责管理和控制虚拟机实例。 命令区别 例&#xff1a; multipass restart my-vm 这个命令用于重启Multipass中的虚拟机实例。例如有一个名为my-vm的虚拟机实例。 multipassd restart 这会重新启动Multipass后台…

达梦主从数据库实例恢复

测试环境&#xff1a;实时主备数据库 1、在节点1向测试表aaa插入数据 如图可见&#xff0c;会话139695153554808向aaa表插入了10000行数据。事务id460520。 2、提交前在另一个窗口kill掉dmserver进程。 3、查看节点2的数据库日志 上图可见&#xff0c;系统执行alter database…