Advertisement
alien_fx_fiend

Yahoo-8Ball-Pool-Clone *FAILED PROJECT*

Oct 22nd, 2024 (edited)
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 25.99 KB | Source Code | 0 0
  1. ==++"Yahoo-Java-Pool.cpp" File 1/1 SourceCode++==::
  2. #include <windows.h>
  3. //#include <winsock2.h>
  4. #include <vector>
  5. #include <cmath>
  6. #include <cstdlib>
  7. #include <ctime>
  8. #include <string>
  9. #include <thread>
  10. #include <map>
  11. #include "resource.h"  // Add this with your other includes
  12.  
  13. //#pragma comment(lib, "ws2_32.lib")
  14.  
  15. #define BALL_RADIUS 10
  16. #define TABLE_WIDTH 700
  17. #define TABLE_HEIGHT 400
  18. #define HOLE_RADIUS 15
  19. #define MAX_SHOT_POWER 20.0f
  20. #define GAME_MODE_STANDARD 1
  21. #define GAME_MODE_TIMED 2
  22.  
  23. // Struct to represent a ball
  24. struct Ball {
  25.     float x, y, vx, vy, spinX, spinY;
  26.     COLORREF color;
  27.     bool isPocketed;
  28.     bool isStripe;
  29.     int radius = BALL_RADIUS;
  30.     float mass = 1.0f;
  31. };
  32.  
  33. // Player struct
  34. struct Player {
  35.     bool isSolid;
  36.     std::vector<Ball> pocketedBalls;
  37.     bool turn;
  38.     bool fouled;
  39.     bool isAI;
  40.     int score;
  41.     int fouls;
  42. };
  43.  
  44. // Lobby for multiplayer games
  45. //std::map<int, SOCKET> lobby;
  46. //std::vector<std::string> availableGames;
  47. //int playerID;
  48. //bool inLobby = true;
  49.  
  50. // Multiplayer network setup (TCP for lobbies)
  51. //SOCKET sock;
  52. //SOCKADDR_IN serverAddr, clientAddr;
  53. //char recvBuffer[512];
  54. //bool isMultiplayer = false;
  55. //bool isHost = false;
  56.  
  57. // Global Variables
  58. Ball cueBall = {100, 250, 0, 0, 0, 0, RGB(255, 255, 255), false, false}; // White cue ball
  59. Ball blackBall = {400, 250, 0, 0, 0, 0, RGB(0, 0, 0), false, false}; // Black 8-ball
  60. Player player1 = {true, {}, true, false, false, 0, 0}; // Human player
  61. Player player2 = {false, {}, false, false, true, 0, 0}; // AI/remote player
  62. std::vector<Ball> balls;
  63. HWND hwnd;
  64. bool gameOver = false;
  65. Player* currentPlayer = &player1;
  66. std::string playerName;
  67. std::vector<Ball> replayFrames;  // Store frames for replay
  68.  
  69. // Cue variables for control
  70. float cueAngle = 0.0f; // Angle of the shot in radians
  71. float shotPower = 0.0f; // Power of the shot
  72. float cueSpinX = 0.0f; // Horizontal spin (English)
  73. float cueSpinY = 0.0f; // Vertical spin (English)
  74. POINT mousePos; // Mouse position for aiming and power control
  75.  
  76. // Customization options
  77. COLORREF tableColor = RGB(34, 139, 34);  // Default green table
  78. COLORREF cueColor = RGB(139, 69, 19);  // Default brown cue
  79. COLORREF stripeBallColor = RGB(255, 255, 0);  // Default yellow stripe
  80. COLORREF solidBallColor = RGB(255, 0, 0);  // Default red solid
  81.  
  82. // UI Elements
  83. RECT powerMeterRect = {750, 50, 780, 450}; // Power meter on the right side
  84. RECT spinIndicatorRect = {60, 480, 140, 560}; // Spin indicator near the bottom
  85. int powerMeterLevel = 0; // Indicates shot power level
  86. int gameMode = GAME_MODE_STANDARD;  // Default game mode
  87. int timer = 120;  // 2-minute timer for timed mode
  88. bool replayMode = false;  // Track if replay mode is active
  89. //std::vector<std::vector<Ball>> replayFrames;  // Store frames for replay
  90.  
  91. // Utility functions
  92. bool IsColliding(Ball& b1, Ball& b2);
  93. void ResolveCollision(Ball& b1, Ball& b2);
  94. bool IsPocketed(Ball& ball);
  95. void HandleFouls(Player& player);
  96. void ApplySpin(Ball& ball);
  97. void AdjustShotPower(POINT& mousePos);
  98. void DrawPowerMeter(HDC hdc);
  99. void DrawSpinIndicator(HDC hdc);
  100. void SwitchTurns();
  101. void AITakeShot();  // AI player logic
  102. void PredictShot(Ball& ball, float& shotScore); // AI shot prediction logic
  103. void CheckGameOver();
  104. void UpdateScores(HDC hdc);
  105. void StartTimedMode();
  106. //void InitNetworkLobby();  // Initialize lobby-based multiplayer system
  107. //void InitNetwork(bool isHost);  // Initialize internet multiplayer network
  108. //void SendNetworkData(const std::string& data); // Send data over the network
  109. //void ReceiveNetworkData();  // Receive data from the network
  110. //void DisplayLobbyMenu();  // Lobby system UI
  111. void CustomizationMenu();  // Customization UI
  112. void SelectCustomization();  // Apply customization options
  113. void ReplayShot();  // Replay mode logic
  114. //void CheckFoul(Player& player, Ball& cueBall, std::vector<Ball>& balls); // Remove if Redundant !!!
  115. //void DisplayFoul(); // Remove if Redundant !!!
  116. //void HandlePlayerTurn(Player& player, Ball& cueBall); // Remove if Redundant !!!
  117.  
  118. // Function to draw the table and pockets with customization
  119. void DrawTable(HDC hdc) {
  120.     // Set table color
  121.     HBRUSH tableBrush = CreateSolidBrush(tableColor);  // Apply table customization
  122.     RECT tableRect = {50, 50, 750, 450}; // Set size of the table
  123.     FillRect(hdc, &tableRect, tableBrush);
  124.  
  125.     // Draw pocket holes (black)
  126.     HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0)); // Black pockets
  127.     SelectObject(hdc, blackBrush);
  128.     Ellipse(hdc, 55, 55, 55 + HOLE_RADIUS * 2, 55 + HOLE_RADIUS * 2); // Top-left
  129.     Ellipse(hdc, 745 - HOLE_RADIUS * 2, 55, 745, 55 + HOLE_RADIUS * 2); // Top-right
  130.     Ellipse(hdc, 55, 445 - HOLE_RADIUS * 2, 55 + HOLE_RADIUS * 2, 445); // Bottom-left
  131.     Ellipse(hdc, 745 - HOLE_RADIUS * 2, 445 - HOLE_RADIUS * 2, 745, 445); // Bottom-right
  132.     Ellipse(hdc, 395 - HOLE_RADIUS * 2, 55, 405 + HOLE_RADIUS * 2, 55 + HOLE_RADIUS * 2); // Top-middle
  133.     Ellipse(hdc, 395 - HOLE_RADIUS * 2, 445 - HOLE_RADIUS * 2, 405 + HOLE_RADIUS * 2, 445); // Bottom-middle
  134. }
  135.  
  136. // Function to draw a ball (solid or stripe) with customization
  137. void DrawBall(HDC hdc, Ball& ball) {
  138.     HBRUSH ballBrush = CreateSolidBrush(ball.isStripe ? stripeBallColor : solidBallColor);  // Custom ball colors
  139.     HPEN ballPen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0)); // Black border
  140.     SelectObject(hdc, ballBrush);
  141.     SelectObject(hdc, ballPen);
  142.  
  143.     // Draw the ball (if not pocketed)
  144.     if (!ball.isPocketed) {
  145.         // Draw shadow first for 3D effect
  146.         Ellipse(hdc, ball.x - ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius);
  147.         // Draw stripe if it's a striped ball
  148.         if (ball.isStripe) {
  149.             HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  150.             SelectObject(hdc, whiteBrush);
  151.             Rectangle(hdc, ball.x - ball.radius, ball.y - 3, ball.x + ball.radius, ball.y + 3);
  152.         }
  153.     }
  154.  
  155. /*     if (!ball.isPocketed) {
  156.         // Draw shadow first for 3D effect
  157.         Ellipse(hdc, ball.x - ball.radius + 3, ball.y - ball.radius + 3, ball.x + ball.radius + 3, ball.y + ball.radius + 3);
  158.  
  159.         // Draw the ball with shading
  160.         SelectObject(hdc, shadowBrush);
  161.         Ellipse(hdc, ball.x - ball.radius, ball.y - ball.radius, ball.x + ball.radius, ball.y + ball.radius);
  162.     } */
  163.  
  164.     // Cleanup
  165.     DeleteObject(ballBrush);
  166.     DeleteObject(ballPen);
  167. }
  168.  
  169. // Function to handle ball physics with spin and friction
  170. void HandleBallPhysics(Ball& ball, std::vector<Ball>& allBalls) {
  171.     // Update position based on velocity
  172.     ball.x += ball.vx + ball.spinX;
  173.     ball.y += ball.vy + ball.spinY;
  174.  
  175.     // Handle table boundary collision (bounce off walls)
  176.     if (ball.x <= 50 || ball.x >= 750) ball.vx *= -1; // Horizontal
  177.     if (ball.y <= 50 || ball.y >= 450) ball.vy *= -1; // Vertical
  178.  
  179.     // Handle ball-to-ball collisions
  180.     for (Ball& otherBall : allBalls) {
  181.         if (&ball != &otherBall && IsColliding(ball, otherBall)) {
  182.             ResolveCollision(ball, otherBall);
  183.         }
  184.     }
  185.  
  186.     // Apply friction and reduce spin over time
  187.     ball.vx *= 0.98;
  188.     ball.vy *= 0.98;
  189.     ball.spinX *= 0.97;
  190.     ball.spinY *= 0.97;
  191. }
  192.  
  193. // Apply spin to a ball (English)
  194. void ApplySpin(Ball& ball) {
  195.     ball.spinX += cueSpinX * 0.1f; // Horizontal spin effect
  196.     ball.spinY += cueSpinY * 0.1f; // Vertical spin effect
  197. }
  198.  
  199. // Check if two balls are colliding
  200. bool IsColliding(Ball& b1, Ball& b2) {
  201.     float dx = b1.x - b2.x;
  202.     float dy = b1.y - b2.y;
  203.     float distance = sqrt(dx * dx + dy * dy);
  204.     return distance < (b1.radius + b2.radius);
  205. }
  206.  
  207. // Resolve collision between two balls
  208. void ResolveCollision(Ball& b1, Ball& b2) {
  209.     float nx = b2.x - b1.x;
  210.     float ny = b2.y - b1.y;
  211.     float distance = sqrt(nx * nx + ny * ny);
  212.     nx /= distance;
  213.     ny /= distance;
  214.  
  215.     float kx = (b1.vx - b2.vx) * nx;
  216.     float ky = (b1.vy - b2.vy) * ny;
  217.     float p = 2.0 * (kx * nx + ky * ny) / (b1.mass + b2.mass);
  218.  
  219.     b1.vx -= p * b2.mass * nx;
  220.     b1.vy -= p * b2.mass * ny;
  221.     b2.vx += p * b1.mass * nx;
  222.     b2.vy += p * b1.mass * ny;
  223. }
  224.  
  225. // Adjust shot power based on mouse position
  226. void AdjustShotPower(POINT& mousePos) {
  227.     float distX = mousePos.x - cueBall.x;
  228.     float distY = mousePos.y - cueBall.y;
  229.     shotPower = sqrt(distX * distX + distY * distY) / 10.0f; // Adjust this value for power sensitivity
  230.     shotPower = min(shotPower, MAX_SHOT_POWER); // Cap the shot power
  231.     powerMeterLevel = (int)(shotPower / MAX_SHOT_POWER * 100); // Set power level for power meter
  232. }
  233.  
  234. // AI shot prediction logic (multi-step and tactical)
  235. void PredictShot(Ball& ball, float& shotScore) {
  236.     // Simulate shot, predict outcome, and score based on potential outcome
  237.     float distX = ball.x - cueBall.x;
  238.     float distY = ball.y - cueBall.y;
  239.     float dist = sqrt(distX * distX + distY * distY);
  240.     float angle = atan2(distY, distX);
  241.  
  242.     // Calculate shot score based on distance and angle
  243.     shotScore = -dist + cos(angle) * 50.0f;
  244.  
  245.     // Increase score for defensive plays or multi-step shot setups
  246.     if (distX < 100 && distY < 100) {
  247.         shotScore += 50.0f;  // Bonus for defensive or setup shots
  248.     }
  249. }
  250.  
  251. // Function to check for pocketing a ball
  252. bool IsPocketed(Ball& ball) {
  253.     return (ball.x < 55 + HOLE_RADIUS && ball.y < 55 + HOLE_RADIUS) || // Top-left pocket
  254.            (ball.x > 745 - HOLE_RADIUS && ball.y < 55 + HOLE_RADIUS) || // Top-right pocket
  255.            (ball.x < 55 + HOLE_RADIUS && ball.y > 445 - HOLE_RADIUS) || // Bottom-left pocket
  256.            (ball.x > 745 - HOLE_RADIUS && ball.y > 445 - HOLE_RADIUS) || // Bottom-right pocket
  257.            (ball.x > 395 - HOLE_RADIUS && ball.x < 405 + HOLE_RADIUS &&
  258.             (ball.y < 55 + HOLE_RADIUS || ball.y > 445 - HOLE_RADIUS)); // Middle pockets
  259. }
  260.  
  261. // Function to draw the power meter
  262. void DrawPowerMeter(HDC hdc) {
  263.     HBRUSH powerBrush = CreateSolidBrush(RGB(0, 255, 0)); // Green for power
  264.     RECT powerLevel = powerMeterRect;
  265.     powerLevel.top = powerMeterRect.bottom - powerMeterLevel * (powerMeterRect.bottom - powerMeterRect.top) / 100; // Adjust height
  266.  
  267.     FillRect(hdc, &powerLevel, powerBrush);
  268.     DeleteObject(powerBrush);
  269. }
  270.  
  271. // Function to draw the spin indicator
  272. void DrawSpinIndicator(HDC hdc) {
  273.     HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255)); // Cue ball color
  274.     Ellipse(hdc, spinIndicatorRect.left, spinIndicatorRect.top, spinIndicatorRect.right, spinIndicatorRect.bottom); // Draw cue ball
  275.  
  276.     // Draw spin dot (shows where spin is being applied)
  277.     HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0)); // Red dot for spin
  278.     int spinX = (int)(cueSpinX * 10); // Scale spin for visualization
  279.     int spinY = (int)(cueSpinY * 10);
  280.     int centerX = (spinIndicatorRect.left + spinIndicatorRect.right) / 2;
  281.     int centerY = (spinIndicatorRect.top + spinIndicatorRect.bottom) / 2;
  282.  
  283.     Ellipse(hdc, centerX + spinX - 5, centerY + spinY - 5, centerX + spinX + 5, centerY + spinY + 5); // Spin dot
  284.     DeleteObject(whiteBrush);
  285.     DeleteObject(redBrush);
  286. }
  287.  
  288. // Handle fouls (e.g., pocketing the cue ball or failing to hit a ball)
  289. void HandleFouls(Player& player) {
  290.     if (IsPocketed(cueBall)) {
  291.         player.fouled = true;
  292.         player.fouls++;
  293.     }
  294. }
  295.  
  296. /*
  297. // Multiplayer setup (TCP/IP for internet)
  298. void InitNetwork(bool isHost) {
  299.     WSADATA wsa;
  300.     WSAStartup(MAKEWORD(2, 2), &wsa);
  301.     sock = socket(AF_INET, SOCK_STREAM, 0);  // Use TCP for internet play
  302.  
  303.     memset(&serverAddr, 0, sizeof(serverAddr));
  304.     serverAddr.sin_family = AF_INET;
  305.     serverAddr.sin_port = htons(8888);
  306.  
  307.     if (isHost) {
  308.         serverAddr.sin_addr.s_addr = INADDR_ANY;
  309.         bind(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
  310.         listen(sock, 1);
  311.         int clientSize = sizeof(clientAddr);
  312.         sock = accept(sock, (SOCKADDR*)&clientAddr, &clientSize);
  313.         isMultiplayer = true;
  314.         isHost = true;
  315.     } else {
  316.         serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");  // Connect to host IP
  317.         connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr));
  318.         isMultiplayer = true;
  319.     }
  320. }
  321.  
  322. // Send data over the network
  323. void SendNetworkData(const std::string& data) {
  324.     send(sock, data.c_str(), data.size(), 0);
  325. }
  326.  
  327. // Receive data from the network
  328. void ReceiveNetworkData() {
  329.     int bytesReceived = recv(sock, recvBuffer, sizeof(recvBuffer), 0);
  330.     recvBuffer[bytesReceived] = '\0';
  331.    
  332.     // Parse and process opponent's move
  333.     std::string receivedData(recvBuffer);
  334.     // Process opponent's shot...
  335. }*/
  336.  
  337. // Check if the black ball has been pocketed and declare the winner
  338. void CheckGameOver() {
  339.     if (IsPocketed(blackBall)) {
  340.         gameOver = true;
  341.         Player* winner = (currentPlayer == &player1) ? &player2 : &player1;
  342.         std::string result = winner == &player1 ? "Player 1 Wins!" : "Player 2 Wins!";
  343.         //SendNetworkData(result);
  344.         MessageBox(hwnd, std::wstring(result.begin(), result.end()).c_str(), L"Game Over", MB_OK);
  345.         PostQuitMessage(0);
  346.     }
  347. }
  348.  
  349. // Update scores based on pocketed balls
  350. void UpdateScores(HDC hdc) {
  351.     wchar_t scoreText[100];
  352.     wsprintf(scoreText, L"Player 1 Score: %d | Player 2 Score: %d", player1.score, player2.score);
  353.     SetTextColor(hdc, RGB(0, 0, 0));
  354.     SetBkMode(hdc, TRANSPARENT);
  355.     TextOut(hdc, 300, 470, scoreText, lstrlen(scoreText));
  356.  
  357.     // Display fouls
  358.     wchar_t foulText[100];
  359.     wsprintf(foulText, L"Fouls: Player 1: %d | Player 2: %d", player1.fouls, player2.fouls);
  360.     TextOut(hdc, 300, 490, foulText, lstrlen(foulText));
  361. }
  362.  
  363.  
  364. // Replay mode: record frames
  365. void RecordReplayFrame() {
  366.     if (!replayMode) {
  367.         replayFrames = balls;  // Copy the current state of all balls
  368.     }
  369. }
  370.  
  371. // Replay mode: show replay frames
  372. void ShowReplayFrames(HDC hdc) {
  373.     if (!replayMode) return;
  374.  
  375.     for (size_t i = 0; i < replayFrames.size(); ++i) {
  376.         for (Ball& ball : replayFrames) {
  377.             DrawBall(hdc, ball);
  378.         }
  379.         Sleep(50);  // Slow down replay for visualization
  380.     }
  381.  
  382.     replayMode = false;  // Exit replay mode after showing
  383. }
  384.  
  385. void ReplayShot() {
  386.     if (replayFrames.empty()) {
  387.         MessageBox(hwnd, L"No shot to replay!", L"Replay", MB_OK | MB_ICONINFORMATION);
  388.         return;
  389.     }
  390.  
  391.     replayMode = true;
  392.     balls = replayFrames;  // Set the balls to the recorded state
  393.     InvalidateRect(hwnd, NULL, TRUE);
  394.     UpdateWindow(hwnd);
  395.     Sleep(1000);  // Show the initial state for 1 second
  396.  
  397.     // Simulate the shot
  398.     for (int i = 0; i < 100; i++) {  // Simulate 100 frames
  399.         for (Ball& ball : balls) {
  400.             HandleBallPhysics(ball, balls);
  401.         }
  402.         InvalidateRect(hwnd, NULL, TRUE);
  403.         UpdateWindow(hwnd);
  404.         Sleep(50);  // Adjust this value to control replay speed
  405.     }
  406.     replayMode = false;
  407. }
  408.  
  409. void CustomizationMenu() {
  410.     MessageBox(hwnd, L"Customization Menu\n\n1. Table Color\n2. Cue Color\n3. Stripe Ball Color\n4. Solid Ball Color\n\nPress the corresponding number key to customize.", L"Customization", MB_OK | MB_ICONINFORMATION);
  411. }
  412.  
  413. void SelectCustomization() {
  414.     if (GetAsyncKeyState('1') & 0x8000) {
  415.         tableColor = RGB(rand() % 256, rand() % 256, rand() % 256);
  416.     }
  417.     else if (GetAsyncKeyState('2') & 0x8000) {
  418.         cueColor = RGB(rand() % 256, rand() % 256, rand() % 256);
  419.     }
  420.     else if (GetAsyncKeyState('3') & 0x8000) {
  421.         stripeBallColor = RGB(rand() % 256, rand() % 256, rand() % 256);
  422.     }
  423.     else if (GetAsyncKeyState('4') & 0x8000) {
  424.         solidBallColor = RGB(rand() % 256, rand() % 256, rand() % 256);
  425.     }
  426.     InvalidateRect(hwnd, NULL, TRUE);
  427. }
  428.  
  429. /*
  430. // Apply customization options from menu
  431. void SelectCustomization() {
  432.     tableColor = RGB(0, 100, 100);  // Example: Teal table
  433.     cueColor = RGB(200, 200, 50);   // Example: Golden cue
  434.     stripeBallColor = RGB(0, 0, 255);   // Example: Blue stripe
  435.     solidBallColor = RGB(0, 255, 0);    // Example: Green solid
  436. }
  437. */
  438.  
  439. /*
  440. // Function to display the lobby menu
  441. void DisplayLobbyMenu() {
  442.     std::cout << "Enter your player name: ";
  443.     std::cin >> playerName;
  444.  
  445.     std::cout << "\nAvailable Games:\n";
  446.     for (const auto& game : availableGames) {
  447.         std::cout << "- " << game << std::endl;
  448.     }
  449.  
  450.     std::cout << "Press 'H' to Host a new game or 'J' to join one: ";
  451.     char choice;
  452.     std::cin >> choice;
  453.  
  454.     if (choice == 'H') {
  455.         InitNetwork(true);  // Host a new game
  456.     } else if (choice == 'J') {
  457.         InitNetwork(false);  // Join an existing game
  458.     }
  459. }
  460.  
  461. // Lobby-based network initialization (TCP for hosting/joining games)
  462. void InitNetworkLobby() {
  463.     WSADATA wsa;
  464.     WSAStartup(MAKEWORD(2, 2), &wsa);
  465.     sock = socket(AF_INET, SOCK_STREAM, 0);
  466.  
  467.     memset(&serverAddr, 0, sizeof(serverAddr));
  468.     serverAddr.sin_family = AF_INET;
  469.     serverAddr.sin_port = htons(8888);
  470.     serverAddr.sin_addr.s_addr = INADDR_ANY;
  471.  
  472.     if (bind(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
  473.         MessageBox(hwnd, "Failed to create lobby", "Error", MB_OK);
  474.         return;
  475.     }
  476.  
  477.     listen(sock, 10);  // Allow up to 10 players to join
  478.  
  479.     while (inLobby) {
  480.         int clientSize = sizeof(clientAddr);
  481.         SOCKET clientSock = accept(sock, (SOCKADDR*)&clientAddr, &clientSize);
  482.         if (clientSock != INVALID_SOCKET) {
  483.             playerID++;
  484.             lobby[playerID] = clientSock;
  485.             std::thread([](SOCKET s, int id) {
  486.                 char buffer[512];
  487.                 int received = recv(s, buffer, sizeof(buffer), 0);
  488.                 buffer[received] = '\0';
  489.  
  490.                 lobby[id] = s;
  491.  
  492.             }, clientSock, playerID).detach();
  493.         }
  494.     }
  495. }
  496. */
  497.  
  498. // Function to start the timed mode game
  499. void StartTimedMode() {
  500.     gameMode = GAME_MODE_TIMED;
  501.     timer = 120; // 2-minute timer
  502.  
  503.  
  504.     SetTimer(hwnd, 1, 1000, NULL);  // Start a 1-second timer
  505. }
  506.  
  507. // Timer event handler
  508. void HandleTimerEvent() {
  509.     if (gameMode == GAME_MODE_TIMED) {
  510.         if (timer > 0) {
  511.             timer--;
  512.         } else {
  513.             // Time up, game over
  514.             MessageBox(hwnd, L"Time's up! Game Over!", L"Game Over", MB_OK);
  515.             gameOver = true;
  516.             PostQuitMessage(0);
  517.         }
  518.     }
  519. }
  520.  
  521. // Function to draw the cue stick and aiming aids
  522. void DrawCueStick(HDC hdc, Ball& cueBall, float angle, float power) {
  523.     // Cue stick
  524.     HPEN cuePen = CreatePen(PS_SOLID, 6, RGB(139, 69, 19)); // Brown cue stick
  525.     SelectObject(hdc, cuePen);
  526.  
  527.     // Draw the cue stick based on angle
  528.     MoveToEx(hdc, cueBall.x, cueBall.y, NULL);
  529.     LineTo(hdc, cueBall.x + power * cos(angle), cueBall.y + power * sin(angle)); // Stick
  530.  
  531.     // Aiming aid (dash line to ball trajectory)
  532.     HPEN dashPen = CreatePen(PS_DASH, 1, RGB(0, 0, 255)); // Blue aiming aid
  533.     SelectObject(hdc, dashPen);
  534.     LineTo(hdc, cueBall.x + 150 * cos(angle), cueBall.y + 150 * sin(angle)); // Aiming aid
  535.  
  536.     DeleteObject(cuePen);
  537.     DeleteObject(dashPen);
  538. }
  539.  
  540. // AI takes a shot with advanced prediction logic
  541. void AITakeShot() {
  542.     Ball* targetBall = nullptr;
  543.     float bestScore = -9999.0f;
  544.  
  545.     for (Ball& ball : balls) {
  546.         if (!ball.isPocketed && currentPlayer->isSolid == !ball.isStripe) {
  547.             float shotScore;
  548.             PredictShot(ball, shotScore);
  549.  
  550.             if (shotScore > bestScore) {
  551.                 bestScore = shotScore;
  552.                 targetBall = &ball;
  553.             }
  554.         }
  555.     }
  556.  
  557.     if (targetBall) {
  558.         cueAngle = atan2(targetBall->y - cueBall.y, targetBall->x - cueBall.x);
  559.         shotPower = (rand() % 10 + 10) / 10.0f;
  560.  
  561.         cueBall.vx = shotPower * cos(cueAngle);
  562.         cueBall.vy = shotPower * sin(cueAngle);
  563.  
  564.         ApplySpin(cueBall);
  565.         SwitchTurns();
  566.     }
  567. }
  568.  
  569. // Switch turns between players after each shot or foul
  570. void SwitchTurns() {
  571.     currentPlayer->turn = false;
  572.     currentPlayer = (currentPlayer == &player1) ? &player2 : &player1;
  573.     currentPlayer->turn = true;
  574.  
  575.     // Trigger AI or network action if it's AI's or remote player's turn
  576.     if (currentPlayer->isAI) {
  577.         AITakeShot();
  578.     } /*else if (isMultiplayer) {
  579.         ReceiveNetworkData();  // Get the opponent's move
  580.     }*/
  581. }
  582.  
  583. // Remove if Redundant !!!
  584. /* void HandleFouls(Player& player) {
  585.     if (IsPocketed(cueBall)) {
  586.         player.fouled = true;
  587.     }
  588. }
  589.  
  590. // Remove if Redundant !!!
  591. // Game logic (foul detection, player switching, pocket checking)
  592. void CheckFoul(Player& player, Ball& cueBall, std::vector<Ball>& balls) {
  593.     if (player.isSolid && IsPocketed(blackBall)) {
  594.         // 8-ball pocketed before all solids, foul
  595.         DisplayFoul();
  596.         player.canMoveCue = true;
  597.     } else if (!player.isSolid && IsPocketed(blackBall)) {
  598.         // 8-ball pocketed before all stripes, foul
  599.         DisplayFoul();
  600.         player.canMoveCue = true;
  601.     }
  602. }
  603.  
  604. // Remove if Redundant !!!
  605. // Display foul text
  606. void DisplayFoul() {
  607.     HDC hdc = GetDC(hwnd);
  608.     SetTextColor(hdc, RGB(255, 0, 0));
  609.     TextOut(hdc, 10, 10, "FOUL!", 5);
  610.     ReleaseDC(hwnd, hdc);
  611. }
  612.  
  613. // Remove if Redundant !!!
  614. // Function to handle player actions (spin, re-spotting, fouls)
  615. void HandlePlayerTurn(Player& player, Ball& cueBall) {
  616.     if (player.fouled) {
  617.         // Cue ball re-spotting
  618.         cueBall.x = 100;
  619.         cueBall.y = 250;
  620.         cueBall.vx = cueBall.vy = cueBall.spinX = cueBall.spinY = 0;
  621.         player.fouled = false;
  622.     }
  623. } */
  624.  
  625. // Main game loop
  626. void GameLoop(HDC hdc) {
  627.     // Clear screen
  628.     RECT clientRect;
  629.     GetClientRect(hwnd, &clientRect);
  630.     FillRect(hdc, &clientRect, (HBRUSH)(COLOR_WINDOW + 1));
  631.  
  632.     // Draw table and balls
  633.     DrawTable(hdc);
  634.  
  635.     if (replayMode) {
  636.         ShowReplayFrames(hdc);  // Show the replay if in replay mode
  637.         return;
  638.     }
  639.  
  640.     for (Ball& ball : balls) {
  641.         HandleBallPhysics(ball, balls);
  642.         DrawBall(hdc, ball);
  643.         if (IsPocketed(ball)) ball.isPocketed = true; // Pocket the ball
  644.     }
  645.  
  646.     // Draw the cue ball
  647.     DrawBall(hdc, cueBall);
  648.  
  649.     if (!gameOver) {
  650.         HandleFouls(*currentPlayer);
  651.         CheckGameOver();
  652.         if (gameMode == GAME_MODE_TIMED) {
  653.             wchar_t timerText[50];
  654.             wsprintf(timerText, L"Time Remaining: %d seconds", timer);
  655.             TextOut(hdc, 350, 20, timerText, lstrlen(timerText));
  656.         }
  657.     }
  658.  
  659.     DrawCueStick(hdc, cueBall, cueAngle, shotPower);
  660.     DrawPowerMeter(hdc);
  661.     DrawSpinIndicator(hdc);
  662.     UpdateScores(hdc);
  663. }
  664.  
  665. // Main game window procedure
  666. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  667.     PAINTSTRUCT ps;
  668.     HDC hdc;
  669.  
  670.     switch (msg) {
  671.         case WM_PAINT:
  672.             hdc = BeginPaint(hwnd, &ps);
  673.             GameLoop(hdc);
  674.             EndPaint(hwnd, &ps);
  675.             break;
  676.         case WM_MOUSEMOVE:
  677.             mousePos.x = LOWORD(lParam);
  678.             mousePos.y = HIWORD(lParam);
  679.             AdjustShotPower(mousePos);
  680.             cueAngle = atan2(mousePos.y - cueBall.y, mousePos.x - cueBall.x);
  681.             InvalidateRect(hwnd, NULL, FALSE);
  682.             break;
  683.         case WM_LBUTTONDOWN:
  684.             cueBall.vx = shotPower * cos(cueAngle);
  685.             cueBall.vy = shotPower * sin(cueAngle);
  686.             ApplySpin(cueBall);
  687.             /*if (isMultiplayer) {
  688.                 std::string data = "SHOT:" + std::to_string(cueBall.vx) + "," + std::to_string(cueBall.vy);
  689.                 SendNetworkData(data);
  690.             }*/
  691.             SwitchTurns();
  692.             InvalidateRect(hwnd, NULL, FALSE);
  693.             break;
  694.         case WM_KEYDOWN:
  695.             switch (wParam) {
  696.                 case VK_LEFT:
  697.                     cueSpinX -= 0.1f;
  698.                     break;
  699.                 case VK_RIGHT:
  700.                     cueSpinX += 0.1f;
  701.                     break;
  702.                 case VK_UP:
  703.                     cueSpinY -= 0.1f;
  704.                     break;
  705.                 case VK_DOWN:
  706.                     cueSpinY += 0.1f;
  707.                     break;
  708.                 case 'T':
  709.                     StartTimedMode();
  710.                     break;
  711.                 /*case 'M':
  712.                     InitNetwork(true);
  713.                     break;
  714.                 case 'C':
  715.                     InitNetwork(false);
  716.                     break;*/
  717.                 case 'R':
  718.                     replayMode = true;
  719.                     InvalidateRect(hwnd, NULL, FALSE);
  720.                     break;
  721.                 case 'P':
  722.                     CustomizationMenu();
  723.                     InvalidateRect(hwnd, NULL, FALSE);
  724.                     break;
  725.             }
  726.             InvalidateRect(hwnd, NULL, FALSE);
  727.             break;
  728.         case WM_DESTROY:
  729.             //closesocket(sock);
  730.             WSACleanup();
  731.             PostQuitMessage(0);
  732.             break;
  733.         default:
  734.             return DefWindowProc(hwnd, msg, wParam, lParam);
  735.     }
  736.     return 0;
  737. }
  738.  
  739. // WinMain
  740. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  741.     MSG msg;
  742.     WNDCLASS wc = {0};
  743.     wc.lpfnWndProc = WndProc;
  744.     wc.hInstance = hInstance;
  745.     wc.lpszClassName = L"BilliardsGame";
  746.     wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));     // Add this line
  747.  
  748.     RegisterClass(&wc);
  749.  
  750.     hwnd = CreateWindowEx(0, L"BilliardsGame", L"Enhanced 8-Ball Billiards", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
  751.     ShowWindow(hwnd, nCmdShow);
  752.  
  753.     // Initialize balls (8-ball game setup)
  754.     balls.push_back(cueBall);
  755.     balls.push_back(blackBall);
  756.  
  757.     // Add all solid and stripe balls
  758.     for (int i = 1; i <= 7; ++i) {
  759.         Ball solidBall = {150 + i * 30, 200, 0, 0, 0, 0, solidBallColor, false, false};
  760.         balls.push_back(solidBall);
  761.  
  762.         Ball stripeBall = {150 + i * 30, 300, 0, 0, 0, 0, stripeBallColor, false, true};
  763.         balls.push_back(stripeBall);
  764.     }
  765.  
  766.     // Seed the random number generator for AI shots
  767.     srand((unsigned)time(NULL));
  768.  
  769.     while (GetMessage(&msg, NULL, 0, 0)) {
  770.         TranslateMessage(&msg);
  771.         DispatchMessage(&msg);
  772.     }
  773.  
  774.     return msg.wParam;
  775. }
Tags: #untenable
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement