Untitled
unknown
c_cpp
a year ago
18 kB
1
Indexable
Never
#include <SDL2/SDL.h> #include <stdbool.h> #include <SDL2/SDL_image.h> #include <stdio.h> // Screen dimensions const int SCREEN_WIDTH = 1200; const int SCREEN_HEIGHT = 600; // Player dimensions const int PLAYER_WIDTH = 50; const int PLAYER_HEIGHT = 100; // Digit dimensions const int DIGIT_WIDTH = 30; const int DIGIT_HEIGHT = 50; // Number of digits in the score const int numDigits = 0; // Player 1 initial position int player1_x = 100; int player1_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90; int player1_velocity_y = 0; int player1_remaining_jumps = 2; // Player 2 initial position int player2_x = 1050; int player2_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90; int player2_velocity_y = 0; int player2_remaining_jumps = 2; // Player 1 and 2 scores int player1_score = 0; int player2_score = 0; // Jumping variables bool player1_jumping = false; bool player2_jumping = false; const int JUMP_HEIGHT = 10000; // Player speeds const int PLAYER_SPEED = 4; // Add gravity and friction constants const double GRAVITY = 0.2; // Adjust as needed const double FRICTION = 0.98; // Adjust as needed // Ball dimensions const int BALL_SIZE = 40; // Ball initial position and velocity int ball_x = SCREEN_WIDTH / 2 - BALL_SIZE / 2; int ball_y = SCREEN_HEIGHT / 2 - BALL_SIZE / 2; double ball_velocity_x = 3.0; // Use double for smoother movement double ball_velocity_y = 1.0; // Goal dimensions and positions const int GOAL_WIDTH = 20; const int GOAL_HEIGHT = 190; // Goal Bar dimensions and positions const int GOAL_BAR_WIDTH = 50; const int GOAL_BAR_HEIGHT = 20; int left_goal_x = 50; // Update left goal position int left_goal_y = (SCREEN_HEIGHT - GOAL_HEIGHT) - 100; int right_goal_x = SCREEN_WIDTH - GOAL_WIDTH - 50; // Update right goal position int right_goal_y = SCREEN_HEIGHT - GOAL_HEIGHT - 100; const int INVISIBLE_FLOOR = SCREEN_HEIGHT - 90; // Adjust the height as needed // Background image SDL_Texture *backgroundTexture = NULL; // Goal Post image SDL_Texture *goalPostTexture = NULL; // Load the ball image and create a texture for it SDL_Texture *ballTexture = NULL; // Load the fan image and create a texture for it SDL_Texture *fanTexture = NULL; // Load digit images from 0 to 9 SDL_Texture *digitTextures[10]; // Function to reset the game void resetGame() { // Reset player positions player1_x = 100; player1_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90; player2_x = 1050; player2_y = SCREEN_HEIGHT - PLAYER_HEIGHT - 90; // Reset ball position and velocity to the middle of the screen ball_x = SCREEN_WIDTH / 2 - BALL_SIZE / 2; ball_y = SCREEN_HEIGHT / 2 - BALL_SIZE / 2; ball_velocity_x = 3.0; ball_velocity_y = 1.0; } // Initialize SDL and create a window bool init(SDL_Window **window, SDL_Renderer **renderer) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); return false; } *window = SDL_CreateWindow("Two Players", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (*window == NULL) { printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); return false; } *renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED); if (*renderer == NULL) { printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError()); return false; } return true; } // Load background image bool loadBackground(SDL_Renderer *renderer) { SDL_Surface *backgroundSurface = IMG_Load("background.jpg"); if (backgroundSurface == NULL) { printf("Unable to load background image! SDL_Image Error: %s\n", IMG_GetError()); return false; } backgroundTexture = SDL_CreateTextureFromSurface(renderer, backgroundSurface); if (backgroundTexture == NULL) { printf("Unable to create texture from background image! SDL Error: %s\n", SDL_GetError()); return false; } SDL_FreeSurface(backgroundSurface); return true; } // Load PNG image and create texture bool loadGoalPost(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture) { SDL_Surface *imageSurface = IMG_Load("goalPost.png"); if (imageSurface == NULL) { printf("Unable to load PNG image! SDL_Image Error: %s\n", IMG_GetError()); return false; } *texture = SDL_CreateTextureFromSurface(renderer, imageSurface); if (*texture == NULL) { printf("Unable to create texture from PNG image! SDL Error: %s\n", SDL_GetError()); return false; } SDL_FreeSurface(imageSurface); return true; } // Load fan image and create texture bool loadFanImage(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture) { SDL_Surface *imageSurface = IMG_Load("fan.png"); if (imageSurface == NULL) { printf("Unable to load PNG image! SDL_Image Error: %s\n", IMG_GetError()); return false; } *texture = SDL_CreateTextureFromSurface(renderer, imageSurface); if (*texture == NULL) { printf("Unable to create texture from PNG image! SDL Error: %s\n", SDL_GetError()); return false; } SDL_FreeSurface(imageSurface); return true; } // Load ball image and create texture bool loadBallImage(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture) { SDL_Surface *imageSurface = IMG_Load("Ball.png"); if (imageSurface == NULL) { printf("Unable to load PNG image! SDL_Image Error: %s\n", IMG_GetError()); return false; } *texture = SDL_CreateTextureFromSurface(renderer, imageSurface); if (*texture == NULL) { printf("Unable to create texture from PNG image! SDL Error: %s\n", SDL_GetError()); return false; } SDL_FreeSurface(imageSurface); return true; } // Load digit images and create textures bool loadDigitImage(SDL_Renderer *renderer, const char *imagePath, SDL_Texture **texture, int digit) { char digitPath[20]; sprintf(digitPath, "number/%d.png", digit); SDL_Surface *imageSurface = IMG_Load(digitPath); if (imageSurface == NULL) { printf("Unable to load PNG image! SDL_Image Error: %s\n", IMG_GetError()); return false; } *texture = SDL_CreateTextureFromSurface(renderer, imageSurface); if (*texture == NULL) { printf("Unable to create texture from PNG image! SDL Error: %s\n", SDL_GetError()); return false; } SDL_FreeSurface(imageSurface); return true; } // Render the score void renderScore(SDL_Renderer *renderer, SDL_Texture **digitTextures, int score, int x, int y) { int tempScore = score; int numDigits = 0; // Count the number of digits in the score do { numDigits++; tempScore /= 10; } while (tempScore > 0); // Render the score digits from right to left tempScore = score; for (int i = numDigits - 1; i >= 0; i--) { int digit = tempScore % 10; SDL_Rect digitRect = {x + i * DIGIT_WIDTH, y, DIGIT_WIDTH, DIGIT_HEIGHT}; SDL_RenderCopy(renderer, digitTextures[digit], NULL, &digitRect); tempScore /= 10; } } // Draw the players and background on the screen void draw(SDL_Renderer *renderer) { // Clear the screen SDL_RenderClear(renderer); // Draw the background SDL_RenderCopy(renderer, backgroundTexture, NULL, NULL); // Draw the fans SDL_RenderCopy(renderer, fanTexture, NULL, NULL); // Draw Player 1 score renderScore(renderer, digitTextures, player1_score, 50, 50); // Draw Player 2 score renderScore(renderer, digitTextures, player2_score, SCREEN_WIDTH - 100 - numDigits * DIGIT_WIDTH, 50); // Draw Player 1 (red rectangle) SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_Rect player1Rect = {player1_x, player1_y, PLAYER_WIDTH, PLAYER_HEIGHT}; SDL_RenderFillRect(renderer, &player1Rect); // Draw Player 2 (blue rectangle) SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); SDL_Rect player2Rect = {player2_x, player2_y, PLAYER_WIDTH, PLAYER_HEIGHT}; SDL_RenderFillRect(renderer, &player2Rect); // Draw the ball (yellow circle) SDL_Rect ballRect = {ball_x, ball_y, BALL_SIZE, BALL_SIZE}; SDL_RenderCopy(renderer, ballTexture, NULL, &ballRect); // Draw the PNG image (on top of the background) SDL_RenderCopy(renderer, goalPostTexture, NULL, NULL); // Update the screen SDL_RenderPresent(renderer); } // Player collisions bool checkCollision(int x1, int y1, int x2, int y2, int width, int height) { return (x1 < x2 + width && x1 + PLAYER_WIDTH > x2 && y1 < y2 + height && y1 + PLAYER_HEIGHT > y2); } // Function to handle ball-wall collisions void handleBallWallCollision() { if (ball_x <= 0 || ball_x + BALL_SIZE >= SCREEN_WIDTH) { ball_velocity_x = -ball_velocity_x; } if (ball_y <= 0 || ball_y + BALL_SIZE >= SCREEN_HEIGHT) { ball_velocity_y = -ball_velocity_y; } } bool checkBallPlayerCollision(int player_x, int player_y) { return (ball_x < player_x + PLAYER_WIDTH && ball_x + BALL_SIZE > player_x && ball_y < player_y + PLAYER_HEIGHT && ball_y + BALL_SIZE > player_y); } // Function to handle ball-goal collisions void handleBallGoalCollision() { int ball_center_x = ball_x + BALL_SIZE / 2; int ball_center_y = ball_y + BALL_SIZE / 2; // Check if the ball's center crosses the left goal line if (ball_center_x <= left_goal_x + GOAL_WIDTH && ball_center_y >= left_goal_y && ball_center_y <= left_goal_y + GOAL_HEIGHT) { // Ball's center crossed the left goal line, player 2 scores printf("Player 2 scores!\n"); player2_score += 1; printf("Player 2: %d\n", player2_score); resetGame(); } // Check if the ball's center crosses the right goal line else if (ball_center_x >= right_goal_x && ball_center_y >= right_goal_y && ball_center_y <= right_goal_y + GOAL_HEIGHT) { // Ball's center crossed the right goal line, player 1 scores printf("Player 1 scores!\n"); player1_score += 1; printf("Player 1: %d\n", player1_score); resetGame(); } } // Function to update the ball's position void updateBallPosition() { ball_x += ball_velocity_x; ball_y += ball_velocity_y; // Apply gravity ball_velocity_y += GRAVITY; // Apply friction ball_velocity_x *= FRICTION; ball_velocity_y *= FRICTION; // Ensure the ball stays above the invisible floor if (ball_y + BALL_SIZE >= INVISIBLE_FLOOR) { ball_y = INVISIBLE_FLOOR - BALL_SIZE; // Reverse the ball's vertical velocity to bounce it off the floor ball_velocity_y = -ball_velocity_y * FRICTION; // Apply friction when bouncing } } int main(int argc, char *argv[]) { printf("Welcome to Head Soccer!\n"); SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; if (!init(&window, &renderer)) { return 1; } if (!loadBackground(renderer)) { return 1; } if (!loadBallImage(renderer, "Ball.png", &ballTexture)) { return 1; } if (!loadGoalPost(renderer, "goalPost.png", &goalPostTexture)) { return 1; } if (!loadFanImage(renderer, "fan.png", &fanTexture)) { return 1; } for (int i = 0; i < 10; i++) { char digitPath[20]; sprintf(digitPath, "number/%d.png", i); if (!loadDigitImage(renderer, digitPath, &digitTextures[i], i)) { return 1; } } bool quit = false; SDL_Event e; while (!quit) { while (SDL_PollEvent(&e) != 0) { if (e.type == SDL_QUIT) { quit = true; } if (e.type == SDL_KEYDOWN) { // Player 1 jump if (e.key.keysym.sym == SDLK_w) { if (player1_remaining_jumps > 0) { player1_jumping = true; player1_velocity_y = -20; player1_remaining_jumps--; } } // Player 2 jump if (e.key.keysym.sym == SDLK_UP) { if (player2_remaining_jumps > 0) { player2_jumping = true; player2_velocity_y = -20; player2_remaining_jumps--; } } } } if (player1_jumping) { player1_y += player1_velocity_y; player1_velocity_y += 1; // Ensure player 1 stays above the invisible floor if (player1_y >= INVISIBLE_FLOOR - PLAYER_HEIGHT) { player1_y = INVISIBLE_FLOOR - PLAYER_HEIGHT; player1_jumping = false; player1_remaining_jumps = 2; } } if (player2_jumping) { player2_y += player2_velocity_y; player2_velocity_y += 1; // Ensure player 2 stays above the invisible floor if (player2_y >= INVISIBLE_FLOOR - PLAYER_HEIGHT) { player2_y = INVISIBLE_FLOOR - PLAYER_HEIGHT; player2_jumping = false; player2_remaining_jumps = 2; } } const Uint8 *currentKeyStates = SDL_GetKeyboardState(NULL); if (checkCollision(player1_x, player1_y, player2_x, player2_y, PLAYER_WIDTH, PLAYER_HEIGHT)) { if (player1_x < player2_x) { player1_x--; player2_x++; } else { player1_x++; player2_x--; } } else { // resetGame; if (currentKeyStates[SDL_SCANCODE_ESCAPE]) { if (currentKeyStates[SDL_SCANCODE_R]) { resetGame(); } } // Player 1 movement if (currentKeyStates[SDL_SCANCODE_A]) { player1_x -= PLAYER_SPEED; } if (currentKeyStates[SDL_SCANCODE_D]) { player1_x += PLAYER_SPEED; } // Player 2 movement if (currentKeyStates[SDL_SCANCODE_LEFT]) { player2_x -= PLAYER_SPEED; } if (currentKeyStates[SDL_SCANCODE_RIGHT]) { player2_x += PLAYER_SPEED; } // Keep players within the screen boundaries if (player1_x < 0) { player1_x = 0; } if (player1_x > SCREEN_WIDTH - PLAYER_WIDTH) { player1_x = SCREEN_WIDTH - PLAYER_WIDTH; } if (player2_x < 0) { player2_x = 0; } if (player2_x > SCREEN_WIDTH - PLAYER_WIDTH) { player2_x = SCREEN_WIDTH - PLAYER_WIDTH; } } if (checkBallPlayerCollision(player1_x, player1_y) && checkBallPlayerCollision(player2_x, player2_y)) { ball_velocity_y = -ball_velocity_y; ball_y += ball_velocity_y; } else { // Check for collision with Player 1 if (checkBallPlayerCollision(player1_x, player1_y)) { // Calculate the direction of the collision int collisionDirection = (ball_x + BALL_SIZE / 2) - (player1_x + PLAYER_WIDTH / 2); // Adjust the ball's velocity based on the collision direction ball_velocity_x = collisionDirection / 5.0; // Use double for smoother adjustment ball_velocity_y = -ball_velocity_y; // Reverse the ball's vertical velocity // Move the ball slightly away from the player to avoid getting stuck ball_x += ball_velocity_x * 2.0; // Use double for smoother adjustment ball_y += ball_velocity_y; } // Check for collision with Player 2 if (checkBallPlayerCollision(player2_x, player2_y)) { // Calculate the direction of the collision int collisionDirection = (ball_x + BALL_SIZE / 2) - (player2_x + PLAYER_WIDTH / 2); // Adjust the ball's velocity based on the collision direction ball_velocity_x = collisionDirection / 5.0; // Use double for smoother adjustment ball_velocity_y = -ball_velocity_y; // Reverse the ball's vertical velocity // Move the ball slightly away from the player to avoid getting stuck ball_x += ball_velocity_x * 2.0; // Use double for smoother adjustment ball_y += ball_velocity_y; } } // Handle ball-goal collisions handleBallGoalCollision(); // Handle ball-wall collisions handleBallWallCollision(); // Update the ball's position updateBallPosition(); draw(renderer); } // Cleanup and exit SDL_DestroyTexture(backgroundTexture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }