開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 BallisticCurve
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト

BallisticCurve.cpp
// 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);
}
 
最終更新:2013年05月09日 11:52