Stefan Ram
2024-09-07 16:55:41 UTC
Reply
Permalinkwith a little help from a chatbot. It's still got some hiccups
and bugs, but hey, it's showing some basic vibes!
I've got a bit of a clue about C++, but the last time I dabbled
a bit in Windows programming was ages ago. Honestly, I wouldn't
have been able to make this happen without some guidance!
The chatbot kicked things off for me with a starter program, and
now I can tweak it to get closer to what I really want to create.
(I basically told the chatbot that I wanted a C++ program for
Windows where a black circle moves towards a red one. Then I went
over some details about how I wanted it coded, and together with
the chatbot, I squashed the bugs until it was running.)
The end condition for the loop still ain't working.
The black circle should stop moving when it hits the red circle.
Instead, the program's stuck in an endless loop (it'll freeze!).
But that's chill. I can handle it later.
I just added the "Sleep(60);" to slow things down so that it does
not run too fast, but it's actually intended without this line.
Manual: Hit Alt-R or just click "Run." You should see two
circles pop up in random spots, with the black one moving
towards the red one. Then, the program will freeze up,
and you'll need to force quit it from outside. (Closing the
console seems to work.)
Some compiler options used (the chatbot explained that to me, too!):
. . . main.cpp -static -mwindows -lquadmath -luser32 -lgdi32
. main.cpp
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <iostream>
const int WIDTH = 800; // Width of the window
const int HEIGHT = 600; // Height of the window
HBITMAP hBitmap;
HDC hdcMem, hdcWindow;
int redCircleX, redCircleY, blackCircleX, blackCircleY;
bool isRunning = false; // Flag to indicate if the simulation is running
HWND hwnd; // Declare hwnd as a global variable
// Define a custom message for the simulation
#define WM_SIMULATE (WM_USER + 1)
// Timing variables
DWORD lastUpdateTime = 0; // Last time the window was updated
const DWORD updateInterval = 50; // Update interval in milliseconds (20 updates per second)
void CreateConsole() {
AllocConsole(); // Allocate a new console for the application
FILE* fp;
freopen_s(&fp, "CONOUT$", "w", stdout); // Redirect stdout to the console
freopen_s(&fp, "CONOUT$", "w", stderr); // Redirect stderr to the console
}
void StartSimulation() {
std::srand(std::time(0));
redCircleX = std::rand() % WIDTH;
redCircleY = std::rand() % HEIGHT;
blackCircleX = std::rand() % WIDTH;
blackCircleY = std::rand() % HEIGHT;
std::cout << "Red Circle Position: (" << redCircleX << ", " << redCircleY << ")" << std::endl;
std::cout << "Black Circle Position: (" << blackCircleX << ", " << blackCircleY << ")" << std::endl;
// Fill bitmap with white
HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
RECT rect = {0, 0, WIDTH, HEIGHT}; // Define RECT here
FillRect(hdcMem, &rect, whiteBrush);
DeleteObject(whiteBrush);
// Draw red circle
HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
SelectObject(hdcMem, redBrush);
Ellipse(hdcMem, redCircleX - 10, redCircleY - 10, redCircleX + 10, redCircleY + 10);
DeleteObject(redBrush);
// Draw black circle
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
SelectObject(hdcMem, blackBrush);
Ellipse(hdcMem, blackCircleX - 10, blackCircleY - 10, blackCircleX + 10, blackCircleY + 10);
DeleteObject(blackBrush);
isRunning = true; // Set the flag to indicate that the simulation is running
lastUpdateTime = GetTickCount(); // Initialize the last update time
}
void SimulateStep() {
// Check neighboring pixels
if ((blackCircleX > 0 && blackCircleY > 0 && GetPixel(hdcMem, blackCircleX - 1, blackCircleY) == RGB(255, 0, 0)) ||
(blackCircleX < WIDTH - 1 && blackCircleY > 0 && GetPixel(hdcMem, blackCircleX + 1, blackCircleY) == RGB(255, 0, 0)) ||
(blackCircleX > 0 && blackCircleY < HEIGHT - 1 && GetPixel(hdcMem, blackCircleX, blackCircleY - 1) == RGB(255, 0, 0)) ||
(blackCircleX < WIDTH - 1 && blackCircleY < HEIGHT - 1 && GetPixel(hdcMem, blackCircleX, blackCircleY + 1) == RGB(255, 0, 0))) {
std::cout << "Black circle is now adjacent to red circle." << std::endl;
isRunning = false; // Stop the simulation
return; // Exit the step
}
// Move black circle towards red circle
if (blackCircleX < redCircleX) blackCircleX++;
else if (blackCircleX > redCircleX) blackCircleX--;
if (blackCircleY < redCircleY) blackCircleY++;
else if (blackCircleY > redCircleY) blackCircleY--;
// Clear and redraw
HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
RECT rect = {0, 0, WIDTH, HEIGHT}; // Define RECT here
FillRect(hdcMem, &rect, whiteBrush); // Use the defined RECT
DeleteObject(whiteBrush);
// Draw red circle
HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
SelectObject(hdcMem, redBrush);
Ellipse(hdcMem, redCircleX - 10, redCircleY - 10, redCircleX + 10, redCircleY + 10);
DeleteObject(redBrush);
// Draw black circle
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
SelectObject(hdcMem, blackBrush);
Ellipse(hdcMem, blackCircleX - 10, blackCircleY - 10, blackCircleX + 10, blackCircleY + 10);
DeleteObject(blackBrush);
// Check if it's time to update the window
DWORD currentTime = GetTickCount();
if (currentTime - lastUpdateTime >= updateInterval) {
InvalidateRect(hwnd, NULL, TRUE); // Use TRUE to force a full redraw
UpdateWindow(hwnd); // Force the window to repaint immediately
lastUpdateTime = currentTime; // Update the last update time
}
// Debug output for the current positions
std::cout << "Current Black Circle Position: (" << blackCircleX << ", " << blackCircleY << ")" << std::endl;
Sleep(60);
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_PAINT: {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
BitBlt(ps.hdc, 0, 0, WIDTH, HEIGHT, hdcMem, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
break;
}
case WM_DESTROY: {
DeleteObject(hBitmap);
DeleteDC(hdcMem);
PostQuitMessage(0);
break;
}
case WM_COMMAND: {
if (LOWORD(wParam) == 1) { // "Run" menu item
std::cout << "Run command triggered." << std::endl;
StartSimulation(); // Start the simulation
PostMessage(hwnd, WM_SIMULATE, 0, 0); // Post a custom message to start the simulation loop
}
break;
}
case WM_SIMULATE: {
if (isRunning) {
SimulateStep(); // Perform one step of the simulation
PostMessage(hwnd, WM_SIMULATE, 0, 0); // Post the message again for the next iteration
}
break;
}
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
CreateConsole(); // Create console for debug output
// Create memory device context
hdcMem = CreateCompatibleDC(NULL);
hBitmap = CreateCompatibleBitmap(GetDC(NULL), WIDTH, HEIGHT);
SelectObject(hdcMem, hBitmap);
// Register window class
const char CLASS_NAME[] = "Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the menu
HMENU hMenu = CreateMenu();
AppendMenu(hMenu, MF_STRING, 1, "Run"); // Add "Run" menu item
// Create window
hwnd = CreateWindowEx(0, CLASS_NAME, "Circle Simulation", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, hMenu, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
// Message loop
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}