基于EasyX和Raylib的字符雨

思路

按如下顺序尝试:

  • 绘制一个字符下落
  • 绘制4个字符(一列)的下落
  • 绘制20个字符(一列)的下落,并封装其位置更新、绘制的过程为 Rain 类的成员函数
  • 绘制多个雨滴
  • 每个雨滴在更新位置时, 也修改字符
  • 每个雨滴初始化时,位置、速度都随即化

基于 EasyX

// 字符雨 (基于 easyx)
// 来源: https://zhuanlan.zhihu.com/p/434484127

#include<stdio.h>
#include<graphics.h> //图形库头文件
#include<Windows.h>
#include <time.h>

#define WIDTH 1615//960
#define HEIGHT 1006//640
#define STR_SIZE 20 //数字雨数组最大存储
#define STR_NUM 128 //数字雨的串数
#define STR_WIDTH 15 //字符串

struct Rain //雨的结构
{
	int x; //数字雨横向位置
	int y; //y坐标
	int speed; //下降速度
	char str[STR_SIZE]; //数字雨数组
} rain[STR_NUM];

char CreateCh()
{
	char temp = 0;
	int flag = rand() % 3;//0 1 2
	if (flag == 0)
	{
		temp = rand() % 26 + 'a';
	}
	else if (flag == 1)
	{
		temp = rand() % 26 + 'A';
	}
	else
	{
		temp = rand() % 10 + '0';
	}

	return temp;
}

void GameInit()
{
	//初始化基础数据
	for (int i = 0; i < STR_NUM; i++)
	{
		rain[i].x = i*STR_WIDTH;
		rain[i].y = rand() % HEIGHT;
		rain[i].speed = rand() % 5 + 5;//5 6 7 8 9 10
	}
	//初始化字符串
	for (int i = 0; i < STR_NUM; i++)
	{
		for (int j = 0; j < STR_SIZE; j++)
		{
			rain[i].str[j] = CreateCh();
		}
	}
}

void GameDraw()
{
	cleardevice();
	for (int i = 0; i < STR_NUM; i++)
	{
		for (int j = 0; j < STR_SIZE; j++)
		{
			outtextxy(rain[i].x, rain[i].y-STR_WIDTH*j, rain[i].str[j]);
			settextcolor(RGB(0,255-13*j,0));
		}
	}
}

void GamePlay()
{
	for (int i = 0; i < STR_NUM; i++)
	{
		rain[i].y += rain[i].speed;
		if (rain[i].y-STR_SIZE*STR_WIDTH>HEIGHT)
		{
			rain[i].y = 0;
		}
	}
}

void ChangeCh()
{
	for (int i = 0; i < STR_NUM; i++)
	{
		rain[rand()%STR_NUM].str[rand()%STR_SIZE] = CreateCh();
	}
}

int main()
{
	initgraph(WIDTH,HEIGHT);
	srand((unsigned)time(NULL));
	GameInit();
	DWORD t1, t2;
	t1 = t2 = GetTickCount();
	while (1)
	{
		BeginBatchDraw();
		GameDraw();
		ChangeCh();
		if (t2 - t1 > 20)//使游戏下落延时
		{
			GamePlay();
			t1 = t2;
		}
		t2 = GetTickCount();
		EndBatchDraw();
		//Sleep(20); //使整个程序延时
	}

	getchar();
	closegraph();
	return 0;
}

基于 Raylib

// 每个雨滴的速度都为随机数,每次落雨都修改雨滴的组成字符
#include "raylib.h"
#include "raylib_helper.hpp"
#include <stdlib.h>
#include <vector>

using std::vector;

#define WIDTH 1615
#define HEIGHT 1006
#define RAIN_HEIGHT 20
#define STR_WIDTH 15

class Rain
{
public:
	char str[RAIN_HEIGHT];
	int x;
	int y;
	int speed;

	void update()
	{
		y += speed;
		if (y - 20 * STR_WIDTH > HEIGHT)
		{
			y = 0;
		}
		change_chars();
	}

	void draw()
	{
		int font_size = 13;
		for (int j = 0; j < RAIN_HEIGHT; j++)
		{
			char s[2] = { 0 };
			s[0] = str[j];
			Color color = make_color(0, j * 13, 0, 255);
			DrawText(s, x, y + j * font_size, font_size, color);
		}
	}
	void change_chars()
	{
		for (int j = 0; j < RAIN_HEIGHT; j++)
		{
			str[j] = ( rand() / (double)RAND_MAX ) * 26 + 'A';
		}
	}
};

vector<Rain> rain(128);

void update()
{
	static int cnt = 0;
	cnt++;
	if (cnt == 2)
	{
		cnt = 0;

		for (int i = 0; i < rain.size(); i++)
		{
			rain[i].update();
		}
	}
}

void startup()
{
	InitWindow(WIDTH, HEIGHT, "The Matrix");
	SetTargetFPS(60);

	for (int i = 0; i < rain.size(); i++)
	{
		rain[i].x = i * STR_WIDTH;
		rain[i].y = rand() % HEIGHT;
		rain[i].speed = rand() % 5 + 5;
		rain[i].change_chars();
	}
}

void show()
{
	BeginDrawing();
	{
		ClearBackground(BLACK);
		for (int i = 0; i < rain.size(); i++)
		{
			rain[i].draw();
		}
	}
	EndDrawing();
}

int main()
{
	startup();
	while (!WindowShouldClose())
	{
		update();
		show();
	}
	CloseWindow();

	return 0;
}
posted @ 2023-01-25 20:10  ChrisZZ  阅读(107)  评论(0编辑  收藏  举报