Skip to content

Instantly share code, notes, and snippets.

@mrboojum
Forked from Chase-san/rain.cpp
Created December 13, 2019 08:21
Show Gist options
  • Save mrboojum/0254e5bfa99aa3b6d181bbe26c381e35 to your computer and use it in GitHub Desktop.
Save mrboojum/0254e5bfa99aa3b6d181bbe26c381e35 to your computer and use it in GitHub Desktop.
Matrix Digital Rain
#include <stdlib.h>
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
using namespace Gdiplus;
wchar_t* characters =
//Hiragana
L"あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもや"
L"ゆよらりるれろわゐゑをんがぎぐげござじずぜぞだぢどばびぶべぼぱぴぷぺぽ"
//Katakana
L"アイウエオカキクケコガギグゲゴサシスセソザジズゼゾタチツテトダヂヅデドナ"
L"ニヌネノハヒフヘホバビブベボパピプペポマミムメモヤユヨラリルレロワヰヱヲン"
//80 most common japanese kanji
L"一右雨円王音下火花学気九休金空月犬見五口校左三山子四糸字耳七車手十出女小上森人水"
L"正生青夕石赤千川先早足村大男中虫町天田土二日入年白八百文木本名目立力林六引雲遠何";
int charlen = 224;
int width = 1440;
int height = 900;
int cw = (int) (width / 12.0);
int ch = (int) (height / 12.0);
int decay = 6; // 2.5%
int fill_start = 102; //40%
float fill_rate = 0.06; //6%
float flip_rate = 0.002; //0.2%
int tick_time = 105; //TODO implement this eventually
wchar_t *data; //character to display
int *path;
wchar_t getRandChar() {
return characters[rand() % charlen];
}
void setupSimulation() {
srand(time(NULL));
data = new wchar_t[cw * ch];
path = new int[cw * ch];
//initialize
for (int i = 0; i < cw * ch; ++i) {
data[i] = getRandChar();
path[i] = 0;
}
}
void update() {
for (int i = cw * ch - 1; i >= 0; --i) {
if (i + cw < cw * ch) {
if (path[i] == 255) {
path[i + cw] = 255;
data[i + cw] = getRandChar();
}
}
if (path[i] > 64 && rand() < flip_rate * RAND_MAX) {
data[i] = getRandChar();
}
if (path[i] > decay) {
path[i] -= decay;
} else {
path[i] = 0;
}
if (i < cw && path[i] <= fill_start) {
if (rand() < fill_rate * RAND_MAX) {
path[i] = 255;
data[i] = getRandChar();
}
}
}
}
void destroySimulation() {
delete data;
delete path;
}
VOID OnPaint(HDC hdc) {
Graphics gx(hdc);
SolidBrush black(Color(0, 0, 0));
gx.FillRectangle(&black, 0, 0, 800, 600);
Font font(L"MS PGothic", 10);
int y = 0;
for (int i = 0; i < cw * ch; ++i) {
SolidBrush brush(Color(0, path[i], 0));
PointF p((i % cw) * 12 + 1, y);
gx.DrawString(&data[i], 1, &font, p, &brush);
if (i % cw == cw - 1)
y += 12;
}
}
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, INT iCmdShow) {
setupSimulation();
HWND hWnd;
MSG msg;
WNDCLASS wndClass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION );
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW );
wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = TEXT("Matrix Digital Rain");
RegisterClass(&wndClass);
int dwStyle = WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU;
int dwExStyle = 0L;
RECT size = { 0, 0, width, height };
AdjustWindowRectEx(&size, dwStyle, false, dwExStyle);
hWnd = CreateWindowEx(dwExStyle, TEXT("Matrix Digital Rain"), // window class name
TEXT("Matrix Digital Rain"), // window caption
dwStyle, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
size.right - size.left, // initial x size
size.bottom - size.top, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
destroySimulation();
return msg.wParam;
} // WinMain
#define ID_TIMER 1
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam) {
switch (message) {
case WM_CREATE:
SetTimer(hWnd, ID_TIMER, tick_time, NULL);
return 0;
case WM_ERASEBKGND:
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP memBM = CreateCompatibleBitmap(hdc, width, height);
SelectObject(memDC, memBM);
OnPaint(memDC);
BitBlt(hdc, 0, 0, width, height, memDC, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
return 0;
}
case WM_TIMER:
update();
InvalidateRect(hWnd, NULL, false);
return 0;
case WM_DESTROY:
KillTimer(hWnd, ID_TIMER);
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
} // WndProc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment