Advertisement
alien_fx_fiend

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

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