首先感谢顽石老师的讲解,十分清晰易懂,附上b站视频链接【C/C++游戏项目教程】趣味编程—黑客帝国数字雨,侵权请联系我删除。

以下为效果图:

效果视频如链接视频所示黑客帝国数字雨效果视频。
——————————————————
我用的VS2022写的,也遇到了一些问题,在后续代码中会尽量标注出来。
全部代码如下所示:

#define _CRT_SECURE_NO_WARNINGS 1
#undef UNICODE //用于防止outtextxy报错
#undef _UNICODE //用于防止outtextxy报错/*总步骤:1、数字雨在下落,雨是字符串,用rand()随机生成字符串2、用数组保存字符串
*/#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <graphics.h> //非标准头文件,需要安装EasyX图形库才能使用#define STR_SIZE 20 //字符串大小(默认20)
#define STR_NUM 512 //字符串条数(默认128)
#define STR_WIDTH 15 //字符之间间隔(默认15)
#define WIN_WIDTH  3120//窗口宽度(默认1024,此电脑为3120)
#define WIN_HEIGHT 2080 //窗口高度(默认640,此电脑为2080)//用结构体存储字符串最合适
struct Rain {int x, y; //雨的坐标int speed; //下落速度char str[STR_SIZE]; //每一串数字雨
}rain[STR_NUM];//随机生成字符
char CreateCh() {char temp = 0;int flag = rand() % 3; //0 1 2if (flag == 0) {temp = rand() % 26 + 'A'; //0-25}else if(flag == 1) {temp = rand() % 26 + 'a';}else {temp = rand() % 10 + '0';}  return temp; //返回一个字符
}//初始化游戏各个参数
void GameInit() {//创建一个窗口initgraph(WIN_WIDTH, WIN_HEIGHT);//设置随机数种子,语句要放在函数里面srand((unsigned)time(NULL)); //初始化字符串for (int i = 0; i < STR_NUM; i++) {for (int k = 0; k < STR_SIZE; k++) {rain[i].str[k] = CreateCh(); //对数字雨逐个赋值}}//初始化坐标和速度for (int i = 0; i < STR_NUM; i++) {rain[i].x = i * STR_WIDTH; //0 15 30 45......rain[i].y = rand() % WIN_HEIGHT;rain[i].speed = rand() % 5 + 2; //防止为0,要加一个数}
}//绘制画面
void GameDraw() {for (int i = 0; i < STR_NUM; i++) {for (int k = 0; k < STR_SIZE; k++) {//设置背景颜色setbkmode(TRANSPARENT);//通过计算255/STR_WIDTH=13,即每个字符颜色相差13settextcolor(RGB(0, 255 - 13 * k, 0));//竖着打印出每条字符串,并且控制好间隔outtextxy(rain[i].x, rain[i].y - STR_WIDTH * k, rain[i].str[k]);}}
}//随机改变已出现的字符串中的字符
void ChangeCh() {for (int i = 0; i < STR_NUM; i++) {rain[i].str[rand() % STR_SIZE] = CreateCh();}
}//使数字雨移动起来
void RainMove() {for (int i = 0; i < STR_NUM; i++) {rain[i].y += rain[i].speed;if (rain[i].y - STR_WIDTH * STR_SIZE > WIN_HEIGHT) {rain[i].y = 0;}}
}int main() {GameInit();BeginBatchDraw(); //开始双缓冲绘图//调用死循环让画面一直更新while (1) {cleardevice(); //每次更新要清除之前的画面GameDraw();FlushBatchDraw(); //绘制ChangeCh();RainMove();}EndBatchDraw(); //getchar(); //防止程序闪退return 0;
}

———————————分割线———————————
接下来我将详细描述代码作用:

首先第一部分

#define _CRT_SECURE_NO_WARNINGS 1
#undef UNICODE //用于防止outtextxy报错
#undef _UNICODE //用于防止outtextxy报错

第一句是针对VS2022以及之前的一些版本都有一些情况,即遇到我们C/C++中常用语句都会报错,在.cpp文件开头加上这一句话可以消除警告并正常运行。
后两句是为了防止后续会用到的outtextxy()函数的报错,后续会详细介绍。

——————————————

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <graphics.h> //非标准头文件,需要安装EasyX图形库才能使用

这些是需要用到的头文件,其中stdlib.h是用到了srand()来生成随机数种子,time.h也是帮助生成随机数种子,而graphics.h需要我们电脑安装EasyX,非常简单,进入EasyX官网,如下图:

点右边的圈直接下载,点左边的圈有安装教程,基本上支持全部版本的VS,连我的目前最新的VS2022也支持自动安装,十分方便。

其可以自动识别你的电脑里的VS版本,直接一键安装上去,就完成了。
————————————

#define STR_SIZE 20 //字符串大小(默认20)
#define STR_NUM 512 //字符串条数(默认128)
#define STR_WIDTH 15 //字符之间间隔(默认15)
#define WIN_WIDTH  3120//窗口宽度(默认1024,此电脑为3120)
#define WIN_HEIGHT 2080 //窗口高度(默认640,此电脑为2080)

用宏定义来定义一些后续代码经常用的一些固定量,你后续修改成自己喜欢的参数也可以直接在这里改。
我们的每条数字雨其实就是一个字符串,其中:
STR_SIZE为字符串大小,表示每条数字雨有多少个字符;
STR_NUM为字符串条数,即为全部一共有多少条数字雨在屏幕上;
STR_WIDTH为字符之间间隔,表示字符串中每个字符之间的间距,调整好后可以使数字雨更美观;
WIN_WIDTH和WIN_HEIGHT用来调整显示数字雨窗口的大小,我调成了我电脑屏幕分辨率的大小,你可以任意该,我是想把这个当屏保,但是最顶上的一条程序的白边还是无法去掉,若有可以去掉白边实现全屏的办法,欢迎分享。
————————————

//用结构体存储字符串最合适
struct Rain {int x, y; //雨的坐标int speed; //下落速度char str[STR_SIZE]; //每一串数字雨
}rain[STR_NUM];

前面我们说了每条数字雨就是一个字符串,但每条数字雨除了它所展示的字符,还有诸如这条雨的x,y坐标,以及其下落速度这些属性,所以我们用结构体struct来存储数字雨。然后便定义一个结构体变量rain[],其大小为数字雨的全部条数,即前面宏定义过的STR_NUM。
————————————

int main() {GameInit();BeginBatchDraw(); //开始双缓冲绘图//调用死循环让画面一直更新while (1) {cleardevice(); //每次更新要清除之前的画面GameDraw();FlushBatchDraw(); //绘制ChangeCh();RainMove();}EndBatchDraw(); //getchar(); //防止程序闪退return 0;
}

先来看我们的主函数,我们依然把游戏的各个功能都封装为单独的函数,在主函数中直接调用即可,这样更简洁,而且后续要修改某一功能也更容易,这种思想在实际项目中很常见而且实用,在学习用其它语言例如Python写类似的游戏和项目时也会大量的运用这种思想。
接下来我们来看主函数中调用的各个函数的写法:
——————————————

//随机生成字符
char CreateCh() {char temp = 0;int flag = rand() % 3; //0 1 2if (flag == 0) {temp = rand() % 26 + 'A'; //0-25}else if(flag == 1) {temp = rand() % 26 + 'a';}else {temp = rand() % 10 + '0';}  return temp; //返回一个字符
}

首先是最主要的生成字符的函数CreateCh(),其返回的就是字符char。
数字雨中的字符是随机的,所以我们用rand()模上3,会有0、1、2三种情况,分别生成大写字母、小写字母、数字,这样数字雨更加多样化,看起来也更炫酷。
——————————————

//初始化游戏各个参数
void GameInit() {//创建一个窗口initgraph(WIN_WIDTH, WIN_HEIGHT);//设置随机数种子,语句要放在函数里面srand((unsigned)time(NULL)); //初始化字符串for (int i = 0; i < STR_NUM; i++) {for (int k = 0; k < STR_SIZE; k++) {rain[i].str[k] = CreateCh(); //对数字雨逐个赋值}}//初始化坐标和速度for (int i = 0; i < STR_NUM; i++) {rain[i].x = i * STR_WIDTH; //0 15 30 45......rain[i].y = rand() % WIN_HEIGHT;rain[i].speed = rand() % 5 + 2; //防止为0,要加一个数}
}

游戏初始化函数GameInit(),用于在游戏每次开始时设定好一些参数,跟前面的宏定义有点类似,但不一样,因为各个地方都要用到的一些常量必须要先定义,它们便放在最一开始的宏定义中。
initgraph()用于创建一个你指定大小的窗口,我们指定的大小就已在宏定义中实现了。这个函数是EasyX中的。
srand()用来设置随机数种子,根据电脑的时间来变化,以保证每次程序运行时所产生的伪随机数是不一样的,让我们的数字雨看上去变幻莫测,不然每次打开程序都是一样的字符,没啥意思。
接下来的嵌套循环就是给每条数字雨的每个字符逐个赋值。
然后是初始化坐标和速度,电脑屏幕向右为x轴正方向,向下为y轴正方向。x坐标要保证相邻的数字雨保持一定间隔;y坐标要在窗口里随机,以此来营造出下雨的感觉;每条数字雨下落的速度也要随机,因为好看,但要防止速度为0,所以要加上一个大于0的数,这里取的模和加的数你可以自己调整,来适应你的窗口大小,以及你自己感觉看的舒服。
——————————————

//绘制画面
void GameDraw() {for (int i = 0; i < STR_NUM; i++) {for (int k = 0; k < STR_SIZE; k++) {//设置背景颜色setbkmode(TRANSPARENT);//通过计算255/STR_WIDTH=13,即每个字符颜色相差13settextcolor(RGB(0, 255 - 13 * k, 0));//竖着打印出每条字符串,并且控制好间隔outtextxy(rain[i].x, rain[i].y - STR_WIDTH * k, rain[i].str[k]);}}
}

这个绘制画面函数GameDraw()主要用来设置颜色,并通过EasyX中的outtextxy()来打印出每条数字雨。
我们对每条字符串中的绿色设置的是渐变暗的颜色。
这里尤其要注意这个outtextxy(),直接调用都会报错,详细见outtextxy编译错误,感谢分享。不过我试了好多次第三种方法,我的VS就是持续报错,所以我用的方法二,即在代码最前面加上如下代码便可解决问题:

#undef UNICODE //用于防止outtextxy报错
#undef _UNICODE //用于防止outtextxy报错

接着,我们要解决要竖着打印字符串的问题,即在打印时让第k个字符y坐标距离字符串首个y坐标k倍的间隔长度,即第一个字符在下面,第二个在第一个的上面1倍的STR_WIDTH距离处,第三个在第一个上面2倍的STR_WIDTH距离处,以此类推。
————————————————

//随机改变已出现的字符串中的字符
void ChangeCh() {for (int i = 0; i < STR_NUM; i++) {rain[i].str[rand() % STR_SIZE] = CreateCh();}
}

若每条数字雨中的字符在下落时都是实时在变化的,那就更酷炫了,ChangeCh()让每条数字雨中的随机字符再赋一遍值,这里便可以直接调用前面写好的CreateCh()函数。
————————————————

//使数字雨移动起来
void RainMove() {for (int i = 0; i < STR_NUM; i++) {rain[i].y += rain[i].speed;if (rain[i].y - STR_WIDTH * STR_SIZE > WIN_HEIGHT) {rain[i].y = 0;}}
}

接着我们要让每条字符串向下移动,主函数每调用一次该RainMove()函数,每条数字雨的y坐标便加上speed即下落速度。
但要注意,当每条字符串的最后一个字符掉到窗口最下端之后,重置该字符串首元素的y值,要不然所有字符串掉出屏幕后就没东西在屏幕上了。
——————————————
最后,再来回到主函数上:

int main() {GameInit();BeginBatchDraw(); //开始双缓冲绘图//调用死循环让画面一直更新while (1) {cleardevice(); //每次更新要清除之前的画面GameDraw();FlushBatchDraw(); //绘制ChangeCh();RainMove();}EndBatchDraw(); getchar(); //防止程序闪退return 0;
}

首先,调用GameInit(),初始化参数。
接着,调用BeginBatchDraw(),它是EasyX中的函数,作用是解决屏幕不停更新导致的频闪问题,需要结合后面的FlushBatchDraw()以及EndBatchDraw()一起使用,具体原理可以参考防闪屏批量绘图。
然后,使用while (1)死循环让画面一直更新,循环中每次先清除之前的画面,再调用GameDraw()绘制画面,然后用FlushBatchDraw()绘制,接着调用ChangeCh()来改变数字雨中字符,然后用RainMove()使数字雨动起来。
最后加上程序结尾,全部大功告成。
————————————————
在开头提到的b站视频教程中,老师在此之后还加上了背景音乐和其它特效,音乐这块我只能提醒用Apple Music导出的.m4p文件貌似不能成功运行,一般的正常的.mp3文件应该可以。不过由于我没有找到我认为适合这个屏保风格的音乐,我就没做进去背景音乐,包括一些其它特效,有需要的可以自己看视频后面部分加进去。
————————————————
遗憾的是,我想达到的屏保效果一直没有实现,由于上方的程序的白条无法去除,我找不到EasyX中有实现全屏的方法,也试过调整分辨率到很大,均无法解决,如果有兄弟做出来了欢迎分享,十分感谢。

强迫症很难受,上面白边一直去不掉。。。。。。
————————————————
结束,谢谢

【黑客帝国数字雨】学习总结相关推荐

  1. 【C/C++源码】黑客帝国数字雨

    今天分享一个用C语言画黑客帝国数字雨的源码~ 用到的是easyx图形库绘图功能,所以需要下载安装easyx图形库,直接官网搜索下载即可,devC++用不了,需要另外配置哦!适用于Visual C++与 ...

  2. 【黑客帝国数字雨屏保】基于Win32的黑客帝国数字雨屏幕保护程序(附VS工程代码文件和可执行文件)

    运行效果 代码结构 //黑客帝国数字雨 花心胡萝卜 #包含 <windows.h> #包含 <stdlib.h>#define 时钟编号 1 #define 最大长度 25 / ...

  3. 实现黑客帝国数字雨效果

    今日闲得慌,折腾了一个黑客帝国数字雨效果,还蛮不错的. 操作:新建一个文本文档,输入 以下代码,再将扩展名修改为 Bat,运行即可. 命令提示符代码:(0-1) @echo off title 黑客帝 ...

  4. canvas黑客帝国数字雨背景 html+css+js

    效果(完整源码在最后): [html+css+js]黑客帝国数字雨源码分享 可拿来作页面背景 制作: 定义canvas标签: <canvas id="canvas">& ...

  5. 使用canvas实现黑客帝国数字雨

    效果图: 代码: <!DOCTYPE html> <html lang="en"> <head><meta charset="U ...

  6. 【炫酷秀】仅用4行代码再现《黑客帝国》数字雨,可立即在终端实现!

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 提到<黑客帝国>,字符雨可谓是让人印象深刻. 这种科技感爆棚的特效,你 ...

  7. 4行代码再现《黑客帝国》数字雨,在终端实现的那种

    十三 发自 凹非寺 量子位 报道 | 公众号 QbitAI 提到<黑客帝国>,字符雨可谓是让人印象深刻. 这种科技感爆棚的特效,你是否也想来一套? 这个,可以有. 最近,名叫akinomy ...

  8. python命令数字雨_用Python实现黑客帝国代码雨效果(3种方式)

    说起电影<黑客帝国>,相信大部分人都看过或听说过,影片中有一个场景数字雨,如果你看过电影的话,应该对这个经典场景印象深刻,本文我们利用 Python 以数字.字母.图片三种形式来实现这一效 ...

  9. GitHub开源:4行代码实现《黑客帝国》数字雨特效

    黑客帝国可是经久不衰的科幻热血巨作,近期GitHub一位大神开源了科技感十足的模拟<黑客帝国>数字雨效果特效.使用终端256色支持的十个级别的"绿色",通过添加随机的亮 ...

  10. C语言项目:黑客帝国之数字雨

    编辑 相信大家看过许许多多的关于计算机黑客.骇客.人工智能.AI方面的电影,每当黑客入侵某个五角大楼,某个网站时,都会出现这样一幅画面: 编辑 然后就轻而易举的成功入侵夺取管理员权限了,这时候的我们, ...

最新文章

  1. mongodb启动不了:child process failed, exited with err
  2. python中文编辑器推荐-八款Python编辑器对比介绍推荐
  3. couldn't register *** with the bootstrap server. Error: unknown error code.
  4. lm80认证_中国能效标识GB30255、GB38450和GB37478认证要求讲解
  5. 阿里云 ESSD 采用自研新一代存储网络协议,打造“超级高速”
  6. linux错误码61,Linux编程中的错误码列表
  7. Django-开胃菜
  8. cent os7 安装nginx1.16.1
  9. Bellman-Ford 算法及其优化
  10. 谈谈 Linux 假死现象
  11. 华为ospf配置命令_教你使用华为Ensp模拟器配置OSPF路由协议(一)
  12. 《挑战不可能之加油中国》中越边境广西段扫雷队整装亮相
  13. Rxjava:interval的使用
  14. 2019 年第 29 周 DApp 影响力排行榜 | TokenInsight
  15. 什么是c++运行库?
  16. 使用userAgent区分浏览器版本
  17. 致刚就业迷茫的你和寄语大学毕业生--技术读者
  18. 求职面试礼仪及注意事项
  19. 蜜蜂采蜜最短路径c语言算法,S018 蜜蜂采蜜太辛苦了,编程实现还是很容易的
  20. Failed to introspect Class [com.controller.HardWareController] from ClassLoa在ssm中读取串口信息

热门文章

  1. 深度学习: marginal cost (边际成本)
  2. android 休眠流程
  3. 从这里开始你的游戏黑客入门的之旅吧
  4. python游戏开发实战:黑客帝国特效
  5. ubuntu 14.04 ADSL 上网失败之解决
  6. 计算机专业助理工程师,计算机助理工程师是职称吗,是什么等级的职称?
  7. 赛博僵尸道长 v1.2
  8. React的消息订阅全过程
  9. SHELL命令 -- 查看显卡型号
  10. 大二期末作业(KTV点歌程序-纯java)