Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <windows.h>
- #include <vector>
- #include <cmath>
- #include <ctime>
- #include <algorithm> // Include this header for std::min and std::max
- #include "resource.h"
- #define WIN_WIDTH 800
- #define WIN_HEIGHT 600
- // Add with other global variables
- bool keyStates[256] = { false }; // Track key states
- bool godMode = false; // Track God Mode state
- bool paused = false; // Track paused state
- LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
- void DrawTriangle(HDC hdc, POINT pts[], int x, int y, double angle);
- void DrawAsteroid(HDC hdc, POINT pts[], int x, int y, double angle);
- bool CheckCollision(POINT player[], POINT asteroid[], int px, int py, int ax, int ay);
- void MoveAsteroids();
- void ShootBullet();
- void DrawBullet(HDC hdc, int x, int y);
- bool CheckBulletCollision(int bx, int by);
- bool DoLinesIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);
- int Direction(int x1, int y1, int x2, int y2, int x3, int y3);
- bool OnSegment(int x1, int y1, int x2, int y2, int x3, int y3);
- bool PointInPolygon(int px, int py, POINT polygon[], int ox, int oy);
- void GenerateAsteroids();
- void SpawnNewAsteroid();
- void UpdatePlayerMovement();
- struct Asteroid {
- int x, y;
- double angle;
- POINT shape[8];
- };
- struct Bullet {
- int x, y;
- double angle;
- };
- std::vector<Asteroid> asteroids;
- std::vector<Bullet> bullets;
- POINT player[3] = { {0, -30}, {20, 20}, {-20, 20} };
- int playerX = WIN_WIDTH / 2, playerY = WIN_HEIGHT / 2;
- double playerAngle = 0;
- int score = 0;
- int lives = 3;
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
- WNDCLASSEX wcex;
- HWND hwnd;
- MSG msg;
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = CS_HREDRAW | CS_VREDRAW;
- wcex.lpfnWndProc = WndProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = hInstance;
- wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- wcex.lpszMenuName = NULL;
- wcex.lpszClassName = TEXT("Asteroids");
- wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));
- //wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
- RegisterClassEx(&wcex);
- // Get the screen dimensions
- int screenWidth = GetSystemMetrics(SM_CXSCREEN);
- int screenHeight = GetSystemMetrics(SM_CYSCREEN);
- // Calculate the window position to center it
- int windowWidth = WIN_WIDTH + 16;
- int windowHeight = WIN_HEIGHT + 39;
- int posX = (screenWidth - windowWidth) / 2;
- int posY = (screenHeight - windowHeight) / 2;
- hwnd = CreateWindow(TEXT("Asteroids"), TEXT("Asteroids ArrowKeys=Controls Space=Shoot F1=GodMode P=Pause F2=About Escape=Quit"), WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
- posX, posY, windowWidth + 16, windowHeight + 39, NULL, NULL, hInstance, NULL);
- ShowWindow(hwnd, SW_SHOW); // Instead of ShowWindow(hwnd, nCmdShow);
- UpdateWindow(hwnd);
- srand(static_cast<unsigned int>(time(0)));
- GenerateAsteroids();
- LARGE_INTEGER freq, startTime, endTime;
- QueryPerformanceFrequency(&freq);
- QueryPerformanceCounter(&startTime);
- // Main game loop
- while (true) {
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
- if (msg.message == WM_QUIT) break;
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- else {
- // Only update game state if not paused
- if (!paused) {
- UpdatePlayerMovement();
- for (auto& ast : asteroids) {
- if (!godMode && CheckCollision(player, ast.shape, playerX, playerY, ast.x, ast.y)) {
- lives--;
- if (lives <= 0) {
- MessageBox(hwnd, TEXT("Game Over!"), TEXT("Asteroids"), MB_OK);
- PostQuitMessage(0);
- }
- playerX = WIN_WIDTH / 2;
- playerY = WIN_HEIGHT / 2;
- playerAngle = 0;
- memset(keyStates, 0, sizeof(keyStates));
- }
- }
- if (rand() % 100 < 2) {
- SpawnNewAsteroid();
- }
- MoveAsteroids();
- for (auto it = bullets.begin(); it != bullets.end();) {
- it->x += 10 * cos(it->angle * 3.14159 / 180);
- it->y += 10 * sin(it->angle * 3.14159 / 180);
- if (CheckBulletCollision(it->x, it->y)) {
- it = bullets.erase(it);
- }
- else {
- ++it;
- }
- }
- }
- RECT clientRect;
- GetClientRect(hwnd, &clientRect);
- InvalidateRect(hwnd, &clientRect, TRUE); // Invalidate with TRUE
- }
- QueryPerformanceCounter(&endTime);
- double elapsedTime = (endTime.QuadPart - startTime.QuadPart) / (double)freq.QuadPart;
- if (elapsedTime < 0.016) { // Cap at approximately 60 FPS
- Sleep((DWORD)((0.016 - elapsedTime) * 1000));
- }
- QueryPerformanceCounter(&startTime); // Reset for next frame
- }
- return (int)msg.wParam;
- }
- LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
- static HDC hdcMem;
- static HBITMAP hbmMem;
- static HBITMAP hbmOld;
- static HBRUSH hbrBkGnd;
- static RECT rect;
- PAINTSTRUCT ps;
- static TCHAR scoreText[50];
- switch (msg) {
- case WM_CREATE:
- GetClientRect(hwnd, &rect);
- hdcMem = CreateCompatibleDC(NULL);
- hbmMem = CreateCompatibleBitmap(GetDC(hwnd), rect.right, rect.bottom);
- hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);
- hbrBkGnd = (HBRUSH)GetStockObject(BLACK_BRUSH); // Use black background brush
- SelectObject(hdcMem, hbrBkGnd); // Select background brush here
- ValidateRect(hwnd, &rect); // Validate client area to prevent initial WM_PAINT
- break;
- case WM_PAINT: {
- HDC hdc = BeginPaint(hwnd, &ps);
- FillRect(hdcMem, &rect, hbrBkGnd);
- DrawTriangle(hdcMem, player, playerX, playerY, playerAngle);
- for (auto& ast : asteroids) {
- DrawAsteroid(hdcMem, ast.shape, ast.x, ast.y, ast.angle);
- }
- for (auto& bullet : bullets) {
- DrawBullet(hdcMem, bullet.x, bullet.y);
- }
- SetTextColor(hdcMem, RGB(255, 255, 255));
- SetBkMode(hdcMem, TRANSPARENT);
- wsprintf(scoreText, TEXT("Score: %d Lives: %d"), score, lives);
- TextOut(hdcMem, 10, 10, scoreText, lstrlen(scoreText));
- if (godMode) {
- TextOut(hdcMem, WIN_WIDTH / 2 - 50, 10, TEXT("God Mode"), 8);
- }
- if (paused) {
- TextOut(hdcMem, WIN_WIDTH / 2 - 50, WIN_HEIGHT / 2 - 10, TEXT("Game Paused"), 10);
- }
- BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcMem, 0, 0, SRCCOPY);
- EndPaint(hwnd, &ps);
- break;
- }
- case WM_KEYDOWN:
- keyStates[wParam] = true;
- if (wParam == VK_F1) {
- godMode = !godMode; // Toggle God Mode
- }
- else if (wParam == 'P') {
- paused = !paused; // Toggle Pause
- }
- if (wParam == VK_ESCAPE) {
- PostQuitMessage(0);
- return 0;
- }
- // Add this new code block
- else if (wParam == VK_F2) {
- MessageBox(hwnd, TEXT("Asteroids v10.8 Basic GDI-Based C++ Win32 Game (384 lines of code) by Entisoft Software (c) Evans Thorpemorton"), TEXT("About"), MB_OK | MB_ICONINFORMATION);
- }
- break;
- case WM_KEYUP:
- keyStates[wParam] = false;
- break;
- case WM_DESTROY:
- SelectObject(hdcMem, hbmOld);
- DeleteObject(hbrBkGnd); // Deselect and delete the brush here
- DeleteObject(hbmMem);
- DeleteDC(hdcMem);
- PostQuitMessage(0);
- break;
- default:
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
- return 0;
- }
- void DrawTriangle(HDC hdc, POINT pts[], int x, int y, double angle) {
- POINT rotated[3];
- for (int i = 0; i < 3; ++i) {
- rotated[i].x = pts[i].x * cos(angle * 3.14159 / 180) - pts[i].y * sin(angle * 3.14159 / 180);
- rotated[i].y = pts[i].x * sin(angle * 3.14159 / 180) + pts[i].y * cos(angle * 3.14159 / 180);
- rotated[i].x += x;
- rotated[i].y += y;
- }
- // In DrawTriangle function, before Polygon call
- HPEN hotPinkPen = CreatePen(PS_SOLID, 1, RGB(255, 20, 147));
- HBRUSH hotPinkBrush = CreateSolidBrush(RGB(255, 20, 147));
- SelectObject(hdc, hotPinkPen);
- SelectObject(hdc, hotPinkBrush);
- Polygon(hdc, rotated, 3);
- DeleteObject(hotPinkPen);
- DeleteObject(hotPinkBrush);
- }
- void DrawAsteroid(HDC hdc, POINT pts[], int x, int y, double angle) {
- POINT rotated[8];
- for (int i = 0; i < 8; ++i) {
- rotated[i].x = pts[i].x * cos(angle * 3.14159 / 180) - pts[i].y * sin(angle * 3.14159 / 180);
- rotated[i].y = pts[i].x * sin(angle * 3.14159 / 180) + pts[i].y * cos(angle * 3.14159 / 180);
- rotated[i].x += x;
- rotated[i].y += y;
- }
- // In DrawAsteroid function, before Polygon call
- HPEN goldPen = CreatePen(PS_SOLID, 1, RGB(255, 215, 0));
- HBRUSH goldBrush = CreateSolidBrush(RGB(255, 215, 0));
- SelectObject(hdc, goldPen);
- SelectObject(hdc, goldBrush);
- Polygon(hdc, rotated, 8);
- DeleteObject(goldPen);
- DeleteObject(goldBrush);
- }
- void UpdatePlayerMovement() {
- if (keyStates[VK_LEFT]) {
- playerAngle -= 5;
- }
- if (keyStates[VK_RIGHT]) {
- playerAngle += 5;
- }
- if (keyStates[VK_UP]) {
- playerX += 5 * cos((playerAngle - 90) * 3.14159 / 180);
- playerY += 5 * sin((playerAngle - 90) * 3.14159 / 180);
- }
- // Add to UpdatePlayerMovement() function
- if (keyStates[VK_DOWN]) {
- playerX -= 5 * cos((playerAngle - 90) * 3.14159 / 180);
- playerY -= 5 * sin((playerAngle - 90) * 3.14159 / 180);
- }
- // Add to UpdatePlayerMovement() function
- static int shootCooldown = 0;
- if (keyStates[VK_SPACE] && shootCooldown == 0) {
- ShootBullet();
- shootCooldown = 10; // Adjust this value to control firing rate
- }
- if (shootCooldown > 0) {
- shootCooldown--;
- }
- // Wrap around screen
- if (playerX < 0) playerX = WIN_WIDTH;
- if (playerX > WIN_WIDTH) playerX = 0;
- if (playerY < 0) playerY = WIN_HEIGHT;
- if (playerY > WIN_HEIGHT) playerY = 0;
- }
- bool CheckCollision(POINT player[], POINT asteroid[], int px, int py, int ax, int ay) {
- for (int i = 0; i < 3; ++i) {
- int px1 = player[i].x + px;
- int py1 = player[i].y + py;
- int px2 = player[(i + 1) % 3].x + px;
- int py2 = player[(i + 1) % 3].y + py;
- for (int j = 0; j < 8; ++j) {
- int ax1 = asteroid[j].x + ax;
- int ay1 = asteroid[j].y + ay;
- int ax2 = asteroid[(j + 1) % 8].x + ax;
- int ay2 = asteroid[(j + 1) % 8].y + ay;
- // Check if the line segments intersect
- if (DoLinesIntersect(px1, py1, px2, py2, ax1, ay1, ax2, ay2)) {
- return true;
- }
- }
- }
- return false;
- }
- bool DoLinesIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) {
- // Calculate the direction of the lines
- int d1 = Direction(x3, y3, x4, y4, x1, y1);
- int d2 = Direction(x3, y3, x4, y4, x2, y2);
- int d3 = Direction(x1, y1, x2, y2, x3, y3);
- int d4 = Direction(x1, y1, x2, y2, x4, y4);
- // Check if the lines intersect
- if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
- return true;
- }
- // Check for collinear points
- if (d1 == 0 && OnSegment(x3, y3, x4, y4, x1, y1)) return true;
- if (d2 == 0 && OnSegment(x3, y3, x4, y4, x2, y2)) return true;
- if (d3 == 0 && OnSegment(x1, y1, x2, y2, x3, y3)) return true;
- if (d4 == 0 && OnSegment(x1, y1, x2, y2, x4, y4)) return true;
- return false;
- }
- int Direction(int x1, int y1, int x2, int y2, int x3, int y3) {
- return (x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1);
- }
- bool OnSegment(int x1, int y1, int x2, int y2, int x3, int y3) {
- int minX = x1 < x2 ? x1 : x2;
- int maxX = x1 > x2 ? x1 : x2;
- int minY = y1 < y2 ? y1 : y2;
- int maxY = y1 > y2 ? y1 : y2;
- if (minX <= x3 && x3 <= maxX && minY <= y3 && y3 <= maxY) {
- return true;
- }
- return false;
- }
- void MoveAsteroids() {
- for (auto& ast : asteroids) {
- ast.x += 2 * cos(ast.angle * 3.14159 / 180);
- ast.y += 2 * sin(ast.angle * 3.14159 / 180);
- // Wrap around screen
- if (ast.x < 0) ast.x = WIN_WIDTH;
- if (ast.x > WIN_WIDTH) ast.x = 0;
- if (ast.y < 0) ast.y = WIN_HEIGHT;
- if (ast.y > WIN_HEIGHT) ast.y = 0;
- }
- }
- void ShootBullet() {
- Bullet bullet;
- // Calculate the tip of the triangle (point[0] is the top vertex)
- bullet.x = playerX + player[0].x * cos(playerAngle * 3.14159 / 180)
- - player[0].y * sin(playerAngle * 3.14159 / 180);
- bullet.y = playerY + player[0].x * sin(playerAngle * 3.14159 / 180)
- + player[0].y * cos(playerAngle * 3.14159 / 180);
- // Adjust the bullet angle to match the ship's orientation
- bullet.angle = playerAngle - 90; // Subtract 90 degrees to align with the ship's nose
- bullets.push_back(bullet);
- }
- // Modified DrawBullet function for green bullets
- void DrawBullet(HDC hdc, int x, int y) {
- HPEN greenPen = CreatePen(PS_SOLID, 1, RGB(0, 255, 0)); // Bright green
- HBRUSH greenBrush = CreateSolidBrush(RGB(0, 255, 0)); // Bright green
- SelectObject(hdc, greenPen);
- SelectObject(hdc, greenBrush);
- Ellipse(hdc, x - 4, y - 4, x + 4, y + 4);
- DeleteObject(greenPen);
- DeleteObject(greenBrush);
- }
- bool CheckBulletCollision(int bx, int by) {
- for (auto it = asteroids.begin(); it != asteroids.end();) {
- if (PointInPolygon(bx, by, it->shape, it->x, it->y)) {
- it = asteroids.erase(it);
- score += 10;
- return true;
- }
- else {
- ++it;
- }
- }
- return false;
- }
- bool PointInPolygon(int px, int py, POINT polygon[], int ox, int oy) {
- int i, j, nvert = 8;
- bool c = false;
- for (i = 0, j = nvert - 1; i < nvert; j = i++) {
- int polyX1 = polygon[i].x + ox;
- int polyY1 = polygon[i].y + oy;
- int polyX2 = polygon[j].x + ox;
- int polyY2 = polygon[j].y + oy;
- if (((polyY1 > py) != (polyY2 > py)) &&
- (px < (polyX2 - polyX1) * (py - polyY1) / (polyY2 - polyY1) + polyX1)) {
- c = !c;
- }
- }
- return c;
- }
- void GenerateAsteroids() {
- for (int i = 0; i < 5; ++i) {
- Asteroid ast;
- ast.x = rand() % WIN_WIDTH;
- ast.y = rand() % WIN_HEIGHT;
- ast.angle = rand() % 360;
- for (int j = 0; j < 8; ++j) {
- double angle = j * 45 * 3.14159 / 180;
- ast.shape[j].x = (rand() % 20 + 10) * cos(angle);
- ast.shape[j].y = (rand() % 20 + 10) * sin(angle);
- }
- asteroids.push_back(ast);
- }
- }
- void SpawnNewAsteroid() {
- Asteroid ast;
- // Randomly choose a side of the screen to spawn from
- int side = rand() % 4;
- switch (side) {
- case 0: // Top
- ast.x = rand() % WIN_WIDTH;
- ast.y = -30;
- break;
- case 1: // Right
- ast.x = WIN_WIDTH + 30;
- ast.y = rand() % WIN_HEIGHT;
- break;
- case 2: // Bottom
- ast.x = rand() % WIN_WIDTH;
- ast.y = WIN_HEIGHT + 30;
- break;
- case 3: // Left
- ast.x = -30;
- ast.y = rand() % WIN_HEIGHT;
- break;
- }
- ast.angle = rand() % 360;
- for (int j = 0; j < 8; ++j) {
- double angle = j * 45 * 3.14159 / 180;
- ast.shape[j].x = (rand() % 20 + 10) * cos(angle);
- ast.shape[j].y = (rand() % 20 + 10) * sin(angle);
- }
- asteroids.push_back(ast);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement