Advertisement
alien_fx_fiend

2D Car Racing (Off-Road Toggle + Collision Detection) *FINAL RELEASE*

Nov 12th, 2024
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 18.34 KB | Source Code | 0 0
  1. ==++ Here's the full source code for (file 1/1) "RaceCar.cpp"::++==
  2. #include <Windows.h>
  3. #include <ctime>
  4. #include <cstdlib>
  5. #include <math.h>
  6. #include <stdio.h>
  7. #include <string>
  8. #include "resource.h"  // Add this with your other includes
  9.  
  10. // Global Variables
  11. const int WIDTH = 1366;
  12. const int HEIGHT = 768;
  13. const int ROAD_WIDTH = 200;
  14. const int CAR_WIDTH = 50;
  15. const int CAR_HEIGHT = 100;
  16. const int TYRE_SIZE = 10;
  17. const int FPS = 60;
  18. const int TIMER = 4;
  19. const int TURN_RADIUS = 5;
  20. const double PI = 3.14159265358979323846;
  21.  
  22. int playerX = 100;
  23. int playerY = HEIGHT - CAR_HEIGHT - 50;
  24. int playerSpeedX = 0;
  25. int playerSpeedY = 0;
  26. int aiX = playerX + CAR_WIDTH + 20;
  27. int aiY = playerY;
  28. float aiAngle = -PI / 2;  // Add this line
  29. int aiSpeedX = 0;
  30. int aiSpeedY = 0;
  31. int speed = 5;
  32. int aiSpeed = 5;
  33. int timer = TIMER;
  34. int playerTyre1X = playerX + 10;
  35. int playerTyre1Y = playerY + CAR_HEIGHT - TYRE_SIZE;
  36. int playerTyre2X = playerX + CAR_WIDTH - TYRE_SIZE - 10;
  37. int playerTyre2Y = playerY + CAR_HEIGHT - TYRE_SIZE;
  38. int aiTyre1X = aiX + 10;
  39. int aiTyre1Y = aiY + CAR_HEIGHT - TYRE_SIZE;
  40. int aiTyre2X = aiX + CAR_WIDTH - TYRE_SIZE - 10;
  41. int aiTyre2Y = aiY + CAR_HEIGHT - TYRE_SIZE;
  42. float playerAngle = -PI / 2;  // Initialize to face North by default
  43. //float playerAngle = 0.0f;
  44.  
  45. bool gameStarted = false;
  46. bool gameOver = false;
  47. bool playerWon = false;
  48. bool godMode = false;
  49. //int timer = 30 * 10; // 30 seconds * 10 (timer resolution)
  50.  
  51. // Window Procedure
  52. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  53. {
  54.    switch (message)
  55.    {
  56.    case WM_CREATE:
  57.        SetTimer(hWnd, 1, 1000 / FPS, NULL);
  58.        break;
  59.    case WM_TIMER:
  60.        if (timer > 0)
  61.        {
  62.            timer--;
  63.            InvalidateRect(hWnd, NULL, FALSE);
  64.        }
  65.        else if (!gameStarted)
  66.        {
  67.            gameStarted = true;
  68.            srand((unsigned int)time(0));
  69.            aiSpeed = rand() % 5 + 3;
  70.  
  71.            // Set initial positions for both cars on the lower left road, facing up
  72.            playerX = ROAD_WIDTH / 2 - CAR_WIDTH / 2;
  73.            playerY = HEIGHT - CAR_HEIGHT - 20;
  74.            playerAngle = -PI / 2; // -90 degrees, pointing straight up
  75.  
  76.            aiX = ROAD_WIDTH / 2 - CAR_WIDTH / 2;
  77.            aiY = HEIGHT - CAR_HEIGHT - 100;
  78.            aiAngle = -PI / 2; // -90 degrees, pointing north
  79.        }
  80.        else if (!gameOver)
  81.        {
  82.            // Add God Mode toggle
  83.            if (GetAsyncKeyState('G') & 1) // Check if G key was just pressed
  84.            {
  85.                godMode = !godMode;
  86.            }
  87.  
  88.            // Store previous position for collision recovery
  89.            float prevPlayerX = playerX;
  90.            float prevPlayerY = playerY;
  91.            float prevPlayerAngle = playerAngle;
  92.  
  93.            // Player car controls
  94.            if (GetAsyncKeyState(VK_LEFT))
  95.            {
  96.                if (GetAsyncKeyState(VK_DOWN))
  97.                    playerAngle += 0.05f; // Reverse turning
  98.                else
  99.                    playerAngle -= 0.05f; // Forward turning
  100.            }
  101.            if (GetAsyncKeyState(VK_RIGHT))
  102.            {
  103.                if (GetAsyncKeyState(VK_DOWN))
  104.                    playerAngle -= 0.05f; // Reverse turning
  105.                else
  106.                    playerAngle += 0.05f; // Forward turning
  107.            }
  108.  
  109.            // Forward/Backward movement in the direction the car is facing
  110.            if (GetAsyncKeyState(VK_UP))
  111.            {
  112.                // Move forward in the direction of playerAngle
  113.                playerX += sin(playerAngle) * speed;
  114.                playerY -= cos(playerAngle) * speed;
  115.            }
  116.            if (GetAsyncKeyState(VK_DOWN))
  117.            {
  118.                // Move backward in the opposite direction of playerAngle
  119.                playerX -= sin(playerAngle) * speed;
  120.                playerY += cos(playerAngle) * speed;
  121.            }
  122.  
  123.            // Update player headlights position based on car angle
  124.            playerTyre1X = playerX + 10;
  125.            playerTyre1Y = playerY + 5;
  126.            playerTyre2X = playerX + CAR_WIDTH - TYRE_SIZE - 10;
  127.            playerTyre2Y = playerY + 5;
  128.  
  129.            // Road collision detection for player
  130.            bool onRoad = false;
  131.            // Vertical road
  132.            if (playerX >= 0 && playerX <= ROAD_WIDTH - CAR_WIDTH)
  133.                onRoad = true;
  134.            // Horizontal road at top (twice as tall)
  135.            if (playerY >= 0 && playerY <= (ROAD_WIDTH * 2) &&
  136.                playerX >= 0 && playerX <= WIDTH - CAR_WIDTH)
  137.                onRoad = true;
  138.  
  139.            if (!onRoad && !godMode) // Only restrict movement if god mode is off
  140.            {
  141.                // Return to previous position if off road
  142.                playerX = prevPlayerX;
  143.                playerY = prevPlayerY;
  144.                playerAngle = prevPlayerAngle;
  145.            }
  146.  
  147.            // AI car movement logic
  148.            if (aiY > ROAD_WIDTH * 2 && aiX < ROAD_WIDTH / 2)
  149.            {
  150.                // Move up on vertical road
  151.                aiSpeedX = 0;
  152.                aiSpeedY = -aiSpeed;
  153.                aiAngle = -PI / 2;  // facing up
  154.            }
  155.            else if (aiY <= ROAD_WIDTH * 2)
  156.            {
  157.                // Turn right on horizontal road
  158.                aiSpeedX = aiSpeed;
  159.                aiSpeedY = 0;
  160.                aiAngle = 0;  // facing right
  161.            }
  162.  
  163.            aiX += aiSpeedX;
  164.            aiY += aiSpeedY;
  165.  
  166.            // Update AI headlights position
  167.            aiTyre1X = aiX + 10;
  168.            aiTyre1Y = aiY + 5;
  169.            aiTyre2X = aiX + CAR_WIDTH - TYRE_SIZE - 10;
  170.            aiTyre2Y = aiY + 5;
  171.  
  172.            // Collision detection between player and AI cars            
  173.            // Define the corners of the player car
  174.            int playerCorner1X = playerX;
  175.            int playerCorner1Y = playerY;
  176.            int playerCorner2X = playerX + CAR_WIDTH;
  177.            int playerCorner2Y = playerY;
  178.            int playerCorner3X = playerX + CAR_WIDTH;
  179.            int playerCorner3Y = playerY + CAR_HEIGHT;
  180.            int playerCorner4X = playerX;
  181.            int playerCorner4Y = playerY + CAR_HEIGHT;
  182.  
  183.            // Define the corners of the AI car
  184.            int aiCorner1X = aiX;
  185.            int aiCorner1Y = aiY;
  186.            int aiCorner2X = aiX + CAR_WIDTH;
  187.            int aiCorner2Y = aiY;
  188.            int aiCorner3X = aiX + CAR_WIDTH;
  189.            int aiCorner3Y = aiY + CAR_HEIGHT;
  190.            int aiCorner4X = aiX;
  191.            int aiCorner4Y = aiY + CAR_HEIGHT;
  192.  
  193.            // Check if the player car is too close to the opponent car from behind
  194.            if (!godMode && playerY + CAR_HEIGHT > aiY &&
  195.                playerY < aiY + CAR_HEIGHT &&
  196.                playerX + CAR_WIDTH > aiX &&
  197.                playerX < aiX + CAR_WIDTH)
  198.            {
  199.                // Prevent the player car from moving forward
  200.                if (GetAsyncKeyState(VK_UP))
  201.                {
  202.                    playerX -= sin(playerAngle) * speed;
  203.                    playerY += cos(playerAngle) * speed;
  204.                }
  205.            }
  206.  
  207.            // Check if any of the player car's corners are inside the AI car
  208.             if (!godMode && ((playerCorner1X > aiCorner1X && playerCorner1X < aiCorner3X &&
  209.                 playerCorner1Y > aiCorner1Y && playerCorner1Y < aiCorner3Y) ||
  210.                 (playerCorner2X > aiCorner1X && playerCorner2X < aiCorner3X &&
  211.                     playerCorner2Y > aiCorner1Y && playerCorner2Y < aiCorner3Y) ||
  212.                 (playerCorner3X > aiCorner1X && playerCorner3X < aiCorner3X &&
  213.                     playerCorner3Y > aiCorner1Y && playerCorner3Y < aiCorner3Y) ||
  214.                 (playerCorner4X > aiCorner1X && playerCorner4X < aiCorner3X &&
  215.                     playerCorner4Y > aiCorner1Y && playerCorner4Y < aiCorner3Y) ||
  216.                 // Check if any of the AI car's corners are inside the player car
  217.                 (aiCorner1X > playerCorner1X && aiCorner1X < playerCorner3X &&
  218.                     aiCorner1Y > playerCorner1Y && aiCorner1Y < playerCorner3Y) ||
  219.                 (aiCorner2X > playerCorner1X && aiCorner2X < playerCorner3X &&
  220.                     aiCorner2Y > playerCorner1Y && aiCorner2Y < playerCorner3Y) ||
  221.                 (aiCorner3X > playerCorner1X && aiCorner3X < playerCorner3X &&
  222.                     aiCorner3Y > playerCorner1Y && aiCorner3Y < playerCorner3Y) ||
  223.                 (aiCorner4X > playerCorner1X && aiCorner4X < playerCorner3X &&
  224.                     aiCorner4Y > playerCorner1Y && aiCorner4Y < playerCorner3Y)))
  225.             {
  226.                 // Move the player car back to prevent collision
  227.                 if (GetAsyncKeyState(VK_UP))
  228.                 {
  229.                     playerX -= sin(playerAngle) * speed;
  230.                     playerY += cos(playerAngle) * speed;
  231.                 }
  232.                 if (GetAsyncKeyState(VK_DOWN))
  233.                 {
  234.                     playerX += sin(playerAngle) * speed;
  235.                     playerY -= cos(playerAngle) * speed;
  236.                 }
  237.  
  238.                 // Move the AI car back to prevent collision
  239.                 aiX -= aiSpeedX;
  240.                 aiY -= aiSpeedY;
  241.             }
  242.             /*if (playerX < aiX + CAR_WIDTH &&
  243.                 playerX + CAR_WIDTH > aiX &&
  244.                 playerY < aiY + CAR_HEIGHT &&
  245.                 playerY + CAR_HEIGHT > aiY)
  246.             {
  247.                 // Move the player car back to prevent collision
  248.                 if (GetAsyncKeyState(VK_UP))
  249.                 {
  250.                     playerX -= sin(playerAngle) * speed;
  251.                     playerY += cos(playerAngle) * speed;
  252.                 }
  253.                 if (GetAsyncKeyState(VK_DOWN))
  254.                 {
  255.                     playerX += sin(playerAngle) * speed;
  256.                     playerY -= cos(playerAngle) * speed;
  257.                 }
  258.             }*/
  259.             /*if (playerX < aiX + CAR_WIDTH &&
  260.                 playerX + CAR_WIDTH > aiX &&
  261.                 playerY < aiY + CAR_HEIGHT &&
  262.                 playerY + CAR_HEIGHT > aiY)
  263.             {
  264.                 // Handle collision (e.g., game over)
  265.                 //gameOver = true;
  266.             }*/
  267.  
  268.             // Win conditions
  269.                         // Victory conditions commented out
  270.             /*if (playerX > WIDTH - ROAD_WIDTH - CAR_WIDTH && playerY < ROAD_WIDTH)
  271.             {
  272.                 gameOver = true;
  273.                 playerWon = true;
  274.             }
  275.             if (aiX > WIDTH - ROAD_WIDTH - CAR_WIDTH && aiY < ROAD_WIDTH)
  276.             {
  277.                 gameOver = true;
  278.                 playerWon = false;
  279.             }*/
  280.  
  281.             InvalidateRect(hWnd, NULL, FALSE);
  282.         }
  283.         break;
  284.     case WM_PAINT:
  285.     {
  286.         PAINTSTRUCT ps;
  287.         HDC hdc = BeginPaint(hWnd, &ps);
  288.  
  289.         // Create memory DC and bitmap for double buffering
  290.         HDC memDC = CreateCompatibleDC(hdc);
  291.         HBITMAP memBitmap = CreateCompatibleBitmap(hdc, WIDTH, HEIGHT);
  292.         HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
  293.  
  294.         // Clear background
  295.         //HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  296.         HBRUSH lightGreenBrush = CreateSolidBrush(RGB(144, 238, 144)); // Light green color
  297.         RECT rect = { 0, 0, WIDTH, HEIGHT };
  298.         FillRect(memDC, &rect, lightGreenBrush);
  299.         //FillRect(memDC, &rect, whiteBrush);
  300.         DeleteObject(lightGreenBrush);
  301.         //DeleteObject(whiteBrush);
  302.  
  303.         // Draw roads (black rectangles)
  304.         HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
  305.         // Vertical road
  306.         RECT verticalRoad = { 0, 0, ROAD_WIDTH, HEIGHT };
  307.         FillRect(memDC, &verticalRoad, blackBrush);
  308.         // Horizontal road (twice as tall)
  309.         RECT horizontalRoad = { 0, 0, WIDTH, ROAD_WIDTH * 2 };
  310.         FillRect(memDC, &horizontalRoad, blackBrush);
  311.         DeleteObject(blackBrush);
  312.  
  313.         // Draw yellow road strips
  314.         HBRUSH yellowBrush = CreateSolidBrush(RGB(255, 255, 0));
  315.         SelectObject(memDC, yellowBrush);
  316.         // Vertical road strips
  317.         for (int y = 0; y < HEIGHT; y += 80) {
  318.             Rectangle(memDC, ROAD_WIDTH / 2 - 5, y, ROAD_WIDTH / 2 + 5, y + 40);
  319.         }
  320.         // Horizontal road strips
  321.         for (int x = 0; x < WIDTH; x += 80) {
  322.             Rectangle(memDC, x, ROAD_WIDTH - 5, x + 40, ROAD_WIDTH + 5);
  323.         }
  324.         DeleteObject(yellowBrush);
  325.  
  326.         // Draw player car (red rectangle)
  327.         HBRUSH redBrush = CreateSolidBrush(RGB(255, 0, 0));
  328.         SelectObject(memDC, redBrush);
  329.  
  330.         // Save the current graphics state
  331.         int savedDC = SaveDC(memDC);
  332.  
  333.         // Set up the transformation matrix for rotation
  334.         XFORM xform;
  335.         SetGraphicsMode(memDC, GM_ADVANCED);
  336.         xform.eM11 = (FLOAT)cos(playerAngle);
  337.         xform.eM12 = (FLOAT)sin(playerAngle);
  338.         xform.eM21 = (FLOAT)-sin(playerAngle);
  339.         xform.eM22 = (FLOAT)cos(playerAngle);
  340.         xform.eDx = (FLOAT)playerX + CAR_WIDTH / 2;
  341.         xform.eDy = (FLOAT)playerY + CAR_HEIGHT / 2;
  342.         SetWorldTransform(memDC, &xform);
  343.  
  344.         // Draw the rotated rectangle
  345.         Rectangle(memDC, -CAR_WIDTH / 2, -CAR_HEIGHT / 2, CAR_WIDTH / 2, CAR_HEIGHT / 2);
  346.  
  347.         // Draw headlights (white circles)
  348.         HBRUSH headlightBrush = CreateSolidBrush(RGB(255, 255, 255));
  349.         SelectObject(memDC, headlightBrush);
  350.         Ellipse(memDC, -CAR_WIDTH / 2 + 10, -CAR_HEIGHT / 2 + 5,
  351.             -CAR_WIDTH / 2 + 20, -CAR_HEIGHT / 2 + 15);
  352.         Ellipse(memDC, CAR_WIDTH / 2 - 20, -CAR_HEIGHT / 2 + 5,
  353.             CAR_WIDTH / 2 - 10, -CAR_HEIGHT / 2 + 15);
  354.         DeleteObject(headlightBrush);
  355.  
  356.         // Restore the original graphics state
  357.         RestoreDC(memDC, savedDC);
  358.  
  359.         DeleteObject(redBrush);
  360.  
  361.         // Draw AI car (blue rectangle)
  362.         HBRUSH blueBrush = CreateSolidBrush(RGB(0, 0, 255));
  363.         SelectObject(memDC, blueBrush);
  364.  
  365.         // Save the current graphics state for AI car
  366.         savedDC = SaveDC(memDC);
  367.  
  368.         // Set up the transformation matrix for AI car rotation
  369.         SetGraphicsMode(memDC, GM_ADVANCED);
  370.         xform.eM11 = (FLOAT)cos(aiAngle);
  371.         xform.eM12 = (FLOAT)sin(aiAngle);
  372.         xform.eM21 = (FLOAT)-sin(aiAngle);
  373.         xform.eM22 = (FLOAT)cos(aiAngle);
  374.         xform.eDx = (FLOAT)aiX + CAR_WIDTH / 2;
  375.         xform.eDy = (FLOAT)aiY + CAR_HEIGHT / 2;
  376.         SetWorldTransform(memDC, &xform);
  377.  
  378.         // Draw the rotated AI car
  379.         Rectangle(memDC, -CAR_WIDTH / 2, -CAR_HEIGHT / 2, CAR_WIDTH / 2, CAR_HEIGHT / 2);
  380.  
  381.         // Draw AI headlights
  382.         headlightBrush = CreateSolidBrush(RGB(255, 255, 255));
  383.         SelectObject(memDC, headlightBrush);
  384.         Ellipse(memDC, -CAR_WIDTH / 2 + 10, -CAR_HEIGHT / 2 + 5,
  385.             -CAR_WIDTH / 2 + 20, -CAR_HEIGHT / 2 + 15);
  386.         Ellipse(memDC, CAR_WIDTH / 2 - 20, -CAR_HEIGHT / 2 + 5,
  387.             CAR_WIDTH / 2 - 10, -CAR_HEIGHT / 2 + 15);
  388.         DeleteObject(headlightBrush);
  389.  
  390.         // Restore the original graphics state
  391.         RestoreDC(memDC, savedDC);
  392.  
  393.         DeleteObject(blueBrush);
  394.  
  395.         // Draw countdown timer if game hasn't started
  396.         if (!gameStarted)
  397.         {
  398.             char timerText[10];
  399.             sprintf_s(timerText, "%d", timer / 10);
  400.             SetTextColor(memDC, RGB(255, 0, 0));
  401.             SetBkMode(memDC, TRANSPARENT);
  402.             TextOutA(memDC, WIDTH / 2 - 10, HEIGHT / 2 - 10, timerText, strlen(timerText));
  403.         }
  404.  
  405.         // Draw God Mode text indicator
  406.         if (godMode)
  407.         {
  408.             SetTextColor(memDC, RGB(255, 0, 0));
  409.             SetBkMode(memDC, TRANSPARENT);
  410.             TextOutA(memDC, 10, 10, "God Mode ON", 10);
  411.         }
  412.  
  413.         // Copy from memory DC to screen
  414.         BitBlt(hdc, 0, 0, WIDTH, HEIGHT, memDC, 0, 0, SRCCOPY);
  415.  
  416.         // Clean up
  417.         SelectObject(memDC, oldBitmap);
  418.         DeleteObject(memBitmap);
  419.         DeleteDC(memDC);
  420.  
  421.         EndPaint(hWnd, &ps);
  422.         break;
  423.     }
  424.     case WM_DESTROY:
  425.         KillTimer(hWnd, 1);
  426.         PostQuitMessage(0);
  427.         break;
  428.     case WM_KEYDOWN:
  429.         if (wParam == VK_F1)
  430.         {
  431.             MessageBoxW(hWnd, L"2D Racing Game 3.0 Programmed in C++ Win32 API (491 lines of code) by Entisoft Software (c) Evans Thorpemorton", L"About", MB_OK | MB_ICONINFORMATION); // orig 395 lines
  432.         }
  433.         //break;
  434.         if (wParam == VK_ESCAPE)
  435.         {
  436.             PostQuitMessage(0);
  437.         }
  438.         break;
  439.     default:
  440.         return DefWindowProc(hWnd, message, wParam, lParam);
  441.     }
  442.     return 0;
  443. }
  444.  
  445. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  446. {
  447.     // Register window class
  448.     WNDCLASSEX wc = { 0 };
  449.     wc.cbSize = sizeof(WNDCLASSEX);
  450.     wc.style = CS_HREDRAW | CS_VREDRAW;
  451.     wc.lpfnWndProc = WndProc;
  452.     wc.cbClsExtra = 0;
  453.     wc.cbWndExtra = 0;
  454.     wc.hInstance = hInstance;
  455.     wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));        // Modified line
  456.     //wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  457.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  458.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  459.     wc.lpszMenuName = NULL;
  460.     wc.lpszClassName = L"RacingGame";
  461.     wc.hIconSm = (HICON)LoadImage(hInstance,                           // Modified line
  462.         MAKEINTRESOURCE(IDI_ICON1),           // Modified line
  463.         IMAGE_ICON,                           // Modified line
  464.         16,                                   // Modified line
  465.         16,                                   // Modified line
  466.         LR_DEFAULTCOLOR);                     // Modified line
  467.     //wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  468.     RegisterClassEx(&wc);
  469.  
  470.     // Calculate the position to center the window
  471.     int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  472.     int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  473.     int windowX = (screenWidth - WIDTH) / 2;
  474.     int windowY = (screenHeight - HEIGHT) / 2;
  475.  
  476.     // Create window
  477.     HWND hWnd = CreateWindowEx(0, L"RacingGame", L"Racing Game (ArrowKeys=Move G=GodMode)", WS_OVERLAPPEDWINDOW, windowX, windowY, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL);
  478.  
  479.     // Show window
  480.     //ShowWindow(hWnd, nCmdShow);
  481.     ShowWindow(hWnd, SW_SHOWMAXIMIZED);
  482.  
  483.     // Main loop
  484.     MSG msg = { 0 };
  485.     while (GetMessage(&msg, NULL, 0, 0))
  486.     {
  487.         TranslateMessage(&msg);
  488.         DispatchMessage(&msg);
  489.     }
  490.  
  491.     return 0;
  492. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement