#include <Windows.h>
#include <ScrnSave.h>
#define _USE_MATH_DEFINES
#include <math.h>
#pragma comment(lib, "scrnsavw")
#pragma comment(lib, "comctl32")
typedef struct {
int x;
int y;
int w;
int h;
} Sprite;
int os[512 * 3];
double ox[512 * 3];
double oz[512 * 3];
int od[512 * 3];
double rx = 0.0;
double rz = 0.0;
int g0 = 0;
int g1 = 0;
int tg = 0;
int side[2];
HDC hdcMem = NULL;
HBITMAP hbmMem = NULL;
HGDIOBJ hbmMemOld = NULL;
HDC hdcSky = NULL;
HBITMAP hbmSky = NULL;
HGDIOBJ hbmSkyOld = NULL;
HDC hdcSpr = NULL;
HBITMAP hbmSpr = NULL;
HGDIOBJ hbmSprOld = NULL;
int width;
int height;
Sprite sprite[6];
LPCTSTR sp_3[] = {
L"#==#",
L"#--#",
L"# #" };
LPCTSTR sp_4[] = {
L" %% ",
L" %%.% ",
L" %%**% ",
L" %%%% % ",
L" %%** .% ",
L" %%% %% % ",
L"%%%* *.. ",
L"%%% %%.%* ",
L" *%%..**.' ",
L" ''*# .'' ",
L" # . ",
L".._## ##_.." };
LPCTSTR sp_5[] = {
L"|X|",
L"===",
L"===",
L"|X|",
L"|X|",
L"|X|",
L"|X|",
L"|X|",
L"|#|",
L"|#|",
L"|X|",
L"|X|" };
//
void OnCreate(HWND hWnd);
void OnDestroy();
void OnTimer(HWND hWnd);
void set_obj();
void draw_obj(int id, double cx, double cz, double qs, double qc);
double radians(int deg);
int rnd(int x);
LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_TIMER:
OnTimer(hWnd);
break;
case WM_CREATE:
OnCreate(hWnd);
SetTimer(hWnd, 1, 1000 / 30, NULL);
break;
case WM_DESTROY:
OnDestroy();
//PostQuitMessage(0);
break;
}
return DefScreenSaverProc(hWnd, msg, wParam, lParam);
}
BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lPara)
{
return TRUE;
}
BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
return TRUE;
}
void OnCreate(HWND hWnd)
{
HDC hdc = GetDC(hWnd);
RECT rc;
GetClientRect(hWnd, &rc);
width = rc.right;
height = rc.bottom;
// バックバッファ
hdcMem = CreateCompatibleDC(hdc);
hbmMem = CreateCompatibleBitmap(hdc, width, height);
hbmMemOld = SelectObject(hdcMem, hbmMem);
SetStretchBltMode(hdcMem, COLORONCOLOR);
// 星空背景
hdcSky = CreateCompatibleDC(hdc);
hbmSky = CreateCompatibleBitmap(hdc, width, height);
hbmSkyOld = SelectObject(hdcSky, hbmSky);
// スプライト
hdcSpr = CreateCompatibleDC(hdc);
hbmSpr = CreateCompatibleBitmap(hdc, 320, 240);
hbmSprOld = SelectObject(hdcSpr, hbmSpr);
ReleaseDC(hWnd, hdc);
//
PatBlt(hdcSky, 0, 0, width, height, BLACKNESS);
SelectObject(hdcSky, GetStockObject(ANSI_FIXED_FONT));
SetBkMode(hdcSky, TRANSPARENT);
SetTextColor(hdcSky, RGB(255, 255, 255));
for (int i = 0; i < 64; i++) {
TextOut(hdcSky, rnd(width / 8) * 8, rnd(height / 32) * 8, L"*." + rnd(2), 1);
}
//
SelectObject(hdcSpr, GetStockObject(ANSI_FIXED_FONT));
SetBkMode(hdcSpr, TRANSPARENT);
sprite[1] = { 0, 0, 48, 13 }; // 線路
sprite[2] = { 0, 20, 48, 13 }; // 草
sprite[3] = { 0, 40, 32, 39 }; // 柵
sprite[4] = { 60, 0, 87, 156 }; // 木
sprite[5] = { 160, 0, 24, 156 }; // 柱
SetTextColor(hdcSpr, RGB(255, 255, 255));
TextOut(hdcSpr, 0, 0, L"/====\\", 6);
SetTextColor(hdcSpr, RGB(0, 255, 0));
TextOut(hdcSpr, 0, 20, L".w.ww.", 6);
SetTextColor(hdcSpr, RGB(255, 255, 0));
for (int i = 0; i < 3; i++) {
TextOut(hdcSpr, 0, 40 + 13 * i, sp_3[i], lstrlen(sp_3[i]));
}
SetTextColor(hdcSpr, RGB(255, 255, 255));
for (int i = 0; i < 12; i++) {
TextOut(hdcSpr, 60, 13 * i, sp_4[i], lstrlen(sp_4[i]));
}
for (int i = 0; i < 12; i++) {
TextOut(hdcSpr, 160, 13 * i, sp_5[i], lstrlen(sp_5[i]));
}
//
//srand((unsigned)time(NULL));
for (int i = 0; i < 512; i++) {
set_obj();
}
}
void OnDestroy()
{
if (hbmMemOld) SelectObject(hdcMem, hbmMemOld);
if (hbmMem) DeleteObject(hbmMem);
if (hdcMem) DeleteDC(hdcMem);
if (hbmSkyOld) SelectObject(hdcSky, hbmSkyOld);
if (hbmSky) DeleteObject(hbmSky);
if (hdcSky) DeleteDC(hdcSky);
if (hbmSprOld) SelectObject(hdcSpr, hbmSprOld);
if (hbmSpr) DeleteObject(hbmSpr);
if (hdcSpr) DeleteDC(hdcSpr);
}
void OnTimer(HWND hWnd)
{
set_obj();
int p = (tg + 0) % 512;
int x = width * od[p] / 360;
BitBlt(hdcMem, 0, 0, width - x, height, hdcSky, x, 0, SRCCOPY);
BitBlt(hdcMem, width - x, 0, x, height, hdcSky, 0, 0, SRCCOPY);
double cx = ox[p];
double cz = oz[p];
double q = radians(od[p]);
double qs = sin(q);
double qc = cos(q);
for (int i = 0; i < 512 * 3; i++) {
if (os[i]) draw_obj(i, cx, cz, qs, qc);
}
//
HDC hdc = GetDC(hWnd);
BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdc);
}
void set_obj()
{
if (tg % 32 == 0) {
g1 = rnd(3) - 1;
side[0] = rnd(3);
side[1] = rnd(3);
}
g0 = (g0 + g1 + 360) % 360;
double rad = radians(g0);
rx += sin(rad) * 64;
rz += cos(rad) * 64;
os[tg] = (tg % 4 == 0) ? 1 : 0;
ox[tg] = rx;
oz[tg] = rz;
od[tg] = g0;
int id = tg;
rad = radians(g0 + 90);
for (int j = 0; j < 2; j++) {
id += 512;
int n = 0;
int d;
if (tg % 8 == 0) {
switch (side[j]) {
case 1:
d = rnd(16) * 64 + 512;
n = 4;
break;
case 2:
d = 512;
n = 3;
break;
}
}
if (tg % 64 == 0) {
d = 512;
n = 5;
}
if (n == 0) {
d = rnd(8) * 128 + 256;
n = 2;
}
d = (j == 0) ? -d : d;
os[id] = n;
ox[id] = rx + d * sin(rad);
oz[id] = rz + d * cos(rad);
}
tg = (tg + 1) % 512;
}
void draw_obj(int id, double cx, double cz, double qs, double qc)
{
double x = ox[id] - cx;
double z = oz[id] - cz;
double dx = x * qc - z * qs;
double dz = x * qs + z * qc;
if (dz <= 64.0) return;
double scale = 2048.0 / dz;
int sx = width / 2 + (int)(512 * dx / dz);
int sy = height / 3 + (int)(131072 / dz);
Sprite& sp = sprite[os[id]];
int sw = (int)(sp.w * scale);
int sh = (int)(sp.h * scale);
StretchBlt(hdcMem, sx - sw / 2, sy - sh, sw, sh, hdcSpr, sp.x, sp.y, sp.w, sp.h, SRCPAINT);
}
double radians(int deg)
{
return deg * M_PI / 180;
}
int rnd(int x)
{
return rand() % x;
}