Advertisement
alien_fx_fiend

Asteroids Impact (Fix For Countdown Not Displaying "3")

Mar 18th, 2025
322
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 29.22 KB | Source Code | 0 0
  1. ==++ Here's the full code for (file 1/2) "GDIGameEngine.cpp"::: ++==
  2. ```GDIGameEngine.cpp
  3. #include <windows.h>
  4. #include <vector>
  5. #include <cmath>
  6. #include <ctime>
  7. #include <algorithm>  // Include this header for std::min and std::max
  8. #include <tchar.h>
  9. // Add these global variables
  10. #include <thread>
  11. #include <atomic>
  12. #include "resource.h"
  13.  
  14. #include <mmsystem.h>
  15. #pragma comment(lib, "winmm.lib")
  16.  
  17. #define WIN_WIDTH 800
  18. #define WIN_HEIGHT 600
  19. // Add this to your global variables
  20. #define NUM_STARS 100
  21. // Add with other global variables
  22. bool keyStates[256] = { false };  // Track key states
  23. bool godMode = false; // Track God Mode state
  24. bool paused = false; // Track paused state
  25. bool gameStarted = false;
  26. //int countdownTimer = 240; // 4 seconds total (3,2,1,Get Ready!)
  27. int countdownTimer = 241; // 4 seconds total (3,2,1,Get Ready!)
  28. int windowWidth;
  29. int windowHeight;
  30. MCIDEVICEID midiDeviceID = 0;
  31. std::atomic<bool> isMusicPlaying(false);
  32. std::thread musicThread;
  33. bool isShielded = true; //changetofalse
  34. int shieldTimer = 0;
  35. const int SHIELD_DURATION = 240; // 4 seconds at 60 FPS
  36.  
  37. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  38. void DrawSpacecraft(HDC hdc, POINT pts[], int x, int y, double angle);
  39. void DrawAsteroid(HDC hdc, POINT pts[], int x, int y, double angle);
  40. bool CheckCollision(POINT player[], POINT asteroid[], int px, int py, int ax, int ay);
  41. void MoveAsteroids();
  42. void ShootBullet();
  43. void DrawBullet(HDC hdc, int x, int y);
  44. bool CheckBulletCollision(int bx, int by);
  45. bool DoLinesIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
  46. int Direction(int x1, int y1, int x2, int y2, int x3, int y3);
  47. bool OnSegment(int x1, int y1, int x2, int y2, int x3, int y3);
  48. bool PointInPolygon(int px, int py, POINT polygon[], int ox, int oy);
  49. void GenerateAsteroids();
  50. void SpawnNewAsteroid();
  51. void UpdatePlayerMovement();
  52. void InitStars();
  53. void DrawStarfield(HDC hdc);
  54.  
  55. struct Asteroid {
  56.    int x, y;
  57.    double angle;
  58.    double speed;
  59.    POINT shape[8];
  60. };
  61.  
  62. struct Bullet {
  63.    int x, y;
  64.    double angle;
  65. };
  66.  
  67. struct Star {
  68.    int x, y;
  69.    int brightness; // 0-255 for varying star brightness
  70. };
  71. Star stars[NUM_STARS];
  72.  
  73. std::vector<Asteroid> asteroids;
  74. std::vector<Bullet> bullets;
  75. // Replace the existing player points definition
  76. // Define more points for a detailed spacecraft
  77. POINT player[15] = {
  78.    {0, -40},    // Nose
  79.    {15, -20},   // Right front
  80.    {20, -10},   // Right body
  81.    {25, 0},     // Right wing
  82.    {30, 20},    // Right thruster
  83.    {20, 25},    // Right back
  84.    {10, 30},    // Right exhaust
  85.    {0, 35},     // Center exhaust
  86.    {-10, 30},   // Left exhaust
  87.    {-20, 25},   // Left back
  88.    {-30, 20},   // Left thruster
  89.    {-25, 0},    // Left wing
  90.    {-20, -10},  // Left body
  91.    {-15, -20},  // Left front
  92.    {0, -40}     // Back to nose
  93. };
  94. int playerX = WIN_WIDTH / 2, playerY = WIN_HEIGHT / 2;
  95. double playerAngle = 0;
  96. int score = 0;
  97. int lives = 3;
  98.  
  99. void PlayMidiInBackground(HWND hwnd, const TCHAR* midiPath) {
  100.    while (isMusicPlaying) {
  101.        MCI_OPEN_PARMS mciOpen = { 0 };
  102.        mciOpen.lpstrDeviceType = TEXT("sequencer");
  103.        mciOpen.lpstrElementName = midiPath;
  104.  
  105.        if (mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT, (DWORD_PTR)&mciOpen) == 0) {
  106.            midiDeviceID = mciOpen.wDeviceID;
  107.  
  108.            MCI_PLAY_PARMS mciPlay = { 0 };
  109.            mciSendCommand(midiDeviceID, MCI_PLAY, 0, (DWORD_PTR)&mciPlay);
  110.  
  111.            // Wait for playback to complete
  112.            MCI_STATUS_PARMS mciStatus = { 0 };
  113.            mciStatus.dwItem = MCI_STATUS_MODE;
  114.  
  115.            do {
  116.                mciSendCommand(midiDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&mciStatus);
  117.                Sleep(100); // Reduce CPU usage
  118.            } while (mciStatus.dwReturn == MCI_MODE_PLAY && isMusicPlaying);
  119.  
  120.            mciSendCommand(midiDeviceID, MCI_CLOSE, 0, NULL);
  121.            midiDeviceID = 0;
  122.        }
  123.    }
  124. }
  125.  
  126. void PlayGameMusic(HWND hwnd) {
  127.    // Stop any existing playback
  128.    if (isMusicPlaying) {
  129.        isMusicPlaying = false;
  130.        if (musicThread.joinable()) {
  131.            musicThread.join();
  132.        }
  133.        if (midiDeviceID != 0) {
  134.            mciSendCommand(midiDeviceID, MCI_CLOSE, 0, NULL);
  135.            midiDeviceID = 0;
  136.        }
  137.    }
  138.  
  139.    // Get the path of the executable
  140.    TCHAR exePath[MAX_PATH];
  141.    GetModuleFileName(NULL, exePath, MAX_PATH);
  142.  
  143.    // Extract the directory path
  144.    TCHAR* lastBackslash = _tcsrchr(exePath, '\\');
  145.    if (lastBackslash != NULL) {
  146.        *(lastBackslash + 1) = '\0';
  147.    }
  148.  
  149.    // Construct the full path to the MIDI file
  150.    static TCHAR midiPath[MAX_PATH];
  151.    _tcscpy_s(midiPath, MAX_PATH, exePath);
  152.    _tcscat_s(midiPath, MAX_PATH, TEXT("GAME MUSIC.MID"));
  153.  
  154.    // Start the background playback
  155.    isMusicPlaying = true;
  156.    musicThread = std::thread(PlayMidiInBackground, hwnd, midiPath);
  157. }
  158.  
  159. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  160.    WNDCLASSEX wcex;
  161.    HWND hwnd;
  162.    MSG msg;
  163.  
  164.    wcex.cbSize = sizeof(WNDCLASSEX);
  165.    wcex.style = CS_HREDRAW | CS_VREDRAW;
  166.    wcex.lpfnWndProc = WndProc;
  167.    wcex.cbClsExtra = 0;
  168.    wcex.cbWndExtra = 0;
  169.    wcex.hInstance = hInstance;
  170.    wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  171.    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  172.    wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); // Replace NULL with this // Set background brush to NULL
  173.    wcex.lpszMenuName = NULL;
  174.    wcex.lpszClassName = TEXT("Asteroids");
  175.    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));
  176.    //wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  177.  
  178.    RegisterClassEx(&wcex);
  179.  
  180.    // Remove WS_MAXIMIZEBOX and WS_THICKFRAME from the window style
  181.    DWORD style = (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX) & ~WS_THICKFRAME;
  182.  
  183.    // Get the screen dimensions
  184.    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  185.    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  186.  
  187.    // Calculate the window position to center it
  188.    int windowWidth = WIN_WIDTH + 16;
  189.    int windowHeight = WIN_HEIGHT + 39;
  190.    int posX = (screenWidth - windowWidth) / 2;
  191.    int posY = (screenHeight - windowHeight) / 2;
  192.  
  193.    hwnd = CreateWindow(TEXT("Asteroids"), TEXT("Asteroids ArrowKeys=Controls Space=Shoot F1=GodMode P=Pause F2=About Escape=Quit"), style,
  194.        posX, posY, windowWidth + 16, windowHeight + 39, NULL, NULL, hInstance, NULL);
  195.  
  196.    //show window + update window here
  197.    
  198.    srand(static_cast<unsigned int>(time(0)));
  199.  
  200.    GenerateAsteroids();
  201.  
  202.    // Add this line in WinMain before the main loop:
  203.    //initstars + playgamemusic here
  204.    InitStars();
  205.    ShowWindow(hwnd, nCmdShow);
  206.    UpdateWindow(hwnd);
  207.    Sleep(500); // Allow window to fully initialize before starting the countdown
  208.    PlayGameMusic(hwnd);
  209.  
  210.    // Main game loop
  211.    while (true) {
  212.        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  213.            if (msg.message == WM_QUIT) break;
  214.            TranslateMessage(&msg);
  215.            DispatchMessage(&msg);
  216.        }
  217.        else {
  218.            if (!gameStarted) {                
  219.                InvalidateRect(hwnd, NULL, FALSE);
  220.                Sleep(16);
  221.                countdownTimer--;
  222.                if (countdownTimer <= 0) {
  223.                    gameStarted = true;                    
  224.                }
  225.                continue;
  226.            }
  227.            if (!paused) { //re-enable-code-below-for-nonshielding
  228.                /*if (isShielded) {
  229.                    shieldTimer--;
  230.                    if (shieldTimer <= 0) {
  231.                        isShielded = false;
  232.                    }
  233.                }*/
  234.  
  235.                UpdatePlayerMovement();
  236.                for (auto& ast : asteroids) {
  237.                    if (!godMode && !isShielded && CheckCollision(player, ast.shape, playerX, playerY, ast.x, ast.y)) {
  238.                        lives--;
  239.                        if (lives <= 0) {
  240.                            if (MessageBox(hwnd, TEXT("Game Over! Play again?"), TEXT("Asteroids"), MB_YESNO) == IDYES) {
  241.                                // Reset game
  242.                                lives = 3;
  243.                                score = 0;
  244.                                playerX = WIN_WIDTH / 2;
  245.                                playerY = WIN_HEIGHT / 2;
  246.                                playerAngle = 0;
  247.                                asteroids.clear();
  248.                                bullets.clear();
  249.                                GenerateAsteroids();
  250.                            }
  251.                            else {
  252.                                PostQuitMessage(0);
  253.                            }
  254.                            continue;
  255.                        }
  256.                        playerX = WIN_WIDTH / 2;
  257.                        playerY = WIN_HEIGHT / 2;
  258.                        playerAngle = 0;
  259.                        isShielded = true;
  260.                        shieldTimer = SHIELD_DURATION;
  261.                        memset(keyStates, 0, sizeof(keyStates));
  262.                    }
  263.                }
  264.  
  265.                if (rand() % 100 < 2) {
  266.                    SpawnNewAsteroid();
  267.                }
  268.  
  269.                MoveAsteroids();
  270.  
  271.                for (auto it = bullets.begin(); it != bullets.end();) {
  272.                    it->x += 10 * cos(it->angle * 3.14159 / 180);
  273.                    it->y += 10 * sin(it->angle * 3.14159 / 180);
  274.  
  275.                    if (CheckBulletCollision(it->x, it->y)) {
  276.                        //Beep(500, 50); // Beep sound when asteroid is destroyed
  277.                        it = bullets.erase(it);
  278.                    }
  279.                    else {
  280.                        ++it;
  281.                    }
  282.                }
  283.            }
  284.            InvalidateRect(hwnd, NULL, FALSE);
  285.            Sleep(16);
  286.        }
  287.    }
  288.  
  289.    return (int)msg.wParam;
  290. }
  291.  
  292.  
  293. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  294.    static HDC hdcMem;
  295.    static HBITMAP hbmMem;
  296.    static HBITMAP hbmOld;
  297.    static HBRUSH hbrBkGnd;
  298.    static RECT rect;
  299.    PAINTSTRUCT ps;
  300.    static TCHAR scoreText[50];
  301.  
  302.    switch (msg) {
  303.    case WM_CREATE:
  304.    {   // Add these braces
  305.        GetClientRect(hwnd, &rect);
  306.        HDC hdcWindow = GetDC(hwnd);
  307.        hdcMem = CreateCompatibleDC(hdcWindow);
  308.        hbmMem = CreateCompatibleBitmap(hdcWindow, rect.right, rect.bottom);
  309.        ReleaseDC(hwnd, hdcWindow);
  310.        hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
  311.        hbrBkGnd = CreateSolidBrush(RGB(0, 0, 0));
  312.    }    // Add these braces
  313.    break;  // Add break statement
  314.  
  315.    case WM_ERASEBKGND:
  316.        return 1;
  317.  
  318.  
  319.    case WM_PAINT: {
  320.        HDC hdc = BeginPaint(hwnd, &ps);
  321.        FillRect(hdcMem, &rect, hbrBkGnd);
  322.  
  323.        // Draw starfield first (before everything else)
  324.        DrawStarfield(hdcMem);
  325.  
  326.        if (!gameStarted) {
  327.            SetTextColor(hdcMem, RGB(255, 255, 255));
  328.            SetBkMode(hdcMem, TRANSPARENT);
  329.            HFONT hFont = CreateFont(72, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
  330.                ANSI_CHARSET, // Changed from DEFAULT_CHARSET to ANSI_CHARSET
  331.                OUT_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
  332.                CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_SWISS, TEXT("Arial"));
  333.            HFONT hOldFont = (HFONT)SelectObject(hdcMem, hFont);
  334.  
  335.            const TCHAR* countText;  // Changed to const TCHAR*
  336.            //int count = (countdownTimer / 60);
  337.            int count = ((countdownTimer + 1) / 60);
  338.  
  339.            // Use direct string assignments instead of wsprintf
  340.            if (count == 4) {
  341.                countText = TEXT("3");
  342.            }
  343.            else if (count == 3) {
  344.                countText = TEXT("2");
  345.            }
  346.            else if (count == 2) {
  347.                countText = TEXT("1");
  348.            }
  349.            else if (count == 1) {
  350.                countText = TEXT("Get Ready!");
  351.            }
  352.            else {
  353.                countText = TEXT("");  // Add default case
  354.            }
  355.  
  356.            RECT textRect;
  357.            GetClientRect(hwnd, &textRect);
  358.            DrawText(hdcMem, countText, -1, &textRect,
  359.                DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  360.  
  361.            SelectObject(hdcMem, hOldFont);
  362.            DeleteObject(hFont);
  363.        }
  364.        else {
  365.            // Your existing drawing code...
  366.            DrawSpacecraft(hdcMem, player, playerX, playerY, playerAngle);
  367.            for (auto& ast : asteroids) {
  368.                DrawAsteroid(hdcMem, ast.shape, ast.x, ast.y, ast.angle);
  369.            }
  370.            for (auto& bullet : bullets) {
  371.                DrawBullet(hdcMem, bullet.x, bullet.y);
  372.            }
  373.  
  374.            SetTextColor(hdcMem, RGB(255, 255, 255));
  375.            SetBkMode(hdcMem, TRANSPARENT);
  376.            wsprintf(scoreText, TEXT("Score: %d  Lives: %d"), score, lives);
  377.            TextOut(hdcMem, 10, 10, scoreText, lstrlen(scoreText));
  378.  
  379.            if (godMode) {
  380.                TextOut(hdcMem, WIN_WIDTH / 2 - 50, 10, TEXT("God Mode"), 8);
  381.            }
  382.            if (paused) {
  383.                TextOut(hdcMem, WIN_WIDTH / 2 - 50, WIN_HEIGHT / 2 - 10, TEXT("Game Paused"), 10);
  384.            }
  385.        }
  386.  
  387.        BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
  388.        EndPaint(hwnd, &ps);
  389.        break;
  390.    }
  391.  
  392.  
  393.  
  394.    case WM_KEYDOWN:
  395.        keyStates[wParam] = true;
  396.        if (wParam == VK_F1) {
  397.            godMode = !godMode; // Toggle God Mode
  398.        }
  399.        else if (wParam == 'P') {
  400.            paused = !paused; // Toggle Pause
  401.        }
  402.        if (wParam == VK_ESCAPE) {
  403.            PostQuitMessage(0);
  404.            return 0;
  405.        }
  406.        // Add this new code block
  407.        else if (wParam == VK_F2) {
  408.            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);
  409.        }
  410.        break;
  411.  
  412.    case WM_KEYUP:
  413.        keyStates[wParam] = false;
  414.        break;  
  415.  
  416.    case WM_DESTROY:
  417.        SelectObject(hdcMem, hbmOld);  // Restore the original bitmap in the memory DC
  418.        DeleteObject(hbmMem);          // Delete the off-screen bitmap
  419.        DeleteDC(hdcMem);              // Delete the memory DC
  420.        DeleteObject(hbrBkGnd);        // Delete the background brush
  421.        isMusicPlaying = false;
  422.        if (musicThread.joinable()) {
  423.            musicThread.join();
  424.        }
  425.        if (midiDeviceID != 0) {
  426.            mciSendCommand(midiDeviceID, MCI_CLOSE, 0, NULL);
  427.            midiDeviceID = 0;
  428.        }
  429.        PostQuitMessage(0);
  430.        break;
  431.  
  432.    default:
  433.        return DefWindowProc(hwnd, msg, wParam, lParam);
  434.    }
  435.    return 0;
  436. }
  437.  
  438. void DrawSpacecraft(HDC hdc, POINT pts[], int x, int y, double angle) {
  439.    POINT rotated[15];
  440.    for (int i = 0; i < 15; ++i) {
  441.        rotated[i].x = pts[i].x * cos(angle * 3.14159 / 180) -
  442.            pts[i].y * sin(angle * 3.14159 / 180);
  443.        rotated[i].y = pts[i].x * sin(angle * 3.14159 / 180) +
  444.            pts[i].y * cos(angle * 3.14159 / 180);
  445.        rotated[i].x += x;
  446.        rotated[i].y += y;
  447.    }
  448.  
  449.    // Draw shield effect if active
  450.    if (isShielded) {
  451.        // Create shield gradient effect
  452.        int shieldRadius = 60;
  453.        HPEN shieldPen;
  454.  
  455.        // Multiple shield layers with different colors and opacity
  456.        for (int i = 0; i < 3; i++) {
  457.            int alpha = (255 - i * 40) * ((sin(shieldTimer * 0.1) + 1) / 2);
  458.            COLORREF shieldColor;
  459.  
  460.            switch ((shieldTimer / 8 + i) % 3) {
  461.            case 0:
  462.                shieldColor = RGB(0, 255, 255); // Cyan
  463.                break;
  464.            case 1:
  465.                shieldColor = RGB(0, 191, 255); // Deep Sky Blue
  466.                break;
  467.            case 2:
  468.                shieldColor = RGB(30, 144, 255); // Dodger Blue
  469.                break;
  470.            }
  471.  
  472.            shieldPen = CreatePen(PS_SOLID, 2 - i, shieldColor);
  473.            HPEN oldPen = (HPEN)SelectObject(hdc, shieldPen);
  474.  
  475.            // Draw shield circles
  476.            int currentRadius = shieldRadius - (i * 10);
  477.            Arc(hdc, x - currentRadius, y - currentRadius,
  478.                x + currentRadius, y + currentRadius,
  479.                x + currentRadius, y, x + currentRadius, y);
  480.  
  481.            // Draw energy field lines
  482.            for (int j = 0; j < 8; j++) {
  483.                double angleRad = (angle + j * 45) * 3.14159 / 180;
  484.                int startX = x + (currentRadius - 10) * cos(angleRad);
  485.                int startY = y + (currentRadius - 10) * sin(angleRad);
  486.                int endX = x + currentRadius * cos(angleRad);
  487.                int endY = y + currentRadius * sin(angleRad);
  488.                MoveToEx(hdc, startX, startY, NULL);
  489.                LineTo(hdc, endX, endY);
  490.            }
  491.  
  492.            // Draw energy particles
  493.            for (int j = 0; j < 12; j++) {
  494.                double particleAngle = (shieldTimer * 2 + j * 30) * 3.14159 / 180;
  495.                int particleX = x + currentRadius * cos(particleAngle);
  496.                int particleY = y + currentRadius * sin(particleAngle);
  497.                SetPixel(hdc, particleX, particleY, shieldColor);
  498.            }
  499.  
  500.            SelectObject(hdc, oldPen);
  501.            DeleteObject(shieldPen);
  502.        }
  503.  
  504.        // Add shield shimmer effect
  505.        HPEN shimmerPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
  506.        SelectObject(hdc, shimmerPen);
  507.        for (int i = 0; i < 16; i++) {
  508.            double shimmerAngle = (shieldTimer * 3 + i * 22.5) * 3.14159 / 180;
  509.            int shimmerX = x + shieldRadius * cos(shimmerAngle);
  510.            int shimmerY = y + shieldRadius * sin(shimmerAngle);
  511.            Ellipse(hdc, shimmerX - 2, shimmerY - 2, shimmerX + 2, shimmerY + 2);
  512.        }
  513.        DeleteObject(shimmerPen);
  514.    }
  515.  
  516.    // Draw main body
  517.    HPEN hotPinkPen = CreatePen(PS_SOLID, 1, RGB(255, 20, 147));
  518.    HBRUSH hotPinkBrush = CreateSolidBrush(RGB(255, 20, 147));
  519.    SelectObject(hdc, hotPinkPen);
  520.    SelectObject(hdc, hotPinkBrush);
  521.    Polygon(hdc, rotated, 15);
  522.  
  523.    // Draw headlights
  524.    HPEN whitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
  525.    SelectObject(hdc, whitePen);
  526.  
  527.    // Left headlight
  528.    int lightX1 = x + 15 * cos((angle - 100) * 3.14159 / 180);
  529.    int lightY1 = y + 15 * sin((angle - 100) * 3.14159 / 180);
  530.    Ellipse(hdc, lightX1 - 3, lightY1 - 3, lightX1 + 3, lightY1 + 3);
  531.  
  532.    // Right headlight
  533.    int lightX2 = x + 15 * cos((angle - 80) * 3.14159 / 180);
  534.    int lightY2 = y + 15 * sin((angle - 80) * 3.14159 / 180);
  535.    Ellipse(hdc, lightX2 - 3, lightY2 - 3, lightX2 + 3, lightY2 + 3);
  536.  
  537.    // Draw engine glow when moving forward
  538.    if (keyStates[VK_UP] || keyStates[VK_DOWN]) {
  539.        HPEN orangePen = CreatePen(PS_SOLID, 1, RGB(255, 165, 0));
  540.        HBRUSH orangeBrush = CreateSolidBrush(RGB(255, 165, 0));
  541.        SelectObject(hdc, orangePen);
  542.        SelectObject(hdc, orangeBrush);
  543.  
  544.        // Draw three exhaust flames
  545.        for (int i = -1; i <= 1; i++) {
  546.            int exhaustX = x - 30 * cos((angle - 90 + i * 15) * 3.14159 / 180);
  547.            int exhaustY = y - 30 * sin((angle - 90 + i * 15) * 3.14159 / 180);
  548.            Ellipse(hdc, exhaustX - 5, exhaustY - 5, exhaustX + 5, exhaustY + 5);
  549.        }
  550.  
  551.        DeleteObject(orangePen);
  552.        DeleteObject(orangeBrush);
  553.    }
  554.  
  555.    DeleteObject(hotPinkPen);
  556.    DeleteObject(hotPinkBrush);
  557.    DeleteObject(whitePen);
  558. }
  559.  
  560. void DrawAsteroid(HDC hdc, POINT pts[], int x, int y, double angle) {
  561.    POINT rotated[8];
  562.    for (int i = 0; i < 8; ++i) {
  563.        rotated[i].x = pts[i].x * cos(angle * 3.14159 / 180) - pts[i].y * sin(angle * 3.14159 / 180);
  564.        rotated[i].y = pts[i].x * sin(angle * 3.14159 / 180) + pts[i].y * cos(angle * 3.14159 / 180);
  565.        rotated[i].x += x;
  566.        rotated[i].y += y;
  567.    }
  568.  
  569.    // In DrawAsteroid function, before Polygon call
  570.    HPEN goldPen = CreatePen(PS_SOLID, 1, RGB(255, 215, 0));
  571.    HBRUSH goldBrush = CreateSolidBrush(RGB(255, 215, 0));
  572.    SelectObject(hdc, goldPen);
  573.    SelectObject(hdc, goldBrush);
  574.    Polygon(hdc, rotated, 8);
  575.    DeleteObject(goldPen);
  576.    DeleteObject(goldBrush);
  577. }
  578.  
  579. void UpdatePlayerMovement() {
  580.    if (keyStates[VK_LEFT]) {
  581.        playerAngle -= 5;
  582.    }
  583.    if (keyStates[VK_RIGHT]) {
  584.        playerAngle += 5;
  585.    }
  586.    if (keyStates[VK_UP]) {
  587.        playerX += 5 * cos((playerAngle - 90) * 3.14159 / 180);
  588.        playerY += 5 * sin((playerAngle - 90) * 3.14159 / 180);
  589.  
  590.        // Move stars in opposite direction of player movement for parallax effect
  591.        for (int i = 0; i < NUM_STARS; i++) {
  592.            stars[i].y += 1;
  593.            if (stars[i].y > WIN_HEIGHT) {
  594.                stars[i].y = 0;
  595.                stars[i].x = rand() % WIN_WIDTH;
  596.            }
  597.        }
  598.    }
  599.    // Add to UpdatePlayerMovement() function
  600.    if (keyStates[VK_DOWN]) {
  601.        playerX -= 5 * cos((playerAngle - 90) * 3.14159 / 180);
  602.        playerY -= 5 * sin((playerAngle - 90) * 3.14159 / 180);
  603.  
  604.        // Move stars in opposite direction of player movement for parallax effect
  605.        for (int i = 0; i < NUM_STARS; i++) {
  606.            stars[i].y += 1;
  607.            if (stars[i].y > WIN_HEIGHT) {
  608.                stars[i].y = 0;
  609.                stars[i].x = rand() % WIN_WIDTH;
  610.            }
  611.        }
  612.    }
  613.    // Add to UpdatePlayerMovement() function
  614.    static int shootCooldown = 0;
  615.    if (keyStates[VK_SPACE] && shootCooldown == 0) {
  616.        ShootBullet();
  617.        shootCooldown = 10; // Adjust this value to control firing rate
  618.    }
  619.    if (shootCooldown > 0) {
  620.        shootCooldown--;
  621.    }
  622.  
  623.    // Wrap around screen
  624.    if (playerX < 0) playerX = WIN_WIDTH;
  625.    if (playerX > WIN_WIDTH) playerX = 0;
  626.    if (playerY < 0) playerY = WIN_HEIGHT;
  627.    if (playerY > WIN_HEIGHT) playerY = 0;
  628. }
  629.  
  630. bool CheckCollision(POINT player[], POINT asteroid[], int px, int py, int ax, int ay) {
  631.    for (int i = 0; i < 3; ++i) {
  632.        int px1 = player[i].x + px;
  633.        int py1 = player[i].y + py;
  634.        int px2 = player[(i + 1) % 3].x + px;
  635.        int py2 = player[(i + 1) % 3].y + py;
  636.  
  637.        for (int j = 0; j < 8; ++j) {
  638.            int ax1 = asteroid[j].x + ax;
  639.            int ay1 = asteroid[j].y + ay;
  640.            int ax2 = asteroid[(j + 1) % 8].x + ax;
  641.            int ay2 = asteroid[(j + 1) % 8].y + ay;
  642.  
  643.            // Check if the line segments intersect
  644.            if (DoLinesIntersect(px1, py1, px2, py2, ax1, ay1, ax2, ay2)) {
  645.                return true;
  646.            }
  647.        }
  648.    }
  649.    return false;
  650. }
  651.  
  652. bool DoLinesIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
  653.    // Calculate the direction of the lines
  654.    int d1 = Direction(x3, y3, x4, y4, x1, y1);
  655.    int d2 = Direction(x3, y3, x4, y4, x2, y2);
  656.    int d3 = Direction(x1, y1, x2, y2, x3, y3);
  657.    int d4 = Direction(x1, y1, x2, y2, x4, y4);
  658.  
  659.    // Check if the lines intersect
  660.    if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
  661.        return true;
  662.    }
  663.  
  664.    // Check for collinear points
  665.    if (d1 == 0 && OnSegment(x3, y3, x4, y4, x1, y1)) return true;
  666.    if (d2 == 0 && OnSegment(x3, y3, x4, y4, x2, y2)) return true;
  667.    if (d3 == 0 && OnSegment(x1, y1, x2, y2, x3, y3)) return true;
  668.    if (d4 == 0 && OnSegment(x1, y1, x2, y2, x4, y4)) return true;
  669.  
  670.    return false;
  671. }
  672.  
  673. int Direction(int x1, int y1, int x2, int y2, int x3, int y3) {
  674.    return (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1);
  675. }
  676.  
  677. bool OnSegment(int x1, int y1, int x2, int y2, int x3, int y3) {
  678.    int minX = x1 < x2 ? x1 : x2;
  679.    int maxX = x1 > x2 ? x1 : x2;
  680.    int minY = y1 < y2 ? y1 : y2;
  681.    int maxY = y1 > y2 ? y1 : y2;
  682.  
  683.    if (minX <= x3 && x3 <= maxX && minY <= y3 && y3 <= maxY) {
  684.        return true;
  685.    }
  686.    return false;
  687. }
  688.  
  689. void MoveAsteroids() {
  690.    for (auto& ast : asteroids) {
  691.        ast.x += ast.speed * cos(ast.angle * 3.14159 / 180);
  692.        ast.y += ast.speed * sin(ast.angle * 3.14159 / 180);
  693.  
  694.        // Randomly adjust angle occasionally
  695.        if (rand() % 100 < 2) {
  696.            ast.angle += (rand() % 21 - 10); // Random turn between -10 and +10 degrees
  697.        }
  698.  
  699.        // Screen wrapping
  700.        if (ast.x < 0) ast.x = WIN_WIDTH;
  701.        if (ast.x > WIN_WIDTH) ast.x = 0;
  702.        if (ast.y < 0) ast.y = WIN_HEIGHT;
  703.        if (ast.y > WIN_HEIGHT) ast.y = 0;
  704.    }
  705. }
  706.  
  707. void ShootBullet() {
  708.    Bullet bullet;
  709.    // Calculate the tip of the triangle (point[0] is the top vertex)
  710.    bullet.x = playerX + player[0].x * cos(playerAngle * 3.14159 / 180)
  711.        - player[0].y * sin(playerAngle * 3.14159 / 180);
  712.    bullet.y = playerY + player[0].x * sin(playerAngle * 3.14159 / 180)
  713.        + player[0].y * cos(playerAngle * 3.14159 / 180);
  714.    // Adjust the bullet angle to match the ship's orientation
  715.     bullet.angle = playerAngle - 90;  // Subtract 90 degrees to align with the ship's nose
  716.     bullets.push_back(bullet);
  717. }
  718.  
  719. // Modified DrawBullet function for green bullets
  720. void DrawBullet(HDC hdc, int x, int y) {
  721.     HPEN greenPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0));    // Bright green
  722.     HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0));      // Bright green
  723.     SelectObject(hdc, greenPen);
  724.     SelectObject(hdc, greenBrush);
  725.     Ellipse(hdc, x - 4, y - 4, x + 4, y + 4);
  726.     DeleteObject(greenPen);
  727.     DeleteObject(greenBrush);
  728. }
  729.  
  730. bool CheckBulletCollision(int bx, int by) {
  731.     for (auto it = asteroids.begin(); it != asteroids.end();) {
  732.         if (PointInPolygon(bx, by, it->shape, it->x, it->y)) {
  733.             //Beep(500, 50); // Add this line
  734.             it = asteroids.erase(it);
  735.             score += 10;
  736.             return true;
  737.         }
  738.         else {
  739.             ++it;
  740.         }
  741.     }
  742.     return false;
  743. }
  744.  
  745. bool PointInPolygon(int px, int py, POINT polygon[], int ox, int oy) {
  746.     int i, j, nvert = 8;
  747.     bool c = false;
  748.  
  749.     for (i = 0, j = nvert - 1; i < nvert; j = i++) {
  750.         int polyX1 = polygon[i].x + ox;
  751.         int polyY1 = polygon[i].y + oy;
  752.         int polyX2 = polygon[j].x + ox;
  753.         int polyY2 = polygon[j].y + oy;
  754.  
  755.         if (((polyY1 > py) != (polyY2 > py)) &&
  756.             (px < (polyX2 - polyX1) * (py - polyY1) / (polyY2 - polyY1) + polyX1)) {
  757.             c = !c;
  758.         }
  759.     }
  760.     return c;
  761. }
  762.  
  763. void GenerateAsteroids() {
  764.     int initialAsteroids = 3; // Start with fewer asteroids
  765.     for (int i = 0; i < initialAsteroids; ++i) {
  766.         Asteroid ast;
  767.         ast.x = rand() % WIN_WIDTH;
  768.         ast.y = rand() % WIN_HEIGHT;
  769.         ast.angle = rand() % 360;
  770.  
  771.         for (int j = 0; j < 8; ++j) {
  772.             int radius = 30 + rand() % 20;
  773.             double angle = j * 45.0 * 3.14159 / 180.0;
  774.             ast.shape[j].x = radius * cos(angle);
  775.             ast.shape[j].y = radius * sin(angle);
  776.         }
  777.         asteroids.push_back(ast);
  778.     }
  779. }
  780.  
  781. void SpawnNewAsteroid() {
  782.     if (asteroids.size() >= 6) return;
  783.  
  784.     Asteroid ast;
  785.     // Spawn from edges
  786.     if (rand() % 2 == 0) {
  787.         ast.x = (rand() % 2) * WIN_WIDTH;
  788.         ast.y = rand() % WIN_HEIGHT;
  789.     }
  790.     else {
  791.         ast.x = rand() % WIN_WIDTH;
  792.         ast.y = (rand() % 2) * WIN_HEIGHT;
  793.     }
  794.  
  795.     // Random angle between 0 and 360
  796.     ast.angle = rand() % 360;
  797.  
  798.     // Random speed variation
  799.     ast.speed = 1.0 + (rand() % 30) / 10.0; // Speed between 1.0 and 4.0
  800.  
  801.     for (int j = 0; j < 8; ++j) {
  802.         int radius = 30 + rand() % 20;
  803.         double angle = j * 45.0 * 3.14159 / 180.0;
  804.         ast.shape[j].x = radius * cos(angle);
  805.         ast.shape[j].y = radius * sin(angle);
  806.     }
  807.     asteroids.push_back(ast);
  808. }
  809.  
  810. // Add this function to initialize the stars (call it once in WinMain before the main loop)
  811. void InitStars() {
  812.     for (int i = 0; i < NUM_STARS; i++) {
  813.         stars[i].x = rand() % WIN_WIDTH;
  814.         stars[i].y = rand() % WIN_HEIGHT;
  815.         stars[i].brightness = 100 + (rand() % 156); // Random brightness between 100-255
  816.     }
  817. }
  818.  
  819. // Add this function to draw the starfield
  820. void DrawStarfield(HDC hdc) {
  821.     for (int i = 0; i < NUM_STARS; i++) {
  822.         int brightness = stars[i].brightness;
  823.         HPEN starPen = CreatePen(PS_SOLID, 1, RGB(brightness, brightness, brightness));
  824.         HBRUSH starBrush = CreateSolidBrush(RGB(brightness, brightness, brightness));
  825.         SelectObject(hdc, starPen);
  826.         SelectObject(hdc, starBrush);
  827.  
  828.         // Draw each star as a small circle
  829.         Ellipse(hdc, stars[i].x - 1, stars[i].y - 1,
  830.             stars[i].x + 1, stars[i].y + 1);
  831.  
  832.         DeleteObject(starPen);
  833.         DeleteObject(starBrush);
  834.  
  835.         // Optional: make stars twinkle
  836.         if (rand() % 100 < 5) { // 5% chance each frame
  837.             stars[i].brightness = 100 + (rand() % 156);
  838.         }
  839.     }
  840. }
  841. ```
  842.  
  843. ==++ Here's the full code for (file 2/2) "resource.h"::: ++==
  844. ```resource.h
  845. //{{NO_DEPENDENCIES}}
  846. // Microsoft Visual C++ generated include file.
  847. // Used by AsteroidsImpact.rc
  848. //
  849. #define IDI_ICON1                       101
  850.  
  851. // Next default values for new objects
  852. //
  853. #ifdef APSTUDIO_INVOKED
  854. #ifndef APSTUDIO_READONLY_SYMBOLS
  855. #define _APS_NEXT_RESOURCE_VALUE        102
  856. #define _APS_NEXT_COMMAND_VALUE         40001
  857. #define _APS_NEXT_CONTROL_VALUE         1001
  858. #define _APS_NEXT_SYMED_VALUE           101
  859. #endif
  860. #endif
  861. ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement