#define UNICODE
#define _UNICODE
#include <windows.h>
#include <math.h>
#include <wchar.h>
#include “aip_common.h”
// Constants for window dimensions, gravity, and animation
#define U4_SIM_WINDOW_WIDTH 600U
#define U4_SIM_WINDOW_HEIGHT 500U
#define U1_SIM_BALL_RADIUS 10U
#define S8_SIM_GRAVITY 0.0008
#define S8_SIM_REBOUND_FACTOR 0.5
#define U4_SIM_GROUND_Y (U4_SIM_WINDOW_HEIGHT - 150U)
// UI control IDs and Timer ID
#define U2_CTRL_HEIGHT_INPUT 201U
#define U2_CTRL_REBOUNDS_INPUT 202U
#define U2_CTRL_SUBMIT_BUTTON 203U
#define U4_SIM_TIMER_ID 101U
// Ball structure
typedef struct {
S8 S8_X_POSITION;
S8 S8_Y_POSITION;
S8 S8_VERTICAL_VELOCITY;
S8 S8_CURRENT_HEIGHT;
U2 U2_REBOUNDS_COUNT;
U2 U2_MAX_REBOUNDS;
U1 U1_SIM_ACTIVE;
U1 U1_IS_FALLING;
S8 S8_INITIAL_WAIT_TIME_MS;
S8 S8_TOTAL_DISTANCE;
} ST_SIM_BALL;
// Global variables
ST_SIM_BALL ST_SIM_BALL_INSTANCE = {0};
HWND HWND_CTRL_HEIGHT_INPUT;
HWND HWND_CTRL_REBOUNDS_INPUT;
HWND HWND_CTRL_SUBMIT_BUTTON;
HWND HWND_SIM_MAIN_WINDOW = NULL;
HWND HWND_RESULT_WINDOW = NULL;
U4 U4_LAST_SIM_TICK_TIME = 0;
S8 S8_SIM_REBOUND_HEIGHTS[100] = {0};
S8 S8_SIM_CUMULATIVE_DISTANCES[100] = {0};
// Function prototypes
void FP_SIM_INITIALIZE_BALL(S8 S8_INITIAL_HEIGHT_METERS, U2 U2_MAX_REBOUNDS);
void FP_SIM_UPDATE_BALL(U4 U4_DELTA_TIME_MS);
void FP_SIM_RENDER_SCENE(HDC hdc);
LRESULT CALLBACK FP_RESULTS_WINDOW_PROC(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void FP_DISPLAY_SIMULATION_RESULTS(HINSTANCE HINSTANCE_CURRENT);
LRESULT CALLBACK FP_MAIN_WINDOW_PROC(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
/* ------------------------------------------------------------------
Initialize ball properties
------------------------------------------------------------------ */
void FP_SIM_INITIALIZE_BALL(S8 S8_INITIAL_HEIGHT_METERS, U2 U2_MAX_REBOUNDS) {
if (S8_INITIAL_HEIGHT_METERS <= 0 || U2_MAX_REBOUNDS <= 0) return;
S8 S8_INITIAL_HEIGHT_PIXELS = S8_INITIAL_HEIGHT_METERS * 2.0;
ST_SIM_BALL_INSTANCE.S8_X_POSITION = U4_SIM_WINDOW_WIDTH / 2.0;
ST_SIM_BALL_INSTANCE.S8_Y_POSITION = U4_SIM_GROUND_Y - S8_INITIAL_HEIGHT_PIXELS;
ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY = 0;
ST_SIM_BALL_INSTANCE.S8_CURRENT_HEIGHT = S8_INITIAL_HEIGHT_PIXELS;
ST_SIM_BALL_INSTANCE.U2_REBOUNDS_COUNT = 0;
ST_SIM_BALL_INSTANCE.U2_MAX_REBOUNDS = U2_MAX_REBOUNDS;
ST_SIM_BALL_INSTANCE.U1_SIM_ACTIVE = TRUE;
ST_SIM_BALL_INSTANCE.U1_IS_FALLING = FALSE;
ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS = 2000.0;
ST_SIM_BALL_INSTANCE.S8_TOTAL_DISTANCE = 0.0;
for (U2 U2_I = 0; U2_I < 100; U2_I++) {
S8_SIM_REBOUND_HEIGHTS[U2_I] = 0;
S8_SIM_CUMULATIVE_DISTANCES[U2_I] = 0;
}
}
/* ------------------------------------------------------------------
Update ball physics
------------------------------------------------------------------ */
void FP_SIM_UPDATE_BALL(U4 U4_DELTA_TIME_MS) {
if (!ST_SIM_BALL_INSTANCE.U1_SIM_ACTIVE) return;
if (ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS > 0) {
ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS -= U4_DELTA_TIME_MS;
if (ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS <= 0) {
ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS = 0;
ST_SIM_BALL_INSTANCE.U1_IS_FALLING = TRUE;
}
return;
}
if (ST_SIM_BALL_INSTANCE.U1_IS_FALLING) {
ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY += S8_SIM_GRAVITY * U4_DELTA_TIME_MS;
ST_SIM_BALL_INSTANCE.S8_Y_POSITION += ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY * U4_DELTA_TIME_MS;
if (ST_SIM_BALL_INSTANCE.S8_Y_POSITION >= U4_SIM_GROUND_Y - U1_SIM_BALL_RADIUS) { ST_SIM_BALL_INSTANCE.S8_Y_POSITION = U4_SIM_GROUND_Y - U1_SIM_BALL_RADIUS; ST_SIM_BALL_INSTANCE.U1_IS_FALLING = FALSE; S8_SIM_CUMULATIVE_DISTANCES[ST_SIM_BALL_INSTANCE.U2_REBOUNDS_COUNT] = ST_SIM_BALL_INSTANCE.S8_TOTAL_DISTANCE + ST_SIM_BALL_INSTANCE.S8_CURRENT_HEIGHT; S8_SIM_REBOUND_HEIGHTS[ST_SIM_BALL_INSTANCE.U2_REBOUNDS_COUNT] = ST_SIM_BALL_INSTANCE.S8_CURRENT_HEIGHT * S8_SIM_REBOUND_FACTOR; ST_SIM_BALL_INSTANCE.S8_TOTAL_DISTANCE += ST_SIM_BALL_INSTANCE.S8_CURRENT_HEIGHT; ST_SIM_BALL_INSTANCE.U2_REBOUNDS_COUNT++; if (ST_SIM_BALL_INSTANCE.U2_REBOUNDS_COUNT < ST_SIM_BALL_INSTANCE.U2_MAX_REBOUNDS) { ST_SIM_BALL_INSTANCE.S8_CURRENT_HEIGHT *= S8_SIM_REBOUND_FACTOR; ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY = -sqrt(2.0 * S8_SIM_GRAVITY * ST_SIM_BALL_INSTANCE.S8_CURRENT_HEIGHT); } else { ST_SIM_BALL_INSTANCE.U1_SIM_ACTIVE = FALSE; } }
} else {
ST_SIM_BALL_INSTANCE.S8_Y_POSITION += ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY * U4_DELTA_TIME_MS;
ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY += S8_SIM_GRAVITY * U4_DELTA_TIME_MS;
if (ST_SIM_BALL_INSTANCE.S8_VERTICAL_VELOCITY >= 0) { ST_SIM_BALL_INSTANCE.U1_IS_FALLING = TRUE; }
}
}
/* ------------------------------------------------------------------
Render simulation scene
------------------------------------------------------------------ */
void FP_SIM_RENDER_SCENE(HDC hdc) {
// Draw ground
HPEN HPEN_GROUND = CreatePen(PS_SOLID, 2, RGB(0, 128, 0));
HPEN HPEN_OLD = (HPEN)SelectObject(hdc, HPEN_GROUND);
MoveToEx(hdc, 0, U4_SIM_GROUND_Y, NULL);
LineTo(hdc, U4_SIM_WINDOW_WIDTH, U4_SIM_GROUND_Y);
SelectObject(hdc, HPEN_OLD);
DeleteObject(HPEN_GROUND);
// Draw ball
HBRUSH HBRUSH_BALL = CreateSolidBrush(RGB(139, 69, 19));
HBRUSH HBRUSH_OLD = (HBRUSH)SelectObject(hdc, HBRUSH_BALL);
Ellipse(hdc,
(int)(ST_SIM_BALL_INSTANCE.S8_X_POSITION - U1_SIM_BALL_RADIUS),
(int)(ST_SIM_BALL_INSTANCE.S8_Y_POSITION - U1_SIM_BALL_RADIUS),
(int)(ST_SIM_BALL_INSTANCE.S8_X_POSITION + U1_SIM_BALL_RADIUS),
(int)(ST_SIM_BALL_INSTANCE.S8_Y_POSITION + U1_SIM_BALL_RADIUS));
SelectObject(hdc, HBRUSH_OLD);
DeleteObject(HBRUSH_BALL);
}
/* ------------------------------------------------------------------
Result window procedure
------------------------------------------------------------------ */
LRESULT CALLBACK FP_RESULTS_WINDOW_PROC(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
wchar_t WSTRING_BUFFER[256]; U2 U2_OFFSET = 10; HFONT HFONT_RESULT = CreateFontW(18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Arial"); HFONT HFONT_OLD = (HFONT)SelectObject(hdc, HFONT_RESULT); swprintf(WSTRING_BUFFER, 256, L"Total Travel Distance: %.2f meters", ST_SIM_BALL_INSTANCE.S8_TOTAL_DISTANCE / 2.0); TextOutW(hdc, 10, U2_OFFSET, WSTRING_BUFFER, wcslen(WSTRING_BUFFER)); U2_OFFSET += 20; for (U2 U2_I = 0; U2_I < ST_SIM_BALL_INSTANCE.U2_REBOUNDS_COUNT; U2_I++) { swprintf(WSTRING_BUFFER, 256, L"Rebound %d Height: %.2f meters", U2_I + 1, S8_SIM_REBOUND_HEIGHTS[U2_I] / 2.0); TextOutW(hdc, 10, U2_OFFSET, WSTRING_BUFFER, wcslen(WSTRING_BUFFER)); U2_OFFSET += 20; swprintf(WSTRING_BUFFER, 256, L"Cumulative Distance: %.2f meters", S8_SIM_CUMULATIVE_DISTANCES[U2_I] / 2.0); TextOutW(hdc, 10, U2_OFFSET, WSTRING_BUFFER, wcslen(WSTRING_BUFFER)); U2_OFFSET += 20; } SelectObject(hdc, HFONT_OLD); DeleteObject(HFONT_RESULT); EndPaint(hwnd, &ps); return 0; } case WM_DESTROY: HWND_RESULT_WINDOW = NULL; return 0; default: return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
/* ------------------------------------------------------------------
Display simulation results
------------------------------------------------------------------ */
void FP_DISPLAY_SIMULATION_RESULTS(HINSTANCE HINSTANCE_CURRENT) {
if (HWND_RESULT_WINDOW != NULL) {
InvalidateRect(HWND_RESULT_WINDOW, NULL, TRUE);
return;
}
const wchar_t CLASS_NAME[] = L"ResultWindow";
WNDCLASS WNDCLASS_RESULTS = {0};
WNDCLASS_RESULTS.lpfnWndProc = FP_RESULTS_WINDOW_PROC;
WNDCLASS_RESULTS.hInstance = HINSTANCE_CURRENT;
WNDCLASS_RESULTS.lpszClassName = CLASS_NAME;
WNDCLASS_RESULTS.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
RegisterClass(&WNDCLASS_RESULTS);
HWND_RESULT_WINDOW = CreateWindow(CLASS_NAME,
L"Simulation Results",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
800,
600,
NULL,
NULL,
HINSTANCE_CURRENT,
NULL);
ShowWindow(HWND_RESULT_WINDOW, SW_SHOW);
UpdateWindow(HWND_RESULT_WINDOW);
}
/* ------------------------------------------------------------------
Main window procedure
------------------------------------------------------------------ */
LRESULT CALLBACK FP_MAIN_WINDOW_PROC(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE: {
// Create input controls
CreateWindow(L"STATIC", L"Initial Height (meters):",
WS_VISIBLE | WS_CHILD,
20, U4_SIM_WINDOW_HEIGHT - 140, 170, 30,
hwnd, NULL, NULL, NULL);
HWND_CTRL_HEIGHT_INPUT = CreateWindow(L"EDIT", L"100", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 190, U4_SIM_WINDOW_HEIGHT - 140, 100, 30, hwnd, (HMENU)U2_CTRL_HEIGHT_INPUT, NULL, NULL); CreateWindow(L"STATIC", L"Max Rebounds:", WS_VISIBLE | WS_CHILD, 20, U4_SIM_WINDOW_HEIGHT - 100, 170, 30, hwnd, NULL, NULL, NULL); HWND_CTRL_REBOUNDS_INPUT = CreateWindow(L"EDIT", L"10", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_NUMBER, 190, U4_SIM_WINDOW_HEIGHT - 100, 100, 30, hwnd, (HMENU)U2_CTRL_REBOUNDS_INPUT, NULL, NULL); HWND_CTRL_SUBMIT_BUTTON = CreateWindow(L"BUTTON", L"Submit", WS_VISIBLE | WS_CHILD, 310, U4_SIM_WINDOW_HEIGHT - 120, 100, 40, hwnd, (HMENU)U2_CTRL_SUBMIT_BUTTON, NULL, NULL); // Initialize default ball position ST_SIM_BALL_INSTANCE.S8_X_POSITION = U4_SIM_WINDOW_WIDTH / 2.0; ST_SIM_BALL_INSTANCE.S8_Y_POSITION = U4_SIM_GROUND_Y - 50; SetTimer(hwnd, U4_SIM_TIMER_ID, 10, NULL); return 0; } case WM_COMMAND: { if (LOWORD(wParam) == U2_CTRL_SUBMIT_BUTTON) { wchar_t HEIGHT_BUFFER[32], REBOUNDS_BUFFER[32]; // Get input values GetWindowText(HWND_CTRL_HEIGHT_INPUT, HEIGHT_BUFFER, 32); double HEIGHT_VALUE = _wtof(HEIGHT_BUFFER); GetWindowText(HWND_CTRL_REBOUNDS_INPUT, REBOUNDS_BUFFER, 32); int REBOUNDS_VALUE = _wtoi(REBOUNDS_BUFFER); // Validate inputs if (HEIGHT_VALUE <= 0 || HEIGHT_VALUE > 150) { MessageBox(hwnd, L"Height out of range! (0-150 meters)", L"Invalid Input", MB_ICONERROR); return 0; } if (REBOUNDS_VALUE <= 0 || REBOUNDS_VALUE > 100) { MessageBox(hwnd, L"Rebound count must be between 1-100", L"Invalid Input", MB_ICONERROR); return 0; } // Stop current simulation KillTimer(hwnd, U4_SIM_TIMER_ID); // Initialize new simulation FP_SIM_INITIALIZE_BALL(HEIGHT_VALUE, REBOUNDS_VALUE); // Record start time U4_LAST_SIM_TICK_TIME = GetTickCount(); // Restart timer SetTimer(hwnd, U4_SIM_TIMER_ID, 10, NULL); // Force redraw InvalidateRect(hwnd, NULL, TRUE); } return 0; } case WM_TIMER: { if (wParam == U4_SIM_TIMER_ID) { // Calculate time delta U4 CURRENT_TIME = GetTickCount(); U4 DELTA_TIME = (U4_LAST_SIM_TICK_TIME == 0) ? 0 : (CURRENT_TIME - U4_LAST_SIM_TICK_TIME); U4_LAST_SIM_TICK_TIME = CURRENT_TIME; if (ST_SIM_BALL_INSTANCE.U1_SIM_ACTIVE) { // Update ball physics FP_SIM_UPDATE_BALL(DELTA_TIME); // Redraw only the necessary area RECT UPDATE_RECT = { 0, 0, U4_SIM_WINDOW_WIDTH, U4_SIM_GROUND_Y + U1_SIM_BALL_RADIUS }; InvalidateRect(hwnd, &UPDATE_RECT, TRUE); } else { // Simulation complete - show results KillTimer(hwnd, U4_SIM_TIMER_ID); FP_DISPLAY_SIMULATION_RESULTS( (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE) ); } } return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); // Clear background RECT rect; GetClientRect(hwnd, &rect); FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW+1)); // Draw simulation elements FP_SIM_RENDER_SCENE(hdc); // Display initial wait state if (ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS > 0) { wchar_t STATUS[100]; swprintf(STATUS, 100, L"Initial state: %.1f seconds remaining", ST_SIM_BALL_INSTANCE.S8_INITIAL_WAIT_TIME_MS / 1000.0); HFONT HFONT_STATUS = CreateFont(18, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, L"Arial"); HFONT HFONT_OLD = (HFONT)SelectObject(hdc, HFONT_STATUS); TextOut(hdc, 20, 20, STATUS, wcslen(STATUS)); SelectObject(hdc, HFONT_OLD); DeleteObject(HFONT_STATUS); } EndPaint(hwnd, &ps); return 0; } case WM_DESTROY: { KillTimer(hwnd, U4_SIM_TIMER_ID); PostQuitMessage(0); return 0; } default: return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
/* ------------------------------------------------------------------
Application entry point
------------------------------------------------------------------ */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
const wchar_t CLASS_NAME[] = L"BouncingBallSimulation";
WNDCLASS WNDCLASS_MAIN = {0};
WNDCLASS_MAIN.lpfnWndProc = FP_MAIN_WINDOW_PROC;
WNDCLASS_MAIN.hInstance = hInstance;
WNDCLASS_MAIN.lpszClassName = CLASS_NAME;
WNDCLASS_MAIN.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
if (!RegisterClass(&WNDCLASS_MAIN)) {
return 0;
}
// Calculate window size including non-client area
RECT rect = {0, 0, U4_SIM_WINDOW_WIDTH, U4_SIM_WINDOW_HEIGHT};
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, TRUE);
int WIDTH = rect.right - rect.left;
int HEIGHT = rect.bottom - rect.top;
// Create main window
HWND_SIM_MAIN_WINDOW = CreateWindow(
CLASS_NAME, L"Bouncing Ball Simulation",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT,
NULL, NULL, hInstance, NULL
);
if (!HWND_SIM_MAIN_WINDOW) {
return 0;
}
// Main message loop
MSG MSG_SIM_LOOP;
while (GetMessage(&MSG_SIM_LOOP, NULL, 0, 0)) {
TranslateMessage(&MSG_SIM_LOOP);
DispatchMessage(&MSG_SIM_LOOP);
}
return (int)MSG_SIM_LOOP.wParam;
}
就在源代码上修改编码规范,刚刚的代码又逻辑不通了’
最新发布