Advertisement
alien_fx_fiend

Asteroids Game (Polished Version !!) *FINAL RELEASE*

Nov 1st, 2024 (edited)
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.40 KB | Source Code | 0 0
  1. #include <windows.h>
  2. #include <vector>
  3. #include <cmath>
  4. #include <ctime>
  5. #include <algorithm>  // Include this header for std::min and std::max
  6. #include "resource.h"
  7.  
  8. #define WIN_WIDTH 800
  9. #define WIN_HEIGHT 600
  10. // Add this to your global variables
  11. #define NUM_STARS 100
  12. // Add with other global variables
  13. bool keyStates[256] = { false };  // Track key states
  14. bool godMode = false; // Track God Mode state
  15. bool paused = false; // Track paused state
  16. bool gameStarted = false;
  17. int countdownTimer = 240; // 4 seconds total (3,2,1,Get Ready!)
  18. int windowWidth;
  19. int windowHeight;
  20.  
  21. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  22. void DrawSpacecraft(HDC hdc, POINT pts[], int x, int y, double angle);
  23. void DrawAsteroid(HDC hdc, POINT pts[], int x, int y, double angle);
  24. bool CheckCollision(POINT player[], POINT asteroid[], int px, int py, int ax, int ay);
  25. void MoveAsteroids();
  26. void ShootBullet();
  27. void DrawBullet(HDC hdc, int x, int y);
  28. bool CheckBulletCollision(int bx, int by);
  29. bool DoLinesIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
  30. int Direction(int x1, int y1, int x2, int y2, int x3, int y3);
  31. bool OnSegment(int x1, int y1, int x2, int y2, int x3, int y3);
  32. bool PointInPolygon(int px, int py, POINT polygon[], int ox, int oy);
  33. void GenerateAsteroids();
  34. void SpawnNewAsteroid();
  35. void UpdatePlayerMovement();
  36. void InitStars();
  37. void DrawStarfield(HDC hdc);
  38.  
  39. struct Asteroid {
  40.     int x, y;
  41.     double angle;
  42.     double speed;
  43.     POINT shape[8];
  44. };
  45.  
  46. struct Bullet {
  47.     int x, y;
  48.     double angle;
  49. };
  50.  
  51. struct Star {
  52.     int x, y;
  53.     int brightness; // 0-255 for varying star brightness
  54. };
  55. Star stars[NUM_STARS];
  56.  
  57. std::vector<Asteroid> asteroids;
  58. std::vector<Bullet> bullets;
  59. // Replace the existing player points definition
  60. // Define more points for a detailed spacecraft
  61. POINT player[15] = {
  62.     {0, -40},    // Nose
  63.     {15, -20},   // Right front
  64.     {20, -10},   // Right body
  65.     {25, 0},     // Right wing
  66.     {30, 20},    // Right thruster
  67.     {20, 25},    // Right back
  68.     {10, 30},    // Right exhaust
  69.     {0, 35},     // Center exhaust
  70.     {-10, 30},   // Left exhaust
  71.     {-20, 25},   // Left back
  72.     {-30, 20},   // Left thruster
  73.     {-25, 0},    // Left wing
  74.     {-20, -10},  // Left body
  75.     {-15, -20},  // Left front
  76.     {0, -40}     // Back to nose
  77. };
  78. int playerX = WIN_WIDTH / 2, playerY = WIN_HEIGHT / 2;
  79. double playerAngle = 0;
  80. int score = 0;
  81. int lives = 3;
  82.  
  83.  
  84. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  85.     WNDCLASSEX wcex;
  86.     HWND hwnd;
  87.     MSG msg;
  88.  
  89.     wcex.cbSize = sizeof(WNDCLASSEX);
  90.     wcex.style = CS_HREDRAW | CS_VREDRAW;
  91.     wcex.lpfnWndProc = WndProc;
  92.     wcex.cbClsExtra = 0;
  93.     wcex.cbWndExtra = 0;
  94.     wcex.hInstance = hInstance;
  95.     wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  96.     wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  97.     wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); // Replace NULL with this // Set background brush to NULL
  98.     wcex.lpszMenuName = NULL;
  99.     wcex.lpszClassName = TEXT("Asteroids");
  100.     wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));
  101.     //wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  102.  
  103.     RegisterClassEx(&wcex);
  104.  
  105.     // Remove WS_MAXIMIZEBOX and WS_THICKFRAME from the window style
  106.     DWORD style = (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_THICKFRAME;
  107.  
  108.     // Get the screen dimensions
  109.     int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  110.     int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  111.  
  112.     // Calculate the window position to center it
  113.     int windowWidth = WIN_WIDTH + 16;
  114.     int windowHeight = WIN_HEIGHT + 39;
  115.     int posX = (screenWidth - windowWidth) / 2;
  116.     int posY = (screenHeight - windowHeight) / 2;
  117.  
  118.     hwnd = CreateWindow(TEXT("Asteroids"), TEXT("Asteroids ArrowKeys=Controls Space=Shoot F1=GodMode P=Pause F2=About Escape=Quit"), style,
  119.         posX, posY, windowWidth + 16, windowHeight + 39, NULL, NULL, hInstance, NULL);
  120.  
  121.     ShowWindow(hwnd, nCmdShow);
  122.     UpdateWindow(hwnd);
  123.  
  124.     srand(static_cast<unsigned int>(time(0)));
  125.  
  126.     GenerateAsteroids();
  127.  
  128.     // Add this line in WinMain before the main loop:
  129.     InitStars();
  130.  
  131.     // Main game loop
  132.     while (true) {
  133.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  134.             if (msg.message == WM_QUIT) break;
  135.             TranslateMessage(&msg);
  136.             DispatchMessage(&msg);
  137.         }
  138.         else {
  139.             if (!gameStarted) {
  140.                 InvalidateRect(hwnd, NULL, FALSE);
  141.                 Sleep(16);
  142.                 countdownTimer--;
  143.                 if (countdownTimer <= 0) {
  144.                     gameStarted = true;
  145.                 }
  146.                 continue;
  147.             }
  148.             if (!paused) {
  149.                 UpdatePlayerMovement();
  150.                 for (auto& ast : asteroids) {
  151.                     if (!godMode && CheckCollision(player, ast.shape, playerX, playerY, ast.x, ast.y)) {
  152.                         lives--;
  153.                         if (lives <= 0) {
  154.                             if (MessageBox(hwnd, TEXT("Game Over! Play again?"), TEXT("Asteroids"), MB_YESNO) == IDYES) {
  155.                                 // Reset game
  156.                                 lives = 3;
  157.                                 score = 0;
  158.                                 playerX = WIN_WIDTH / 2;
  159.                                 playerY = WIN_HEIGHT / 2;
  160.                                 playerAngle = 0;
  161.                                 asteroids.clear();
  162.                                 bullets.clear();
  163.                                 GenerateAsteroids();
  164.                             }
  165.                             else {
  166.                                 PostQuitMessage(0);
  167.                             }
  168.                             continue;
  169.                         }
  170.                         playerX = WIN_WIDTH / 2;
  171.                         playerY = WIN_HEIGHT / 2;
  172.                         playerAngle = 0;
  173.                         memset(keyStates, 0, sizeof(keyStates));
  174.                     }
  175.                 }
  176.  
  177.                 if (rand() % 100 < 2) {
  178.                     SpawnNewAsteroid();
  179.                 }
  180.  
  181.                 MoveAsteroids();
  182.  
  183.                 for (auto it = bullets.begin(); it != bullets.end();) {
  184.                     it->x += 10 * cos(it->angle * 3.14159 / 180);
  185.                     it->y += 10 * sin(it->angle * 3.14159 / 180);
  186.  
  187.                     if (CheckBulletCollision(it->x, it->y)) {
  188.                         //Beep(500, 50); // Beep sound when asteroid is destroyed
  189.                         it = bullets.erase(it);
  190.                     }
  191.                     else {
  192.                         ++it;
  193.                     }
  194.                 }
  195.             }
  196.             InvalidateRect(hwnd, NULL, FALSE);
  197.             Sleep(16);
  198.         }
  199.     }
  200.  
  201.     return (int)msg.wParam;
  202. }
  203.  
  204.  
  205. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  206.     static HDC hdcMem;
  207.     static HBITMAP hbmMem;
  208.     static HBITMAP hbmOld;
  209.     static HBRUSH hbrBkGnd;
  210.     static RECT rect;
  211.     PAINTSTRUCT ps;
  212.     static TCHAR scoreText[50];
  213.  
  214.     switch (msg) {
  215.     case WM_CREATE:
  216.     {   // Add these braces
  217.         GetClientRect(hwnd, &rect);
  218.         HDC hdcWindow = GetDC(hwnd);
  219.         hdcMem = CreateCompatibleDC(hdcWindow);
  220.         hbmMem = CreateCompatibleBitmap(hdcWindow, rect.right, rect.bottom);
  221.         ReleaseDC(hwnd, hdcWindow);
  222.         hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
  223.         hbrBkGnd = CreateSolidBrush(RGB(0, 0, 0));
  224.     }    // Add these braces
  225.     break;  // Add break statement
  226.  
  227.  
  228.     case WM_PAINT: {
  229.         HDC hdc = BeginPaint(hwnd, &ps);
  230.         FillRect(hdcMem, &rect, hbrBkGnd);
  231.  
  232.         // Draw starfield first (before everything else)
  233.         DrawStarfield(hdcMem);
  234.  
  235.         if (!gameStarted) {
  236.             SetTextColor(hdcMem, RGB(255, 255, 255));
  237.             SetBkMode(hdcMem, TRANSPARENT);
  238.             HFONT hFont = CreateFont(72, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
  239.                 DEFAULT_CHARSET, OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
  240.                 CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_SWISS, TEXT("Arial"));
  241.             HFONT hOldFont = (HFONT)SelectObject(hdcMem, hFont);
  242.  
  243.             TCHAR countText[20];
  244.             int count = (countdownTimer / 60);
  245.  
  246.             if (count == 4) {
  247.                 wsprintf(countText, TEXT("3"));
  248.             }
  249.             else if (count == 3) {
  250.                 wsprintf(countText, TEXT("2"));
  251.             }
  252.             else if (count == 2) {
  253.                 wsprintf(countText, TEXT("1"));
  254.             }
  255.             else if (count == 1) {
  256.                 lstrcpy(countText, TEXT("Get Ready!"));
  257.             }
  258.  
  259.             RECT textRect;
  260.             GetClientRect(hwnd, &textRect);
  261.             DrawText(hdcMem, countText, -1, &textRect,
  262.                 DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  263.  
  264.             SelectObject(hdcMem, hOldFont);
  265.             DeleteObject(hFont);
  266.         }
  267.         else {
  268.             // Your existing drawing code...
  269.             DrawSpacecraft(hdcMem, player, playerX, playerY, playerAngle);
  270.             for (auto& ast : asteroids) {
  271.                 DrawAsteroid(hdcMem, ast.shape, ast.x, ast.y, ast.angle);
  272.             }
  273.             for (auto& bullet : bullets) {
  274.                 DrawBullet(hdcMem, bullet.x, bullet.y);
  275.             }
  276.  
  277.             SetTextColor(hdcMem, RGB(255, 255, 255));
  278.             SetBkMode(hdcMem, TRANSPARENT);
  279.             wsprintf(scoreText, TEXT("Score: %d  Lives: %d"), score, lives);
  280.             TextOut(hdcMem, 10, 10, scoreText, lstrlen(scoreText));
  281.  
  282.             if (godMode) {
  283.                 TextOut(hdcMem, WIN_WIDTH / 2 - 50, 10, TEXT("God Mode"), 8);
  284.             }
  285.             if (paused) {
  286.                 TextOut(hdcMem, WIN_WIDTH / 2 - 50, WIN_HEIGHT / 2 - 10, TEXT("Game Paused"), 10);
  287.             }
  288.         }
  289.  
  290.         BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
  291.         EndPaint(hwnd, &ps);
  292.         break;
  293.     }
  294.  
  295.  
  296.  
  297.     case WM_KEYDOWN:
  298.         keyStates[wParam] = true;
  299.         if (wParam == VK_F1) {
  300.             godMode = !godMode; // Toggle God Mode
  301.         }
  302.         else if (wParam == 'P') {
  303.             paused = !paused; // Toggle Pause
  304.         }
  305.         if (wParam == VK_ESCAPE) {
  306.             PostQuitMessage(0);
  307.             return 0;
  308.         }
  309.         // Add this new code block
  310.         else if (wParam == VK_F2) {
  311.             MessageBox(hwnd, TEXT("Asteroids v10.8 Basic GDI-Based C++ Win32 Game (663 lines of code) by Entisoft Software (c) Evans Thorpemorton"), TEXT("About"), MB_OK | MB_ICONINFORMATION);
  312.         }
  313.         break;
  314.  
  315.     case WM_KEYUP:
  316.         keyStates[wParam] = false;
  317.         break;        
  318.  
  319.     case WM_DESTROY:
  320.         SelectObject(hdcMem, hbmOld);  // Restore the original bitmap in the memory DC
  321.         DeleteObject(hbmMem);          // Delete the off-screen bitmap
  322.         DeleteDC(hdcMem);              // Delete the memory DC
  323.         DeleteObject(hbrBkGnd);        // Delete the background brush
  324.         PostQuitMessage(0);
  325.         break;
  326.  
  327.     default:
  328.         return DefWindowProc(hwnd, msg, wParam, lParam);
  329.     }
  330.     return 0;
  331. }
  332.  
  333. void DrawSpacecraft(HDC hdc, POINT pts[], int x, int y, double angle) {
  334.     POINT rotated[15];
  335.     for (int i = 0; i < 15; ++i) {
  336.         rotated[i].x = pts[i].x * cos(angle * 3.14159 / 180) -
  337.             pts[i].y * sin(angle * 3.14159 / 180);
  338.         rotated[i].y = pts[i].x * sin(angle * 3.14159 / 180) +
  339.             pts[i].y * cos(angle * 3.14159 / 180);
  340.         rotated[i].x += x;
  341.         rotated[i].y += y;
  342.     }
  343.  
  344.     // Draw main body
  345.     HPEN hotPinkPen = CreatePen(PS_SOLID, 1, RGB(255, 20, 147));
  346.     HBRUSH hotPinkBrush = CreateSolidBrush(RGB(255, 20, 147));
  347.     SelectObject(hdc, hotPinkPen);
  348.     SelectObject(hdc, hotPinkBrush);
  349.     Polygon(hdc, rotated, 15);
  350.  
  351.     // Draw headlights
  352.     HPEN whitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
  353.     SelectObject(hdc, whitePen);
  354.  
  355.     // Left headlight
  356.     int lightX1 = x + 15 * cos((angle - 100) * 3.14159 / 180);
  357.     int lightY1 = y + 15 * sin((angle - 100) * 3.14159 / 180);
  358.     Ellipse(hdc, lightX1 - 3, lightY1 - 3, lightX1 + 3, lightY1 + 3);
  359.  
  360.     // Right headlight
  361.     int lightX2 = x + 15 * cos((angle - 80) * 3.14159 / 180);
  362.     int lightY2 = y + 15 * sin((angle - 80) * 3.14159 / 180);
  363.     Ellipse(hdc, lightX2 - 3, lightY2 - 3, lightX2 + 3, lightY2 + 3);
  364.  
  365.     // Draw engine glow when moving forward
  366.     if (keyStates[VK_UP] || keyStates[VK_DOWN]) {
  367.         HPEN orangePen = CreatePen(PS_SOLID, 1, RGB(255, 165, 0));
  368.         HBRUSH orangeBrush = CreateSolidBrush(RGB(255, 165, 0));
  369.         SelectObject(hdc, orangePen);
  370.         SelectObject(hdc, orangeBrush);
  371.  
  372.         // Draw three exhaust flames
  373.         for (int i = -1; i <= 1; i++) {
  374.             int exhaustX = x - 30 * cos((angle - 90 + i * 15) * 3.14159 / 180);
  375.             int exhaustY = y - 30 * sin((angle - 90 + i * 15) * 3.14159 / 180);
  376.             Ellipse(hdc, exhaustX - 5, exhaustY - 5, exhaustX + 5, exhaustY + 5);
  377.         }
  378.  
  379.         DeleteObject(orangePen);
  380.         DeleteObject(orangeBrush);
  381.     }
  382.  
  383.     DeleteObject(hotPinkPen);
  384.     DeleteObject(hotPinkBrush);
  385.     DeleteObject(whitePen);
  386. }
  387.  
  388. void DrawAsteroid(HDC hdc, POINT pts[], int x, int y, double angle) {
  389.     POINT rotated[8];
  390.     for (int i = 0; i < 8; ++i) {
  391.         rotated[i].x = pts[i].x * cos(angle * 3.14159 / 180) - pts[i].y * sin(angle * 3.14159 / 180);
  392.         rotated[i].y = pts[i].x * sin(angle * 3.14159 / 180) + pts[i].y * cos(angle * 3.14159 / 180);
  393.         rotated[i].x += x;
  394.         rotated[i].y += y;
  395.     }
  396.  
  397.     // In DrawAsteroid function, before Polygon call
  398.     HPEN goldPen = CreatePen(PS_SOLID, 1, RGB(255, 215, 0));
  399.     HBRUSH goldBrush = CreateSolidBrush(RGB(255, 215, 0));
  400.     SelectObject(hdc, goldPen);
  401.     SelectObject(hdc, goldBrush);
  402.     Polygon(hdc, rotated, 8);
  403.     DeleteObject(goldPen);
  404.     DeleteObject(goldBrush);
  405. }
  406.  
  407. void UpdatePlayerMovement() {
  408.     if (keyStates[VK_LEFT]) {
  409.         playerAngle -= 5;
  410.     }
  411.     if (keyStates[VK_RIGHT]) {
  412.         playerAngle += 5;
  413.     }
  414.     if (keyStates[VK_UP]) {
  415.         playerX += 5 * cos((playerAngle - 90) * 3.14159 / 180);
  416.         playerY += 5 * sin((playerAngle - 90) * 3.14159 / 180);
  417.  
  418.         // Move stars in opposite direction of player movement for parallax effect
  419.         for (int i = 0; i < NUM_STARS; i++) {
  420.             stars[i].y += 1;
  421.             if (stars[i].y > WIN_HEIGHT) {
  422.                 stars[i].y = 0;
  423.                 stars[i].x = rand() % WIN_WIDTH;
  424.             }
  425.         }
  426.     }
  427.     // Add to UpdatePlayerMovement() function
  428.     if (keyStates[VK_DOWN]) {
  429.         playerX -= 5 * cos((playerAngle - 90) * 3.14159 / 180);
  430.         playerY -= 5 * sin((playerAngle - 90) * 3.14159 / 180);
  431.  
  432.         // Move stars in opposite direction of player movement for parallax effect
  433.         for (int i = 0; i < NUM_STARS; i++) {
  434.             stars[i].y += 1;
  435.             if (stars[i].y > WIN_HEIGHT) {
  436.                 stars[i].y = 0;
  437.                 stars[i].x = rand() % WIN_WIDTH;
  438.             }
  439.         }
  440.     }
  441.     // Add to UpdatePlayerMovement() function
  442.     static int shootCooldown = 0;
  443.     if (keyStates[VK_SPACE] && shootCooldown == 0) {
  444.         ShootBullet();
  445.         shootCooldown = 10; // Adjust this value to control firing rate
  446.     }
  447.     if (shootCooldown > 0) {
  448.         shootCooldown--;
  449.     }
  450.  
  451.     // Wrap around screen
  452.     if (playerX < 0) playerX = WIN_WIDTH;
  453.     if (playerX > WIN_WIDTH) playerX = 0;
  454.     if (playerY < 0) playerY = WIN_HEIGHT;
  455.     if (playerY > WIN_HEIGHT) playerY = 0;
  456. }
  457.  
  458. bool CheckCollision(POINT player[], POINT asteroid[], int px, int py, int ax, int ay) {
  459.     for (int i = 0; i < 3; ++i) {
  460.         int px1 = player[i].x + px;
  461.         int py1 = player[i].y + py;
  462.         int px2 = player[(i + 1) % 3].x + px;
  463.         int py2 = player[(i + 1) % 3].y + py;
  464.  
  465.         for (int j = 0; j < 8; ++j) {
  466.             int ax1 = asteroid[j].x + ax;
  467.             int ay1 = asteroid[j].y + ay;
  468.             int ax2 = asteroid[(j + 1) % 8].x + ax;
  469.             int ay2 = asteroid[(j + 1) % 8].y + ay;
  470.  
  471.             // Check if the line segments intersect
  472.             if (DoLinesIntersect(px1, py1, px2, py2, ax1, ay1, ax2, ay2)) {
  473.                 return true;
  474.             }
  475.         }
  476.     }
  477.     return false;
  478. }
  479.  
  480. bool DoLinesIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
  481.     // Calculate the direction of the lines
  482.     int d1 = Direction(x3, y3, x4, y4, x1, y1);
  483.     int d2 = Direction(x3, y3, x4, y4, x2, y2);
  484.     int d3 = Direction(x1, y1, x2, y2, x3, y3);
  485.     int d4 = Direction(x1, y1, x2, y2, x4, y4);
  486.  
  487.     // Check if the lines intersect
  488.     if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
  489.         return true;
  490.     }
  491.  
  492.     // Check for collinear points
  493.     if (d1 == 0 && OnSegment(x3, y3, x4, y4, x1, y1)) return true;
  494.     if (d2 == 0 && OnSegment(x3, y3, x4, y4, x2, y2)) return true;
  495.     if (d3 == 0 && OnSegment(x1, y1, x2, y2, x3, y3)) return true;
  496.     if (d4 == 0 && OnSegment(x1, y1, x2, y2, x4, y4)) return true;
  497.  
  498.     return false;
  499. }
  500.  
  501. int Direction(int x1, int y1, int x2, int y2, int x3, int y3) {
  502.     return (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1);
  503. }
  504.  
  505. bool OnSegment(int x1, int y1, int x2, int y2, int x3, int y3) {
  506.     int minX = x1 < x2 ? x1 : x2;
  507.     int maxX = x1 > x2 ? x1 : x2;
  508.     int minY = y1 < y2 ? y1 : y2;
  509.     int maxY = y1 > y2 ? y1 : y2;
  510.  
  511.     if (minX <= x3 && x3 <= maxX && minY <= y3 && y3 <= maxY) {
  512.         return true;
  513.     }
  514.     return false;
  515. }
  516.  
  517. void MoveAsteroids() {
  518.     for (auto& ast : asteroids) {
  519.         ast.x += ast.speed * cos(ast.angle * 3.14159 / 180);
  520.         ast.y += ast.speed * sin(ast.angle * 3.14159 / 180);
  521.  
  522.         // Randomly adjust angle occasionally
  523.         if (rand() % 100 < 2) {
  524.             ast.angle += (rand() % 21 - 10); // Random turn between -10 and +10 degrees
  525.         }
  526.  
  527.         // Screen wrapping
  528.         if (ast.x < 0) ast.x = WIN_WIDTH;
  529.         if (ast.x > WIN_WIDTH) ast.x = 0;
  530.         if (ast.y < 0) ast.y = WIN_HEIGHT;
  531.         if (ast.y > WIN_HEIGHT) ast.y = 0;
  532.     }
  533. }
  534.  
  535. void ShootBullet() {
  536.     Bullet bullet;
  537.     // Calculate the tip of the triangle (point[0] is the top vertex)
  538.     bullet.x = playerX + player[0].x * cos(playerAngle * 3.14159 / 180)
  539.         - player[0].y * sin(playerAngle * 3.14159 / 180);
  540.     bullet.y = playerY + player[0].x * sin(playerAngle * 3.14159 / 180)
  541.         + player[0].y * cos(playerAngle * 3.14159 / 180);
  542.     // Adjust the bullet angle to match the ship's orientation
  543.     bullet.angle = playerAngle - 90;  // Subtract 90 degrees to align with the ship's nose
  544.     bullets.push_back(bullet);
  545. }
  546.  
  547. // Modified DrawBullet function for green bullets
  548. void DrawBullet(HDC hdc, int x, int y) {
  549.     HPEN greenPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));    // Bright green
  550.     HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0));      // Bright green
  551.     SelectObject(hdc, greenPen);
  552.     SelectObject(hdc, greenBrush);
  553.     Ellipse(hdc, x - 4, y - 4, x + 4, y + 4);
  554.     DeleteObject(greenPen);
  555.     DeleteObject(greenBrush);
  556. }
  557.  
  558. bool CheckBulletCollision(int bx, int by) {
  559.     for (auto it = asteroids.begin(); it != asteroids.end();) {
  560.         if (PointInPolygon(bx, by, it->shape, it->x, it->y)) {
  561.             //Beep(500, 50); // Add this line
  562.             it = asteroids.erase(it);
  563.             score += 10;
  564.             return true;
  565.         }
  566.         else {
  567.             ++it;
  568.         }
  569.     }
  570.     return false;
  571. }
  572.  
  573. bool PointInPolygon(int px, int py, POINT polygon[], int ox, int oy) {
  574.     int i, j, nvert = 8;
  575.     bool c = false;
  576.  
  577.     for (i = 0, j = nvert - 1; i < nvert; j = i++) {
  578.         int polyX1 = polygon[i].x + ox;
  579.         int polyY1 = polygon[i].y + oy;
  580.         int polyX2 = polygon[j].x + ox;
  581.         int polyY2 = polygon[j].y + oy;
  582.  
  583.         if (((polyY1 > py) != (polyY2 > py)) &&
  584.             (px < (polyX2 - polyX1) * (py - polyY1) / (polyY2 - polyY1) + polyX1)) {
  585.             c = !c;
  586.         }
  587.     }
  588.     return c;
  589. }
  590.  
  591. void GenerateAsteroids() {
  592.     int initialAsteroids = 3; // Start with fewer asteroids
  593.     for (int i = 0; i < initialAsteroids; ++i) {
  594.         Asteroid ast;
  595.         ast.x = rand() % WIN_WIDTH;
  596.         ast.y = rand() % WIN_HEIGHT;
  597.         ast.angle = rand() % 360;
  598.  
  599.         for (int j = 0; j < 8; ++j) {
  600.             int radius = 30 + rand() % 20;
  601.             double angle = j * 45.0 * 3.14159 / 180.0;
  602.             ast.shape[j].x = radius * cos(angle);
  603.             ast.shape[j].y = radius * sin(angle);
  604.         }
  605.         asteroids.push_back(ast);
  606.     }
  607. }
  608.  
  609. void SpawnNewAsteroid() {
  610.     if (asteroids.size() >= 6) return;
  611.  
  612.     Asteroid ast;
  613.     // Spawn from edges
  614.     if (rand() % 2 == 0) {
  615.         ast.x = (rand() % 2) * WIN_WIDTH;
  616.         ast.y = rand() % WIN_HEIGHT;
  617.     }
  618.     else {
  619.         ast.x = rand() % WIN_WIDTH;
  620.         ast.y = (rand() % 2) * WIN_HEIGHT;
  621.     }
  622.  
  623.     // Random angle between 0 and 360
  624.     ast.angle = rand() % 360;
  625.  
  626.     // Random speed variation
  627.     ast.speed = 1.0 + (rand() % 30) / 10.0; // Speed between 1.0 and 4.0
  628.  
  629.     for (int j = 0; j < 8; ++j) {
  630.         int radius = 30 + rand() % 20;
  631.         double angle = j * 45.0 * 3.14159 / 180.0;
  632.         ast.shape[j].x = radius * cos(angle);
  633.         ast.shape[j].y = radius * sin(angle);
  634.     }
  635.     asteroids.push_back(ast);
  636. }
  637.  
  638. // Add this function to initialize the stars (call it once in WinMain before the main loop)
  639. void InitStars() {
  640.     for (int i = 0; i < NUM_STARS; i++) {
  641.         stars[i].x = rand() % WIN_WIDTH;
  642.         stars[i].y = rand() % WIN_HEIGHT;
  643.         stars[i].brightness = 100 + (rand() % 156); // Random brightness between 100-255
  644.     }
  645. }
  646.  
  647. // Add this function to draw the starfield
  648. void DrawStarfield(HDC hdc) {
  649.     for (int i = 0; i < NUM_STARS; i++) {
  650.         int brightness = stars[i].brightness;
  651.         HPEN starPen = CreatePen(PS_SOLID, 1, RGB(brightness, brightness, brightness));
  652.         HBRUSH starBrush = CreateSolidBrush(RGB(brightness, brightness, brightness));
  653.         SelectObject(hdc, starPen);
  654.         SelectObject(hdc, starBrush);
  655.  
  656.         // Draw each star as a small circle
  657.         Ellipse(hdc, stars[i].x - 1, stars[i].y - 1,
  658.             stars[i].x + 1, stars[i].y + 1);
  659.  
  660.         DeleteObject(starPen);
  661.         DeleteObject(starBrush);
  662.  
  663.         // Optional: make stars twinkle
  664.         if (rand() % 100 < 5) { // 5% chance each frame
  665.             stars[i].brightness = 100 + (rand() % 156);
  666.         }
  667.     }
  668. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement