開発環境 Microsoft Visual Studio Community 2019
実行環境 Microsoft Windows 10 Home (64bit)
プロジェクト テンプレート C++ 空のプロジェクト
プロジェクト名 AATrain



AATrain.cpp
#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;
}
 
最終更新:2019年12月04日 19:33
添付ファイル