// BallisticCurve2
#define _USE_MATH_DEFINES
#include <Windows.h>
#include <wchar.h>
#include <math.h>
#define APP_NAME TEXT("BallisticCurve")
#define dt 0.1
#define g 9.80665 // 標準重力加速度(m/s^2)
// 外部変数
HDC hdcMem = NULL;
HBITMAP hBmp = NULL;
// 関数プロトタイプ宣言
void Trace(LPCTSTR format, ...);
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnCreate(HWND hWnd, LPARAM lParam);
void OnPaint(HWND hWnd);
//==============================================================================
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow)
{
// ウィンドウクラスの登録
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof wcx);
wcx.cbSize = sizeof wcx;
// wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = WndProc;
wcx.hInstance = hInstance;
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
// wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcx.lpszClassName = APP_NAME;
if (RegisterClassEx(&wcx) == 0) {
return 0;
}
// ウィンドウの作成
DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
RECT rc;
SetRect(&rc, 0, 0, 640, 400);
AdjustWindowRect(&rc, dwStyle, FALSE);
HWND hWnd = CreateWindow(
APP_NAME, APP_NAME,
dwStyle,
CW_USEDEFAULT, 0,
rc.right - rc.left, rc.bottom - rc.top,
NULL, NULL, hInstance, NULL);
if (hWnd == NULL) {
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// メッセージループ
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void Trace(LPCTSTR format, ...)
{
va_list arg_ptr;
va_start(arg_ptr, format);
TCHAR buffer[256];
int size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr);
va_end(arg_ptr);
OutputDebugString(buffer);
if (size < 0) {
OutputDebugString(L"...\n");
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_PAINT:
OnPaint(hWnd);
return 0;
case WM_CREATE:
OnCreate(hWnd, lParam);
return 0;
case WM_DESTROY:
if (hdcMem) DeleteDC(hdcMem);
if (hBmp) DeleteObject(hBmp);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
void OnCreate(HWND hWnd, LPARAM lParam)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
HDC hdc = GetDC(hWnd);
hdcMem = CreateCompatibleDC(hdc);
hBmp = CreateCompatibleBitmap(hdc, pcs->cx, pcs->cy);
SelectObject(hdcMem, hBmp);
PatBlt(hdcMem, 0, 0, 640, 400, BLACKNESS);
SelectObject(hdcMem, GetStockObject(WHITE_PEN));
for (int deg = 15; deg <= 75; deg += 15) {
double v = 40.0; // m/s
double a = deg * M_PI / 180;
double x = 0.0; // m
double y = 1.0; // m
Trace(L"\na=%.1f\n", a * 180 / M_PI);
MoveToEx(hdcMem, int(x * 4), 400 - int(y * 4), NULL);
for (double t = 0; t < 10.0; t += dt) {
double vx = v * cos(a);
double vy = v * sin(a) - g * dt;
a = atan2(vy, vx);
v = sqrt(vx * vx + vy * vy);
v -= 0.002 * v * v * dt; // 空気抵抗
x += vx * dt;
y += vy * dt;
Trace(L"t=%.1f x=%.1f y=%.1f v=%.1fkm/h a=%.1f\n", t, x, y, v * 3.6, a * 180 / M_PI);
LineTo(hdcMem, int(x * 4), 400 - int(y * 4));
if (y <= 0.0) break;
}
}
ReleaseDC(hWnd, hdc);
}
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
Trace(L"OnPaint(%d, %d, %d, %d)\n", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
// BitBlt(hdc, 0, 0, 640, 400, hdcMem, 0, 0, SRCCOPY);
BitBlt( hdc,
ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom,
hdcMem,
ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
EndPaint(hWnd, &ps);
}