-
-
Save mrboojum/0254e5bfa99aa3b6d181bbe26c381e35 to your computer and use it in GitHub Desktop.
Matrix Digital Rain
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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