Advertisement
alien_fx_fiend

New Code With Changes (Stick UI+ShotPower+AimingAids)

Aug 13th, 2024
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.81 KB | None | 0 0
  1. #include <windows.h>
  2. #include <vector>
  3. #include <cmath>
  4. #include <ctime>
  5.  
  6. #define ID_TIMER 1
  7. #define BALL_RADIUS 10
  8. #define TABLE_WIDTH 800
  9. #define TABLE_HEIGHT 400
  10. #define MAX_SHOT_POWER 500
  11.  
  12. HINSTANCE hInst;
  13. HWND hwnd;
  14. HDC hdcMem;
  15. HBITMAP hbmMem, hbmOld;
  16. RECT table = { 50, 50, 850, 450 };
  17. POINT cueStart, cueEnd;
  18. bool isDragging = false;
  19. float power = 0.0f;
  20. int currentPlayerColor = 0;
  21. bool foulOccurred = false;
  22. bool cueBallMoveAllowed = true;
  23. bool gameOver = false;
  24.  
  25. struct Ball {
  26.     float x, y;
  27.     float vx, vy;
  28.     COLORREF color;
  29.     bool isPocketed;
  30. };
  31.  
  32. std::vector<Ball> balls;
  33. Ball cueBall;
  34. Ball eightBall;
  35.  
  36. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  37. void InitBalls();
  38. void DrawTable(HDC);
  39. void DrawBalls(HDC);
  40. void DrawCue(HDC);
  41. void DrawPowerMeter(HDC);
  42. void UpdateBalls();
  43. void CheckCollisions();
  44. void CheckPockets();
  45. void ApplyEnglish(Ball&, float, float);
  46. bool CheckGameOver();
  47. void HandleFoul();
  48.  
  49. int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int nCmdShow) {
  50.     hInst = hInstance;
  51.     WNDCLASS wc = {};
  52.     wc.lpfnWndProc = WndProc;
  53.     wc.hInstance = hInstance;
  54.     wc.lpszClassName = L"8BallPool";
  55.     RegisterClass(&wc);
  56.  
  57.     hwnd = CreateWindowEx(0, L"8BallPool", L"8-Ball Pool", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 900, 600, nullptr, nullptr, hInstance, nullptr);
  58.     ShowWindow(hwnd, nCmdShow);
  59.  
  60.     MSG msg = {};
  61.     while (GetMessage(&msg, nullptr, 0, 0)) {
  62.         TranslateMessage(&msg);
  63.         DispatchMessage(&msg);
  64.     }
  65.     return (int)msg.wParam;
  66. }
  67.  
  68. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
  69.     switch (message) {
  70.     case WM_CREATE:
  71.         srand((unsigned int)time(NULL));
  72.         InitBalls();
  73.         SetTimer(hwnd, ID_TIMER, 16, NULL);
  74.         break;
  75.     case WM_PAINT: {
  76.         PAINTSTRUCT ps;
  77.         HDC hdc = BeginPaint(hwnd, &ps);
  78.         if (!hdcMem) {
  79.             hdcMem = CreateCompatibleDC(hdc);
  80.             hbmMem = CreateCompatibleBitmap(hdc, 900, 600);
  81.             hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
  82.         }
  83.         FillRect(hdcMem, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
  84.         DrawTable(hdcMem);
  85.         DrawBalls(hdcMem);
  86.         if (!gameOver && !foulOccurred && !isDragging) {
  87.             DrawCue(hdcMem);
  88.             DrawPowerMeter(hdcMem);
  89.         }
  90.         if (foulOccurred) {
  91.             SetTextColor(hdcMem, RGB(255, 0, 0));
  92.             TextOut(hdcMem, 10, 10, L"Foul!", 5);
  93.         }
  94.         BitBlt(hdc, 0, 0, 900, 600, hdcMem, 0, 0, SRCCOPY);
  95.         EndPaint(hwnd, &ps);
  96.         break;
  97.     }
  98.     case WM_LBUTTONDOWN:
  99.         if (gameOver) break;
  100.         cueStart.x = LOWORD(lParam);
  101.         cueStart.y = HIWORD(lParam);
  102.         if (foulOccurred && cueBallMoveAllowed) {
  103.             cueBall.x = (float)cueStart.x;
  104.             cueBall.y = (float)cueStart.y;
  105.             InvalidateRect(hwnd, NULL, FALSE);
  106.         } else {
  107.             isDragging = true;
  108.         }
  109.         break;
  110.     case WM_MOUSEMOVE:
  111.         if (isDragging) {
  112.             cueEnd.x = LOWORD(lParam);
  113.             cueEnd.y = HIWORD(lParam);
  114.             power = min(sqrt(pow(cueEnd.x - cueStart.x, 2) + pow(cueEnd.y - cueStart.y, 2)) / 100.0f, 1.0f);
  115.             InvalidateRect(hwnd, NULL, FALSE);
  116.         }
  117.         break;
  118.     case WM_LBUTTONUP:
  119.         if (isDragging) {
  120.             isDragging = false;
  121.             float dx = cueEnd.x - cueStart.x;
  122.             float dy = cueEnd.y - cueStart.y;
  123.             cueBall.vx = dx * power * 0.5f;
  124.             cueBall.vy = dy * power * 0.5f;
  125.             ApplyEnglish(cueBall, dx * power * 0.1f, dy * power * 0.1f);
  126.             foulOccurred = false;
  127.             cueBallMoveAllowed = false;
  128.             InvalidateRect(hwnd, NULL, FALSE);
  129.         }
  130.         break;
  131.     case WM_RBUTTONDOWN:
  132.         if (isDragging) {
  133.             power = min(sqrt(pow(cueEnd.x - cueStart.x, 2) + pow(cueEnd.y - cueStart.y, 2)) / 100.0f, 1.0f);
  134.             InvalidateRect(hwnd, NULL, FALSE);
  135.         }
  136.         break;
  137.     case WM_TIMER:
  138.         if (!gameOver) {
  139.             UpdateBalls();
  140.             CheckCollisions();
  141.             CheckPockets();
  142.             if (CheckGameOver()) {
  143.                 gameOver = true;
  144.             }
  145.             InvalidateRect(hwnd, NULL, FALSE);
  146.         }
  147.         break;
  148.     case WM_DESTROY:
  149.         KillTimer(hwnd, ID_TIMER);
  150.         SelectObject(hdcMem, hbmOld);
  151.         DeleteObject(hbmMem);
  152.         DeleteDC(hdcMem);
  153.         PostQuitMessage(0);
  154.         break;
  155.     default:
  156.         return DefWindowProc(hwnd, message, wParam, lParam);
  157.     }
  158.     return 0;
  159. }
  160.  
  161. void InitBalls() {
  162.     balls.clear();
  163.     cueBall = { 150.0f, 250.0f, 0.0f, 0.0f, RGB(255, 255, 255), false };
  164.     balls.push_back(cueBall);
  165.  
  166.     eightBall = { 600.0f, 250.0f, 0.0f, 0.0f, RGB(0, 0, 0), false };
  167.     balls.push_back(eightBall);
  168.  
  169.     for (int i = 0; i < 7; ++i) {
  170.         float angle = (float)i / 7.0f * 3.14159f * 2.0f;
  171.         balls.push_back({ 600.0f + cos(angle) * 30, 250.0f + sin(angle) * 30, 0.0f, 0.0f, RGB(255, 255, 0), false });
  172.         balls.push_back({ 600.0f + cos(angle) * 60, 250.0f + sin(angle) * 60, 0.0f, 0.0f, RGB(255, 0, 0), false });
  173.     }
  174. }
  175.  
  176. void DrawTable(HDC hdc) {
  177.     HBRUSH hBrush = CreateSolidBrush(RGB(0, 128, 0));
  178.     FillRect(hdc, &table, hBrush);
  179.     DeleteObject(hBrush);
  180.  
  181.     for (int i = 0; i < 2; ++i) {
  182.         for (int j = 0; j < 3; ++j) {
  183.             Ellipse(hdc, table.left + j * TABLE_WIDTH / 2 - BALL_RADIUS, table.top + i * TABLE_HEIGHT - BALL_RADIUS, table.left + j * TABLE_WIDTH / 2 + BALL_RADIUS, table.top + i * TABLE_HEIGHT + BALL_RADIUS);
  184.         }
  185.     }
  186.  
  187.     MoveToEx(hdc, (int)(table.left + 0.3f * TABLE_WIDTH), table.top, NULL);
  188.     LineTo(hdc, (int)(table.left + 0.3f * TABLE_WIDTH), table.bottom);
  189. }
  190.  
  191. void DrawBalls(HDC hdc) {
  192.     for (const auto& ball : balls) {
  193.         if (!ball.isPocketed) {
  194.             hBrush = CreateSolidBrush(ball.color);
  195.             SelectObject(hdc, hBrush);
  196.             Ellipse(hdc, (int)(ball.x - BALL_RADIUS), (int)(ball.y - BALL_RADIUS), (int)(ball.x + BALL_RADIUS), (int)(ball.y + BALL_RADIUS));
  197.             DeleteObject(hBrush);
  198.         }
  199.     }
  200. }
  201.  
  202. void DrawCue(HDC hdc) {
  203.     // Determine cue stick length and thickness
  204.     int cueLength = 200;
  205.     int cueThickness = 10;
  206.  
  207.     // Calculate the cue stick angle based on the position of the cue ball and the mouse position
  208.     float angle = atan2(cueEnd.y - cueBall.y, cueEnd.x - cueBall.x);
  209.  
  210.     // Calculate the cue stick endpoint positions based on the angle and the desired cue stick length
  211.     int cueX1 = (int)(cueBall.x + cos(angle) * BALL_RADIUS);
  212.     int cueY1 = (int)(cueBall.y + sin(angle) * BALL_RADIUS);
  213.     int cueX2 = (int)(cueX1 + cos(angle) * cueLength);
  214.     int cueY2 = (int)(cueY1 + sin(angle) * cueLength);
  215.  
  216.     // Draw the cue stick as a thick line with the specified thickness
  217.     HPEN hPen = CreatePen(PS_SOLID, cueThickness, RGB(139, 69, 19)); // Brown color for the cue stick
  218.     SelectObject(hdc, hPen);
  219.     MoveToEx(hdc, cueX1, cueY1, NULL);
  220.     LineTo(hdc, cueX2, cueY2);
  221.  
  222.     // Draw the tip of the cue stick with a different color (light blue)
  223.     HPEN hPenTip = CreatePen(PS_SOLID, cueThickness / 2, RGB(173, 216, 230)); // Light blue for the tip
  224.     SelectObject(hdc, hPenTip);
  225.     LineTo(hdc, cueX2 + (int)(cos(angle) * 10), cueY2 + (int)(sin(angle) * 10));
  226.  
  227.     DeleteObject(hPen);
  228.     DeleteObject(hPenTip);
  229. }
  230.  
  231. void DrawPowerMeter(HDC hdc) {
  232.     RECT powerRect = { 750, 500, 800, 500 - (int)(power * 400) };
  233.     HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));
  234.     FillRect(hdc, &powerRect, hBrush);
  235.     DeleteObject(hBrush);
  236. }
  237.  
  238. void UpdateBalls() {
  239.     for (auto& ball : balls) {
  240.         if (!ball.isPocketed) {
  241.             ball.x += ball.vx;
  242.             ball.y += ball.vy;
  243.  
  244.             ball.vx *= 0.99f;
  245.             ball.vy *= 0.99f;
  246.  
  247.             if (ball.x - BALL_RADIUS < table.left || ball.x + BALL_RADIUS > table.right) {
  248.                 ball.vx = -ball.vx;
  249.                 ball.x = min(max(ball.x, table.left + BALL_RADIUS), table.right - BALL_RADIUS);
  250.             }
  251.             if (ball.y - BALL_RADIUS < table.top || ball.y + BALL_RADIUS > table.bottom) {
  252.                 ball.vy = -ball.vy;
  253.                 ball.y = min(max(ball.y, table.top + BALL_RADIUS), table.bottom - BALL_RADIUS);
  254.             }
  255.         }
  256.     }
  257. }
  258.  
  259. void CheckCollisions() {
  260.     for (size_t i = 0; i < balls.size(); ++i) {
  261.         for (size_t j = i + 1; j < balls.size(); ++j) {
  262.             Ball& b1 = balls[i];
  263.             Ball& b2 = balls[j];
  264.  
  265.             float dx = b1.x - b2.x;
  266.             float dy = b1.y - b2.y;
  267.             float dist = sqrt(dx * dx + dy * dy);
  268.             if (dist < BALL_RADIUS * 2) {
  269.                 float nx = dx / dist;
  270.                 float ny = dy / dist;
  271.  
  272.                 float tx = -ny;
  273.                 float ty = nx;
  274.  
  275.                 float dpTan1 = b1.vx * tx + b1.vy * ty;
  276.                 float dpTan2 = b2.vx * tx + b2.vy * ty;
  277.  
  278.                 float dpNorm1 = b1.vx * nx + b1.vy * ny;
  279.                 float dpNorm2 = b2.vx * nx + b2.vy * ny;
  280.  
  281.                 float m1 = (dpNorm1 * (1 - 1) + 2 * dpNorm2) / 2;
  282.                 float m2 = (dpNorm2 * (1 - 1) + 2 * dpNorm1) / 2;
  283.  
  284.                 b1.vx = tx * dpTan1 + nx * m1;
  285.                 b1.vy = ty * dpTan1 + ny * m1;
  286.                 b2.vx = tx * dpTan2 + nx * m2;
  287.                 b2.vy = ty * dpTan2 + ny * m2;
  288.  
  289.                 float overlap = 0.5f * (BALL_RADIUS * 2 - dist);
  290.                 b1.x += nx * overlap;
  291.                 b1.y += ny * overlap;
  292.                 b2.x -= nx * overlap;
  293.                 b2.y -= ny * overlap;
  294.             }
  295.         }
  296.     }
  297. }
  298.  
  299. void CheckPockets() {
  300.     for (auto& ball : balls) {
  301.         for (int i = 0; i < 2; ++i) {
  302.             for (int j = 0; j < 3; ++j) {
  303.                 int px = table.left + j * TABLE_WIDTH / 2;
  304.                 int py = table.top + i * TABLE_HEIGHT;
  305.  
  306.                 float dist = sqrt(pow(ball.x - px, 2) + pow(ball.y - py, 2));
  307.                 if (dist < BALL_RADIUS * 1.5f) {
  308.                     ball.isPocketed = true;
  309.                     ball.vx = 0;
  310.                     ball.vy = 0;
  311.  
  312.                     if (&ball == &cueBall) {
  313.                         foulOccurred = true;
  314.                         cueBallMoveAllowed = true;
  315.                     } else if (&ball == &eightBall) {
  316.                         gameOver = true;
  317.                     }
  318.                 }
  319.             }
  320.         }
  321.     }
  322. }
  323.  
  324. void ApplyEnglish(Ball& ball, float ex, float ey) {
  325.     ball.vx += ex * 0.1f;
  326.     ball.vy += ey * 0.1f;
  327. }
  328.  
  329. bool CheckGameOver() {
  330.     for (const auto& ball : balls) {
  331.         if (!ball.isPocketed && &ball != &eightBall) {
  332.             return false;
  333.         }
  334.     }
  335.     return true;
  336. }
  337.  
  338. void HandleFoul() {
  339.     cueBall.vx = 0;
  340.     cueBall.vy = 0;
  341.     cueBallMoveAllowed = true;
  342. }
  343.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement