diff --git a/bounce_cpp.slnx b/bounce_cpp.slnx new file mode 100644 index 0000000..220e9fa --- /dev/null +++ b/bounce_cpp.slnx @@ -0,0 +1,7 @@ + + + + + + + diff --git a/bounce_cpp/Resource.aps b/bounce_cpp/Resource.aps new file mode 100644 index 0000000..1235c37 Binary files /dev/null and b/bounce_cpp/Resource.aps differ diff --git a/bounce_cpp/Resource.rc b/bounce_cpp/Resource.rc new file mode 100644 index 0000000..816f46b Binary files /dev/null and b/bounce_cpp/Resource.rc differ diff --git a/bounce_cpp/bounce_cpp.vcxproj b/bounce_cpp/bounce_cpp.vcxproj new file mode 100644 index 0000000..2aecb3d --- /dev/null +++ b/bounce_cpp/bounce_cpp.vcxproj @@ -0,0 +1,147 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 18.0 + Win32Proj + {61c6f079-9b1c-4d66-b9c7-4646f87181a6} + bouncecpp + 10.0 + + + + Application + true + v145 + Unicode + + + Application + false + v145 + true + Unicode + + + Application + true + v145 + Unicode + + + Application + false + v145 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + + + Windows + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp20 + MultiThreaded + + + Windows + true + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bounce_cpp/bounce_cpp.vcxproj.filters b/bounce_cpp/bounce_cpp.vcxproj.filters new file mode 100644 index 0000000..cefc746 --- /dev/null +++ b/bounce_cpp/bounce_cpp.vcxproj.filters @@ -0,0 +1,43 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/bounce_cpp/bounce_cpp.vcxproj.user b/bounce_cpp/bounce_cpp.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/bounce_cpp/bounce_cpp.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/bounce_cpp/hyrax.bmp b/bounce_cpp/hyrax.bmp new file mode 100644 index 0000000..600bba5 Binary files /dev/null and b/bounce_cpp/hyrax.bmp differ diff --git a/bounce_cpp/icon1.ico b/bounce_cpp/icon1.ico new file mode 100644 index 0000000..5d06b9f Binary files /dev/null and b/bounce_cpp/icon1.ico differ diff --git a/bounce_cpp/main.cpp b/bounce_cpp/main.cpp new file mode 100644 index 0000000..0d64c55 --- /dev/null +++ b/bounce_cpp/main.cpp @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include + +#pragma comment(lib, "gdiplus.lib") + +using namespace Gdiplus; + +Image* LoadImageFromResource(int resId) { + HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(resId), RT_RCDATA); + if (!hRes) return NULL; + + DWORD size = SizeofResource(NULL, hRes); + if (size == 0) return NULL; + + HGLOBAL hData = LoadResource(NULL, hRes); + if (!hData) return NULL; + + void* pData = LockResource(hData); + if (!pData) return NULL; + + HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, size); + if (!hBuffer) return NULL; + + void* pBuffer = GlobalLock(hBuffer); + if (!pBuffer) { + GlobalFree(hBuffer); + return NULL; + } + + memcpy(pBuffer, pData, size); + GlobalUnlock(hBuffer); + + IStream* stream = NULL; + HRESULT hr = CreateStreamOnHGlobal(hBuffer, TRUE, &stream); + if (FAILED(hr) || !stream) { + GlobalFree(hBuffer); + return NULL; + } + + Image* img = Image::FromStream(stream); + stream->Release(); + + if (!img || img->GetLastStatus() != Ok) { + if (img) delete img; + return NULL; + } + + return img; +} + + +double x = 200.0, y = 50.0; +double vx = 0.0, vy = 0.0; + +double gravity = 1200.0; +double restitution = 0.6; +double air_drag = 0.999; +double ground_friction = 0.8; + +int win_w = 640; +int win_h = 480; + +int dragging = 0; +int offset_x = 0, offset_y = 0; + +POINT last_mouse; +double last_mouse_time = 0.0; +double last_time = 0.0; + +LARGE_INTEGER freq; + +ULONG_PTR gdiplusToken; +Image* img = NULL; + + +double now_time() { + LARGE_INTEGER t; + QueryPerformanceCounter(&t); + return (double)t.QuadPart / (double)freq.QuadPart; +} + + +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + switch (msg) { + + case WM_CREATE: { + QueryPerformanceFrequency(&freq); + + GdiplusStartupInput gdiplusStartupInput; + GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + + img = LoadImageFromResource(111); + + if (!img || img->GetLastStatus() != Ok) { + // MessageBoxA(NULL, "Image failed to load", "Error", MB_OK); + } + else { + win_w = 640; + win_h = 480; + SetWindowPos(hwnd, NULL, 0, 0, win_w, win_h, SWP_NOMOVE); + } + + SetTimer(hwnd, 1, 10, NULL); + + last_time = now_time(); + last_mouse_time = last_time; + break; + } + + case WM_LBUTTONDOWN: { + dragging = 1; + offset_x = LOWORD(lParam); + offset_y = HIWORD(lParam); + + vx = vy = 0; + + GetCursorPos(&last_mouse); + last_mouse_time = now_time(); + + SetCapture(hwnd); + break; + } + + case WM_SETCURSOR: + if (dragging) + SetCursor(LoadCursor(NULL, IDC_SIZEALL)); + else + SetCursor(LoadCursor(NULL, IDC_HAND)); + return TRUE; + + case WM_MOUSEMOVE: + if (dragging) { + POINT p; + GetCursorPos(&p); + + double now = now_time(); + double dt = now - last_mouse_time; + + if (dt > 0) { + vx = (p.x - last_mouse.x) / dt; + vy = (p.y - last_mouse.y) / dt; + } + + last_mouse = p; + last_mouse_time = now; + + x = p.x - offset_x; + y = p.y - offset_y; + + SetWindowPos(hwnd, NULL, (int)x, (int)y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + } + break; + + case WM_LBUTTONUP: + dragging = 0; + ReleaseCapture(); + break; + + case WM_TIMER: { + double now = now_time(); + double dt = now - last_time; + last_time = now; + + int screen_w = GetSystemMetrics(SM_CXSCREEN); + int screen_h = GetSystemMetrics(SM_CYSCREEN); + + if (!dragging) { + vy += gravity * dt; + + vx *= air_drag; + vy *= air_drag; + + x += vx * dt; + y += vy * dt; + + if (x <= 0) { + x = 0; + vx = -vx * restitution; + } + else if (x >= screen_w - win_w) { + x = screen_w - win_w; + vx = -vx * restitution; + } + + if (y >= screen_h - win_h) { + y = screen_h - win_h; + vy = -vy * restitution; + vx *= ground_friction; + + if (fabs(vy) < 5) + vy = 0; + } + + if (y <= 0) { + y = 0; + vy = -vy * restitution; + } + + SetWindowPos(hwnd, NULL, (int)x, (int)y, 0, 0, + SWP_NOSIZE | SWP_NOZORDER); + } + break; + } + + case WM_PAINT: { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + Graphics g(hdc); + + if (img) + g.DrawImage(img, 0, 0, win_w, win_h); + + EndPaint(hwnd, &ps); + break; + } + + case WM_KEYDOWN: + if (wParam == VK_ESCAPE) + DestroyWindow(hwnd); + break; + + case WM_DESTROY: + if (img) delete img; + GdiplusShutdown(gdiplusToken); + PostQuitMessage(0); + break; + } + + return DefWindowProcW(hwnd, msg, wParam, lParam); +} + + +static int WINAPI wWinMain( + HINSTANCE hInstance, + HINSTANCE, + PWSTR, + int nCmdShow +) { + + if (IsDebuggerPresent()) + return 0; + + WNDCLASSW wc = { 0 }; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.lpszClassName = L"Hyrax"; + wc.hCursor = LoadCursor(NULL, IDC_HAND); + + RegisterClassW(&wc); + + HWND hwnd = CreateWindowExW( + WS_EX_TOPMOST, + L"Hyrax", + L"", + WS_POPUP, + (int)x, (int)y, + win_w, win_h, + NULL, NULL, hInstance, NULL + ); + + ShowWindow(hwnd, nCmdShow); + + MSG msg; + while (GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + return 0; +} \ No newline at end of file diff --git a/bounce_cpp/resource.h b/bounce_cpp/resource.h new file mode 100644 index 0000000..74fc674 --- /dev/null +++ b/bounce_cpp/resource.h @@ -0,0 +1,17 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc +// +#define IDR_RCDATA1 111 +#define IDI_ICON1 114 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 115 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif