欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

实现黑客帝国的片头字符雨并控制其停止,显示“The Matrix”

程序员文章站 2024-03-19 16:59:46
...

最近在学图形学,作业涉及到做一个字符雨动画,这不禁让我想到黑客帝国的片头,黑客帝国的特效以及其跨时代意义在今天看来都令人惊叹,可见创作者对未来的洞悉,也能深深感受到计算机图形学的无穷魅力。

因为OpenGL的框架略微繁琐,之前对一些图形学原理知识比如图形生成算法、裁剪算法、曲线生成算法等等,一直用EasyX二维图形库去进行绘制,这里也一样,其实和OpenGL相比不过就是简化了那些配置,变成了2维,反而更便于对一些原理知识的验证、实现。

字符雨的实现的一些细节:(注释中都已给出)
(1)随机生成字符要用随机种子,否则会出现很多重复内容。
(2)明暗度和结束时的过渡效果我们就用RGB的255表示方法从0~255逐渐变亮代替。
(3)还有就是字符的更新,就是简单的后者替换前者并生成最开始新的字符。

效果:
实现黑客帝国的片头字符雨并控制其停止,显示“The Matrix”
最终:
实现黑客帝国的片头字符雨并控制其停止,显示“The Matrix”
代码:

#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>
//屏幕的宽高(我屏幕的分辨率是1366*768)
#define Height 768
#define Width 1366
#define fontsize 25//字符大小

int CharNum[Width/fontsize][Height/fontsize];//每个字符的ASCII码
int RowNum[Width/fontsize];//每一列字符的数量
int row_num=Width/fontsize,column_num=Height/fontsize;//全部充满字符时的行数列数
int Green_level[Width/fontsize];//每列字符的颜色明暗
int flag=0;//控制是否播放随机字符
void startup() // 数据初始化
{
	//对字符数组进行初始化
	srand((unsigned) time(NULL));//设置随机种子
	int i,j;
	for(i=0;i<row_num;i++){
		RowNum[i]=rand()%(column_num*9/10)+column_num/10;//随机产生每一列字符的数量
		for(j=0;j<RowNum[i];j++){
			CharNum[i][j]=rand()%26+65;//产生A—Z的随机ASCII码
		}
	}
	//开始绘制
	initgraph(Width,Height);
	BeginBatchDraw();
}
void clean()//清除上一帧
{
	clearrectangle(0,0,Width-1,Height-1);
}
void show()  // 显示画面
{
	int i,j;
	if(!flag){
		for(i=0;i<row_num;i++){
			int x=i*fontsize;//当前字符的x坐标
			for(j=0;j<RowNum[i];j++){
				int y=j*fontsize;//当前字符的y坐标
				//输出字符
				setfont(25,10, _T("Courier"));
				setcolor(RGB(0,Green_level[i],0));
				outtextxy(x,y,CharNum[i][j]);
			}
		}
	}
	//控制字符雨何时结束并显示The Matrix
	static int time=0;
	time++;
	if(time>=175){//为了有渐隐的结束效果,设置亮度逐渐降低
		for(i=0;i<row_num;i++){
			if(Green_level[i]>=10){
				Green_level[i]-=10;
			}
		}
	}
	if(time==200){
		flag=1;
	}
	if(flag){
		setfont(60,20, _T("Courier"));
		setcolor(RGB(0,255,0));
		outtextxy(Width/2-150,Height/2,_T("The Matrix"));
	}
	FlushBatchDraw();
	Sleep(100); 
}	

void updateWithoutInput()  // 与用户输入无关的更新
{	
	int i,j;
	srand((unsigned) time(NULL));//设置随机种子
	//每一帧向下移动,最上面产生新的字符
	for(i=0;i<row_num;i++){
		if(RowNum[i]<column_num){//对于当前列字符数没填满屏幕的
			for(j=RowNum[i]-1;j>0;j--){
				CharNum[i][j]=CharNum[i][j-1];//上一个字符代替下一个
			}
			RowNum[i]++;
			CharNum[i][0]=rand()%26+65;//生成最上面的新的字符
		}else{//如果已经满了就降低字符亮度
			if(Green_level[i]>40){
				Green_level[i]-=20;
			}else{//降到一定程度后重新生成字符
				RowNum[i]=rand()%(column_num/3)+column_num/10;//随机产生当前列列字符的数量
				Green_level[i]=rand()%75+180;//随机产生当前列列字符的亮度
				for(j=0;j<RowNum[i];j++){
					CharNum[i][j]=rand()%26+65;//随机产生当前列列字符ASCII码
				}
			}
		}
	}
}

void updateWithInput()  // 与用户输入有关的更新
{
	//null
}
void gameover()//结束时调用的函数
{
	EndBatchDraw();
	getch();
	closegraph();
}
int main()
{
	startup();  // 数据初始化	
	while (1) //  游戏循环执行
	{
		clean();//清除上一帧画的
		updateWithoutInput();  // 与用户输入无关的更新
		updateWithInput();  // 与用户输入有关的更新
		show();  // 显示画面	
	}
	gameover();
	return 0;
}
相关标签: c/c++游戏