基于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;
}
Greatness is never a given, it must be earned.