Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <windows.h>
- #include <winsock2.h>
- #include <vector>
- #include <cmath>
- #include <cstdlib>
- #include <ctime>
- #include <string>
- #include <thread>
- #include <map>
- #pragma comment(lib, "ws2_32.lib")
- #define BALL_RADIUS 10
- #define TABLE_WIDTH 700
- #define TABLE_HEIGHT 400
- #define HOLE_RADIUS 15
- #define MAX_SHOT_POWER 20.0f
- #define GAME_MODE_STANDARD 1
- #define GAME_MODE_TIMED 2
- // Struct to represent a ball
- struct Ball {
- float x, y, vx, vy, spinX, spinY;
- COLORREF color;
- bool isPocketed;
- bool isStripe;
- int radius = BALL_RADIUS;
- float mass = 1.0f;
- };
- // Player struct
- struct Player {
- bool isSolid;
- std::vector<Ball> pocketedBalls;
- bool turn;
- bool fouled;
- bool isAI;
- int score;
- int fouls;
- };
- // Lobby for multiplayer games
- std::map<int, SOCKET> lobby;
- std::vector<std::string> availableGames;
- int playerID;
- bool inLobby = true;
- // Multiplayer network setup (TCP for lobbies)
- SOCKET sock;
- SOCKADDR_IN serverAddr, clientAddr;
- char recvBuffer[512];
- bool isMultiplayer = false;
- bool isHost = false;
- // Global Variables
- Ball cueBall = {100, 250, 0, 0, 0, 0, RGB(255, 255, 255), false, false}; // White cue ball
- Ball blackBall = {400, 250, 0, 0, 0, 0, RGB(0, 0, 0), false, false}; // Black 8-ball
- Player player1 = {true, {}, true, false, false, 0, 0}; // Human player
- Player player2 = {false, {}, false, false, true, 0, 0}; // AI/remote player
- std::vector<Ball> balls;
- HWND hwnd;
- bool gameOver = false;
- Player* currentPlayer = &player1;
- std::string playerName;
- std::vector<Ball> replayFrames; // Store frames for replay
- // Cue variables for control
- float cueAngle = 0.0f; // Angle of the shot in radians
- float shotPower = 0.0f; // Power of the shot
- float cueSpinX = 0.0f; // Horizontal spin (English)
- float cueSpinY = 0.0f; // Vertical spin (English)
- POINT mousePos; // Mouse position for aiming and power control
- // Customization options
- COLORREF tableColor = RGB(34, 139, 34); // Default green table
- COLORREF cueColor = RGB(139, 69, 19); // Default brown cue
- COLORREF stripeBallColor = RGB(255, 255, 0); // Default yellow stripe
- COLORREF solidBallColor = RGB(255, 0, 0); // Default red solid
- // UI Elements
- RECT powerMeterRect = {750, 50, 780, 450}; // Power meter on the right side
- RECT spinIndicatorRect = {60, 480, 140, 560}; // Spin indicator near the bottom
- int powerMeterLevel = 0; // Indicates shot power level
- int gameMode = GAME_MODE_STANDARD; // Default game mode
- int timer = 120; // 2-minute timer for timed mode
- bool replayMode = false; // Track if replay mode is active
- // Utility functions
- bool IsColliding(Ball& b1, Ball& b2);
- void ResolveCollision(Ball& b1, Ball& b2);
- bool IsPocketed(Ball& ball);
- void HandleFouls(Player& player);
- void ApplySpin(Ball& ball);
- void AdjustShotPower(POINT& mousePos);
- void DrawPowerMeter(HDC hdc);
- void DrawSpinIndicator(HDC hdc);
- void SwitchTurns();
- void AITakeShot(); // AI player logic
- void PredictShot(Ball& ball, float& shotScore); // AI shot prediction logic
- void CheckGameOver();
- void UpdateScores(HDC hdc);
- void StartTimedMode();
- void InitNetworkLobby(); // Initialize lobby-based multiplayer system
- void InitNetwork(bool isHost); // Initialize internet multiplayer network
- void SendNetworkData(const std::string& data); // Send data over the network
- void ReceiveNetworkData(); // Receive data from the network
- void DisplayLobbyMenu(); // Lobby system UI
- void CustomizationMenu(); // Customization UI
- void SelectCustomization(); // Apply customization options
- void ReplayShot(); // Replay mode logic
- void CheckFoul(Player& player, Ball& cueBall, std::vector<Ball>& balls) // Remove if Redundant !!!
- void DisplayFoul(); // Remove if Redundant !!!
- void HandlePlayerTurn(Player& player, Ball& cueBall); // Remove if Redundant !!!
- // Function to draw the table and pockets with customization
- void DrawTable(HDC hdc) {
- // Set table color
- HBRUSH tableBrush = CreateSolidBrush(tableColor); // Apply table customization
- RECT tableRect = {50, 50, 750, 450}; // Set size of the table
- FillRect(hdc, &tableRect, tableBrush);
- // Draw pocket holes (black)
- HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0)); // Black pockets
- SelectObject(hdc, blackBrush);
- Ellipse(hdc, 55, 55, 55 + HOLE_RADIUS * 2, 55 + HOLE_RADIUS * 2); // Top-left
- Ellipse(hdc, 745 - HOLE_RADIUS * 2, 55, 745, 55 + HOLE_RADIUS * 2); // Top-right
- Ellipse(hdc, 55, 445 - HOLE_RADIUS * 2, 55 + HOLE_RADIUS * 2, 445); // Bottom-left
- Ellipse(hdc, 745 - HOLE_RADIUS * 2, 445 - HOLE_RADIUS * 2, 745, 445); // Bottom-right
- Ellipse(hdc, 395 - HOLE_RADIUS * 2, 55, 405 + HOLE_RADIUS * 2, 55 + HOLE_RADIUS * 2); // Top-middle
- Ellipse(hdc, 395 - HOLE_RADIUS * 2, 445 - HOLE_RADIUS * 2, 405 + HOLE_RADIUS * 2, 445); // Bottom-middle
- }
- // Function to draw a ball (solid or stripe) with customization
- void DrawBall(HDC hdc, Ball& ball) {
- HBRUSH ballBrush = CreateSolidBrush(ball.isStripe ? stripeBallColor : solidBallColor); // Custom ball colors
- HPEN ballPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0)); // Black border
- SelectObject(hdc, ballBrush);
- SelectObject(hdc, ballPen);
- // Draw the ball (if not pocketed)
- if (!ball.isPocketed) {
- // Draw shadow first for 3D effect
- Ellipse(hdc, ball.x - ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius);
- // Draw stripe if it's a striped ball
- if (ball.isStripe) {
- HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
- SelectObject(hdc, whiteBrush);
- Rectangle(hdc, ball.x - ball.radius, ball.y - 3, ball.x + ball.radius, ball.y + 3);
- }
- }
- /* if (!ball.isPocketed) {
- // Draw shadow first for 3D effect
- Ellipse(hdc, ball.x - ball.radius + 3, ball.y - ball.radius + 3, ball.x + ball.radius + 3, ball.y + ball.radius + 3);
- // Draw the ball with shading
- SelectObject(hdc, shadowBrush);
- Ellipse(hdc, ball.x - ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius);
- } */
- // Cleanup
- DeleteObject(ballBrush);
- DeleteObject(ballPen);
- }
- // Function to handle ball physics with spin and friction
- void HandleBallPhysics(Ball& ball, std::vector<Ball>& allBalls) {
- // Update position based on velocity
- ball.x += ball.vx + ball.spinX;
- ball.y += ball.vy + ball.spinY;
- // Handle table boundary collision (bounce off walls)
- if (ball.x <= 50 || ball.x >= 750) ball.vx *= -1; // Horizontal
- if (ball.y <= 50 || ball.y >= 450) ball.vy *= -1; // Vertical
- // Handle ball-to-ball collisions
- for (Ball& otherBall : allBalls) {
- if (&ball != &otherBall && IsColliding(ball, otherBall)) {
- ResolveCollision(ball, otherBall);
- }
- }
- // Apply friction and reduce spin over time
- ball.vx *= 0.98;
- ball.vy *= 0.98;
- ball.spinX *= 0.97;
- ball.spinY *= 0.97;
- }
- // Apply spin to a ball (English)
- void ApplySpin(Ball& ball) {
- ball.spinX += cueSpinX * 0.1f; // Horizontal spin effect
- ball.spinY += cueSpinY * 0.1f; // Vertical spin effect
- }
- // Check if two balls are colliding
- bool IsColliding(Ball& b1, Ball& b2) {
- float dx = b1.x - b2.x;
- float dy = b1.y - b2.y;
- float distance = sqrt(dx * dx + dy * dy);
- return distance < (b1.radius + b2.radius);
- }
- // Resolve collision between two balls
- void ResolveCollision(Ball& b1, Ball& b2) {
- float nx = b2.x - b1.x;
- float ny = b2.y - b1.y;
- float distance = sqrt(nx * nx + ny * ny);
- nx /= distance;
- ny /= distance;
- float kx = (b1.vx - b2.vx) * nx;
- float ky = (b1.vy - b2.vy) * ny;
- float p = 2.0 * (kx * nx + ky * ny) / (b1.mass + b2.mass);
- b1.vx -= p * b2.mass * nx;
- b1.vy -= p * b2.mass * ny;
- b2.vx += p * b1.mass * nx;
- b2.vy += p * b1.mass * ny;
- }
- // Adjust shot power based on mouse position
- void AdjustShotPower(POINT& mousePos) {
- float distX = mousePos.x - cueBall.x;
- float distY = mousePos.y - cueBall.y;
- shotPower = sqrt(distX * distX + distY * distY) / 10.0f; // Adjust this value for power sensitivity
- shotPower = min(shotPower, MAX_SHOT_POWER); // Cap the shot power
- powerMeterLevel = (int)(shotPower / MAX_SHOT_POWER * 100); // Set power level for power meter
- }
- // AI shot prediction logic (multi-step and tactical)
- void PredictShot(Ball& ball, float& shotScore) {
- // Simulate shot, predict outcome, and score based on potential outcome
- float distX = ball.x - cueBall.x;
- float distY = ball.y - cueBall.y;
- float dist = sqrt(distX * distX + distY * distY);
- float angle = atan2(distY, distX);
- // Calculate shot score based on distance and angle
- shotScore = -dist + cos(angle) * 50.0f;
- // Increase score for defensive plays or multi-step shot setups
- if (distX < 100 && distY < 100) {
- shotScore += 50.0f; // Bonus for defensive or setup shots
- }
- }
- // Function to check for pocketing a ball
- bool IsPocketed(Ball& ball) {
- return (ball.x < 55 + HOLE_RADIUS && ball.y < 55 + HOLE_RADIUS) || // Top-left pocket
- (ball.x > 745 - HOLE_RADIUS && ball.y < 55 + HOLE_RADIUS) || // Top-right pocket
- (ball.x < 55 + HOLE_RADIUS && ball.y > 445 - HOLE_RADIUS) || // Bottom-left pocket
- (ball.x > 745 - HOLE_RADIUS && ball.y > 445 - HOLE_RADIUS) || // Bottom-right pocket
- (ball.x > 395 - HOLE_RADIUS && ball.x < 405 + HOLE_RADIUS &&
- (ball.y < 55 + HOLE_RADIUS || ball.y > 445 - HOLE_RADIUS)); // Middle pockets
- }
- // Function to draw the power meter
- void DrawPowerMeter(HDC hdc) {
- HBRUSH powerBrush = CreateSolidBrush(RGB(0, 255, 0)); // Green for power
- RECT powerLevel = powerMeterRect;
- powerLevel.top = powerMeterRect.bottom - powerMeterLevel * (powerMeterRect.bottom - powerMeterRect.top) / 100; // Adjust height
- FillRect(hdc, &powerLevel, powerBrush);
- DeleteObject(powerBrush);
- }
- // Function to draw the spin indicator
- void DrawSpinIndicator(HDC hdc) {
- HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255)); // Cue ball color
- Ellipse(hdc, spinIndicatorRect.left, spinIndicatorRect.top, spinIndicatorRect.right, spinIndicatorRect.bottom); // Draw cue ball
- // Draw spin dot (shows where spin is being applied)
- HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0)); // Red dot for spin
- int spinX = (int)(cueSpinX * 10); // Scale spin for visualization
- int spinY = (int)(cueSpinY * 10);
- int centerX = (spinIndicatorRect.left + spinIndicatorRect.right) / 2;
- int centerY = (spinIndicatorRect.top + spinIndicatorRect.bottom) / 2;
- Ellipse(hdc, centerX + spinX - 5, centerY + spinY - 5, centerX + spinX + 5, centerY + spinY + 5); // Spin dot
- DeleteObject(whiteBrush);
- DeleteObject(redBrush);
- }
- // Handle fouls (e.g., pocketing the cue ball or failing to hit a ball)
- void HandleFouls(Player& player) {
- if (IsPocketed(cueBall)) {
- player.fouled = true;
- player.fouls++;
- }
- }
- // Multiplayer setup (TCP/IP for internet)
- void InitNetwork(bool isHost) {
- WSADATA wsa;
- WSAStartup(MAKEWORD(2, 2), &wsa);
- sock = socket(AF_INET, SOCK_STREAM, 0); // Use TCP for internet play
- memset(&serverAddr, 0, sizeof(serverAddr));
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_port = htons(8888);
- if (isHost) {
- serverAddr.sin_addr.s_addr = INADDR_ANY;
- bind(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
- listen(sock, 1);
- int clientSize = sizeof(clientAddr);
- sock = accept(sock, (SOCKADDR*)&clientAddr, &clientSize);
- isMultiplayer = true;
- isHost = true;
- } else {
- serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Connect to host IP
- connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
- isMultiplayer = true;
- }
- }
- // Send data over the network
- void SendNetworkData(const std::string& data) {
- send(sock, data.c_str(), data.size(), 0);
- }
- // Receive data from the network
- void ReceiveNetworkData() {
- int bytesReceived = recv(sock, recvBuffer, sizeof(recvBuffer), 0);
- recvBuffer[bytesReceived] = '\0';
- // Parse and process opponent's move
- std::string receivedData(recvBuffer);
- // Process opponent's shot...
- }
- // Check if the black ball has been pocketed and declare the winner
- void CheckGameOver() {
- if (IsPocketed(blackBall)) {
- gameOver = true;
- Player* winner = (currentPlayer == &player1) ? &player2 : &player1;
- std::string result = winner == &player1 ? "Player 1 Wins!" : "Player 2 Wins!";
- SendNetworkData(result);
- MessageBox(hwnd, result.c_str(), "Game Over", MB_OK);
- PostQuitMessage(0);
- }
- }
- // Update scores based on pocketed balls
- void UpdateScores(HDC hdc) {
- wchar_t scoreText[100];
- wsprintf(scoreText, L"Player 1 Score: %d | Player 2 Score: %d", player1.score, player2.score);
- SetTextColor(hdc, RGB(0, 0, 0));
- SetBkMode(hdc, TRANSPARENT);
- TextOut(hdc, 300, 470, scoreText, lstrlen(scoreText));
- // Display fouls
- wchar_t foulText[100];
- wsprintf(foulText, L"Fouls: Player 1: %d | Player 2: %d", player1.fouls, player2.fouls);
- TextOut(hdc, 300, 490, foulText, lstrlen(foulText));
- }
- // Replay mode: record frames
- void RecordReplayFrame() {
- std::vector<Ball> frame;
- for (const auto& ball : balls) {
- frame.push_back(ball);
- }
- replayFrames.push_back(frame);
- }
- // Replay mode: show replay frames
- void ShowReplayFrames(HDC hdc) {
- if (!replayMode) return;
- for (size_t i = 0; i < replayFrames.size(); ++i) {
- for (Ball& ball : replayFrames[i]) {
- DrawBall(hdc, ball);
- }
- Sleep(50); // Slow down replay for visualization
- }
- replayMode = false; // Exit replay mode after showing
- }
- // Apply customization options from menu
- void SelectCustomization() {
- tableColor = RGB(0, 100, 100); // Example: Teal table
- cueColor = RGB(200, 200, 50); // Example: Golden cue
- stripeBallColor = RGB(0, 0, 255); // Example: Blue stripe
- solidBallColor = RGB(0, 255, 0); // Example: Green solid
- }
- // Function to display the lobby menu
- void DisplayLobbyMenu() {
- std::cout << "Enter your player name: ";
- std::cin >> playerName;
- std::cout << "\nAvailable Games:\n";
- for (const auto& game : availableGames) {
- std::cout << "- " << game << std::endl;
- }
- std::cout << "Press 'H' to Host a new game or 'J' to join one: ";
- char choice;
- std::cin >> choice;
- if (choice == 'H') {
- InitNetwork(true); // Host a new game
- } else if (choice == 'J') {
- InitNetwork(false); // Join an existing game
- }
- }
- // Lobby-based network initialization (TCP for hosting/joining games)
- void InitNetworkLobby() {
- WSADATA wsa;
- WSAStartup(MAKEWORD(2, 2), &wsa);
- sock = socket(AF_INET, SOCK_STREAM, 0);
- memset(&serverAddr, 0, sizeof(serverAddr));
- serverAddr.sin_family = AF_INET;
- serverAddr.sin_port = htons(8888);
- serverAddr.sin_addr.s_addr = INADDR_ANY;
- if (bind(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
- MessageBox(hwnd, "Failed to create lobby", "Error", MB_OK);
- return;
- }
- listen(sock, 10); // Allow up to 10 players to join
- while (inLobby) {
- int clientSize = sizeof(clientAddr);
- SOCKET clientSock = accept(sock, (SOCKADDR*)&clientAddr, &clientSize);
- if (clientSock != INVALID_SOCKET) {
- playerID++;
- lobby[playerID] = clientSock;
- std::thread([](SOCKET s, int id) {
- char buffer[512];
- int received = recv(s, buffer, sizeof(buffer), 0);
- buffer[received] = '\0';
- lobby[id] = s;
- }, clientSock, playerID).detach();
- }
- }
- }
- // Function to start the timed mode game
- void StartTimedMode() {
- gameMode = GAME_MODE_TIMED;
- timer = 120; // 2-minute timer
- SetTimer(hwnd, 1, 1000, NULL); // Start a 1-second timer
- }
- // Timer event handler
- void HandleTimerEvent() {
- if (gameMode == GAME_MODE_TIMED) {
- if (timer > 0) {
- timer--;
- } else {
- // Time up, game over
- MessageBox(hwnd, "Time's up! Game Over!", "Game Over", MB_OK);
- gameOver = true;
- PostQuitMessage(0);
- }
- }
- }
- // Function to draw the cue stick and aiming aids
- void DrawCueStick(HDC hdc, Ball& cueBall, float angle, float power) {
- // Cue stick
- HPEN cuePen = CreatePen(PS_SOLID, 6, RGB(139, 69, 19)); // Brown cue stick
- SelectObject(hdc, cuePen);
- // Draw the cue stick based on angle
- MoveToEx(hdc, cueBall.x, cueBall.y, NULL);
- LineTo(hdc, cueBall.x + power * cos(angle), cueBall.y + power * sin(angle)); // Stick
- // Aiming aid (dash line to ball trajectory)
- HPEN dashPen = CreatePen(PS_DASH, 1, RGB(0, 0, 255)); // Blue aiming aid
- SelectObject(hdc, dashPen);
- LineTo(hdc, cueBall.x + 150 * cos(angle), cueBall.y + 150 * sin(angle)); // Aiming aid
- DeleteObject(cuePen);
- DeleteObject(dashPen);
- }
- // AI takes a shot with advanced prediction logic
- void AITakeShot() {
- Ball* targetBall = nullptr;
- float bestScore = -9999.0f;
- for (Ball& ball : balls) {
- if (!ball.isPocketed && currentPlayer->isSolid == !ball.isStripe) {
- float shotScore;
- PredictShot(ball, shotScore);
- if (shotScore > bestScore) {
- bestScore = shotScore;
- targetBall = &ball;
- }
- }
- }
- if (targetBall) {
- cueAngle = atan2(targetBall->y - cueBall.y, targetBall->x - cueBall.x);
- shotPower = (rand() % 10 + 10) / 10.0f;
- cueBall.vx = shotPower * cos(cueAngle);
- cueBall.vy = shotPower * sin(cueAngle);
- ApplySpin(cueBall);
- SwitchTurns();
- }
- }
- // Switch turns between players after each shot or foul
- void SwitchTurns() {
- currentPlayer->turn = false;
- currentPlayer = (currentPlayer == &player1) ? &player2 : &player1;
- currentPlayer->turn = true;
- // Trigger AI or network action if it's AI's or remote player's turn
- if (currentPlayer->isAI) {
- AITakeShot();
- } else if (isMultiplayer) {
- ReceiveNetworkData(); // Get the opponent's move
- }
- }
- // Remove if Redundant !!!
- /* void HandleFouls(Player& player) {
- if (IsPocketed(cueBall)) {
- player.fouled = true;
- }
- } */
- // Remove if Redundant !!!
- // Game logic (foul detection, player switching, pocket checking)
- void CheckFoul(Player& player, Ball& cueBall, std::vector<Ball>& balls) {
- if (player.isSolid && IsPocketed(blackBall)) {
- // 8-ball pocketed before all solids, foul
- DisplayFoul();
- player.canMoveCue = true;
- } else if (!player.isSolid && IsPocketed(blackBall)) {
- // 8-ball pocketed before all stripes, foul
- DisplayFoul();
- player.canMoveCue = true;
- }
- }
- // Remove if Redundant !!!
- // Display foul text
- void DisplayFoul() {
- HDC hdc = GetDC(hwnd);
- SetTextColor(hdc, RGB(255, 0, 0));
- TextOut(hdc, 10, 10, "FOUL!", 5);
- ReleaseDC(hwnd, hdc);
- }
- // Remove if Redundant !!!
- // Function to handle player actions (spin, re-spotting, fouls)
- void HandlePlayerTurn(Player& player, Ball& cueBall) {
- if (player.fouled) {
- // Cue ball re-spotting
- cueBall.x = 100;
- cueBall.y = 250;
- cueBall.vx = cueBall.vy = cueBall.spinX = cueBall.spinY = 0;
- player.fouled = false;
- }
- }
- // Main game loop
- void GameLoop(HDC hdc) {
- // Clear screen
- RECT clientRect;
- GetClientRect(hwnd, &clientRect);
- FillRect(hdc, &clientRect, (HBRUSH)(COLOR_WINDOW + 1));
- // Draw table and balls
- DrawTable(hdc);
- for (Ball& ball : balls) {
- HandleBallPhysics(ball, balls);
- DrawBall(hdc, ball);
- if (IsPocketed(ball)) ball.isPocketed = true; // Pocket the ball
- }
- // Draw the cue ball
- DrawBall(hdc, cueBall);
- if (!gameOver) {
- HandleFouls(*currentPlayer);
- CheckGameOver();
- if (gameMode == GAME_MODE_TIMED) {
- wchar_t timerText[50];
- wsprintf(timerText, L"Time Remaining: %d seconds", timer);
- TextOut(hdc, 350, 20, timerText, lstrlen(timerText));
- }
- }
- DrawCueStick(hdc, cueBall, cueAngle, shotPower);
- DrawPowerMeter(hdc);
- DrawSpinIndicator(hdc);
- UpdateScores(hdc);
- }
- // Main game window procedure
- LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
- PAINTSTRUCT ps;
- HDC hdc;
- switch (msg) {
- case WM_PAINT:
- hdc = BeginPaint(hwnd, &ps);
- GameLoop(hdc);
- EndPaint(hwnd, &ps);
- break;
- case WM_MOUSEMOVE:
- mousePos.x = LOWORD(lParam);
- mousePos.y = HIWORD(lParam);
- AdjustShotPower(mousePos);
- cueAngle = atan2(mousePos.y - cueBall.y, mousePos.x - cueBall.x);
- InvalidateRect(hwnd, NULL, FALSE);
- break;
- case WM_LBUTTONDOWN:
- cueBall.vx = shotPower * cos(cueAngle);
- cueBall.vy = shotPower * sin(cueAngle);
- ApplySpin(cueBall);
- if (isMultiplayer) {
- std::string data = "SHOT:" + std::to_string(cueBall.vx) + "," + std::to_string(cueBall.vy);
- SendNetworkData(data);
- }
- SwitchTurns();
- InvalidateRect(hwnd, NULL, FALSE);
- break;
- case WM_KEYDOWN:
- switch (wParam) {
- case VK_LEFT:
- cueSpinX -= 0.1f;
- break;
- case VK_RIGHT:
- cueSpinX += 0.1f;
- break;
- case VK_UP:
- cueSpinY -= 0.1f;
- break;
- case VK_DOWN:
- cueSpinY += 0.1f;
- break;
- case 'T':
- StartTimedMode();
- break;
- case 'M':
- InitNetwork(true);
- break;
- case 'C':
- InitNetwork(false);
- break;
- case 'R':
- replayMode = true;
- InvalidateRect(hwnd, NULL, FALSE);
- break;
- case 'P':
- CustomizationMenu();
- InvalidateRect(hwnd, NULL, FALSE);
- break;
- }
- InvalidateRect(hwnd, NULL, FALSE);
- break;
- case WM_DESTROY:
- closesocket(sock);
- WSACleanup();
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
- return 0;
- }
- // WinMain
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
- MSG msg;
- WNDCLASS wc = {0};
- wc.lpfnWndProc = WndProc;
- wc.hInstance = hInstance;
- wc.lpszClassName = "BilliardsGame";
- RegisterClass(&wc);
- hwnd = CreateWindowEx(0, "BilliardsGame", "Enhanced 8-Ball Billiards", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
- ShowWindow(hwnd, nCmdShow);
- // Initialize balls (8-ball game setup)
- balls.push_back(cueBall);
- balls.push_back(blackBall);
- // Add all solid and stripe balls
- for (int i = 1; i <= 7; ++i) {
- Ball solidBall = {150 + i * 30, 200, 0, 0, 0, 0, solidBallColor, false, false};
- balls.push_back(solidBall);
- Ball stripeBall = {150 + i * 30, 300, 0, 0, 0, 0, stripeBallColor, false, true};
- balls.push_back(stripeBall);
- }
- // Seed the random number generator for AI shots
- srand((unsigned)time(NULL));
- while (GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return msg.wParam;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement